Zum Inhalt springen

USART - Universal Synchronous and Asynchronous Receiver Transmitter

starlightViewModes.switchTo

In Datenverarbeitungsprogrammen ist es oft, wenn nicht sogar immer, notwendig, Daten zwischen Computern auszutauschen. Um diese Verbindung zwischen unserem ATmega328p Board und unserer Entwicklungsmaschine herzustellen, gibt es das USART (Universal Synchronous/Asynchronous Receiver Transmitter).

Theorie

Datenübertragung

Für die Datenübertragung braucht es zwei PINs, ein PIN zum Senden und ein PIN zum Empfangen von Daten. Dafür sind beim ATmega328p die PINs PD0 und PD1 reserviert. Wenn Sie das USART also verwenden möchten, achten Sie darauf, diese beiden PINs nicht gleichzeitig für andere Zwecke zu verwenden.

Konfiguration

Baud Rate

Damit das USART beim ATmega328p richtig funktioniert, muss man die Baud Rate auf 9600 setzen. Die Baud Rate gibt an, wie viele Bits pro Sekunde übertragen werden sollen. Dabei ist es wichtig, dass unsere Arduino Board und der andere Kommunikationspartner die gleiche Baud Rate verwenden.

UBRR0 = 103;

Für andere Baud Rate-Konfigurationen lesen Sie bitte Kapitel 19-11 im Datenblatt durch.

Senden aktivieren

Wenn Sie Daten senden möchten, müssen Sie dies aktivieren.

UCSR0B |= (1<<TXEN0);

Empfangen aktivieren

Für das Aktivieren für das Empfangen von Daten muss zusätzlich auch das Interrupt aktiviert werden, damit bei jedem hereinkommenden Zeichen diese getriggert wird.

UCSR0B |= (1<<RXEN0) | (1<<RXCIE0);

Größe der Bits setzen

Sender und Empfänger müssen definieren, wie viele Bits pro gesendetem Zeichen verwendet werden sollen. Je nachdem, welche Codierung (ASCII, UTF-8, UTF-16 …) verwendet wird, benötigen die Zeichen jeweils acht, 16 oder mehrere Bits.

Die meisten Encodings verwenden 8-bit:

UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);

Für andere Konfigurationen verwenden Sie die Tabelle 19-7 aus dem Datenblatt.

Code

Konfiguration

Meistens verwenden Sie diese Konfiguration um alles bezüglich USART richtig zu konfigurieren:

UBRR0 = 103;
UCSR0B |= (1<<TXEN0) | (1<<RXEN0) | (1<<RXCIE0);
UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);

Daten senden

Um die Implementierung zu erleichtern, verwendet man Pointer. Dies ist die Methode für einzelne ASCII-Zeichen.

void write_char(char str) {
while (!(UCSR0A & (1<<UDRE0)));
UDR0=str;
}

Für ganze Zeichenketten gibt es diese einfache Methode:

void write_string(char *arr) {
while(*arr) {
while (!(UCSR0A & (1<<UDRE0)));
UDR0=*arr++;
}
}

Daten empfangen

Während man ganze Zeichenketten schicken kann, kann man immer nur einzelne Zeichen empfangen.

ISR(USART_RX_vect) {
uint8_t tmp;
tmp = UDR0;
}

Um ganze Zeichenketten zu empfangen müsste man ein Protokoll definieren / verwenden, damit die Kommunikation zwischen den Computern einheitlich ist. Das Protokoll würde zum Beispiel definieren, welcher Overhead vor / nach den eigentlichen RAW-Daten mitgeschickt werden müsste, damit alle Komponenten exakt wissen, welche Zeichen zu welcher Zeichenkette gehören.