Difference between revisions of "AVR Embedded Tutorial - UART/de"
Line 4: | Line 4: | ||
==Polling== | ==Polling== | ||
− | + | ==ATmega328p (Arduino uno/nano)== | |
Für die serielle Ausgabe wird ein Terminal mit folgenden Einstellungen gebraucht: | Für die serielle Ausgabe wird ein Terminal mit folgenden Einstellungen gebraucht: | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 19: | Line 19: | ||
Beim Betätigen von '''[space]''' im Terminal-Programm, sollte ein "Hello World !" zurück kommen. | Beim Betätigen von '''[space]''' im Terminal-Programm, sollte ein "Hello World !" zurück kommen. | ||
+ | ===Konstanten für Inizialisierung=== | ||
<syntaxhighlight lang="pascal">program Project1; | <syntaxhighlight lang="pascal">program Project1; | ||
const | const | ||
Line 24: | Line 25: | ||
Baud = 9600; // Baudrate | Baud = 9600; // Baudrate | ||
Teiler = CPU_Clock div (16 * Baud) - 1; | Teiler = CPU_Clock div (16 * Baud) - 1; | ||
+ | </syntaxhighlight> | ||
+ | ===Inizialisieren=== | ||
+ | Die UART-Schnittstelle konfigurierieren. | ||
+ | <syntaxhighlight lang="pascal">program Project1; | ||
procedure UARTInit; | procedure UARTInit; | ||
begin | begin | ||
− | UBRR0 := Teiler; | + | UBRR0 := Teiler; // Baud |
− | UCSR0A := | + | UCSR0A := 0 // Normale Geschwindigkeit |
− | UCSR0B := (1 shl TXEN0) or (1 shl RXEN0); | + | UCSR0B := (1 shl TXEN0) or (1 shl RXEN0); // Empfangen und Senden |
− | UCSR0C := (%011 shl UCSZ0); | + | UCSR0C := (%011 shl UCSZ0); // 8-Bit Übertragung |
end; | end; | ||
+ | </syntaxhighlight> | ||
− | + | ===Zeichen empfangen=== | |
+ | <syntaxhighlight lang="pascal">program Project1; | ||
+ | function UARTReadChar: char; | ||
begin | begin | ||
− | while UCSR0A and (1 shl | + | while UCSR0A and (1 shl RXC0) = 0 do begin // Warten, bis Zeichen ankommt. |
end; | end; | ||
− | + | Result := char(UDR0); // Zeichen einlesen. | |
end; | end; | ||
+ | </syntaxhighlight> | ||
− | + | ===Zeichen senden=== | |
+ | <syntaxhighlight lang="pascal">program Project1; | ||
+ | procedure UARTSendChar(c: char); | ||
begin | begin | ||
− | while UCSR0A and (1 shl | + | while UCSR0A and (1 shl UDRE0) = 0 do begin // Warten, bis letztes Zeichen gesendet. |
end; | end; | ||
− | + | UDR0 := byte(c); // Zeichen senden. | |
end; | end; | ||
+ | </syntaxhighlight> | ||
+ | ===String senden=== | ||
+ | <syntaxhighlight lang="pascal">program Project1; | ||
procedure UARTSendString(s: ShortString); | procedure UARTSendString(s: ShortString); | ||
var | var | ||
Line 56: | Line 70: | ||
end; | end; | ||
end; | end; | ||
+ | </syntaxhighlight> | ||
+ | ===Hauptschleife=== | ||
+ | Hier wird gewartet, bis [space] ankommt, anschliessend wir "Hello World !" gesendet. | ||
+ | <syntaxhighlight lang="pascal">program Project1; | ||
begin | begin | ||
UARTInit; | UARTInit; | ||
Line 64: | Line 82: | ||
end; | end; | ||
until 1 = 2; | until 1 = 2; | ||
− | end.</syntaxhighlight> | + | end. |
+ | </syntaxhighlight> | ||
===ATtiny2313=== | ===ATtiny2313=== |
Revision as of 21:58, 18 November 2017
UART
Polling
ATmega328p (Arduino uno/nano)
Für die serielle Ausgabe wird ein Terminal mit folgenden Einstellungen gebraucht:
Baud Rate | 9600 |
Bits | 8 |
Stopbits | 1 |
Parity | none |
Beim Betätigen von [space] im Terminal-Programm, sollte ein "Hello World !" zurück kommen.
Konstanten für Inizialisierung
program Project1;
const
CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
Baud = 9600; // Baudrate
Teiler = CPU_Clock div (16 * Baud) - 1;
Inizialisieren
Die UART-Schnittstelle konfigurierieren.
program Project1;
procedure UARTInit;
begin
UBRR0 := Teiler; // Baud
UCSR0A := 0 // Normale Geschwindigkeit
UCSR0B := (1 shl TXEN0) or (1 shl RXEN0); // Empfangen und Senden
UCSR0C := (%011 shl UCSZ0); // 8-Bit Übertragung
end;
Zeichen empfangen
program Project1;
function UARTReadChar: char;
begin
while UCSR0A and (1 shl RXC0) = 0 do begin // Warten, bis Zeichen ankommt.
end;
Result := char(UDR0); // Zeichen einlesen.
end;
Zeichen senden
program Project1;
procedure UARTSendChar(c: char);
begin
while UCSR0A and (1 shl UDRE0) = 0 do begin // Warten, bis letztes Zeichen gesendet.
end;
UDR0 := byte(c); // Zeichen senden.
end;
String senden
program Project1;
procedure UARTSendString(s: ShortString);
var
i: integer;
begin
for i := 1 to length(s) do begin
UARTSendChar(s[i]);
end;
end;
Hauptschleife
Hier wird gewartet, bis [space] ankommt, anschliessend wir "Hello World !" gesendet.
program Project1;
begin
UARTInit;
repeat
if UARTReadChar = #32 then begin // space
UARTSendString('Hello World !'#13#10);
end;
until 1 = 2;
end.
ATtiny2313
Beim ATtiny2313 haben die Register eine andere Bezeichnung als beim ATmega328p.
- Die 0 entfällt in der Bezeichnung.
- UBRR0 muss man in UBRRH und UBRRL zerlegen.
Das sieht dann so aus:
UBRRH := Teiler shr 8;
UBRRL := Byte(Teiler);
UCSRB := (1 shl TXEN) or (1 shl RXEN);
UCSRC := (%011 shl UCSZ);
(Der Code wurde nicht getestet)
Interrupt
Beim Polling kann es passieren, das Zeichen verschluckt werden, dies passiert, wen ein Zeichen ankommt und man dieses nicht abholt. Aus diesem Grund empfiehlt es sich, den Zeichenempfang Interrupt gesteuert zum machen.
Deklaration
Zeichenbuffer deklarieren, hier wir ein Puffer von 16 Zeichen angelegt.
const
Crxlen = 16;
var
RxBuf: array[0..Crxlen - 1] of byte;
rxread: byte = 0;
rxwrite: byte = 0;
Inzialisieren
Dies ist ähnlich des Polling verfahren, der Unterschied, man teilt mit RXCIE0 mit, das beim Zeichenempfang ein Interrupt ausgelöst wird.
procedure UARTInit;
begin
UBRR0 := teiler;
UCSR0A := (0 shl U2X0);
UCSR0B := (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
UCSR0C := %011 shl UCSZ0;
end;
Interrupt
Bei auslösen des Interrupts, wird das Zeichen vom UART in Zeichenbuffer kopiert.
procedure UART_RX_Empfang; public Name 'USART__RX_ISR'; interrupt;
var
tchr: byte;
begin
tchr := UDR0;
if tchr <> 0 then begin
RxBuf[rxwrite] := tchr;
Inc(rxwrite);
if rxwrite >= Crxlen then begin
rxwrite := 0;
end;
end;
end;
Hauptschleife
In der Hauptschleife wird geprüft, ob sich etwas im Empfangspuffer, wen ja, wird ein Zeichen davon ausgelesen. In diesem Beispiel werden, die empfangenen Zeichen in Grossbuchstaben umgewandelt und anschiessend wieder ausgegeben.
begin
// UART inizialisieren, die Interrupt gesteuert.
UARTInit;
// Interrupt aktivieren.
asm sei end;
// Hauptschleife.
repeat
cli;
while rxwrite <> rxread do begin
ch := RxBuf[rxread];
Inc(rxread);
if rxread >= Crxlen then begin
rxread := 0;
end;
if ch in [$61..$7A] then begin
Dec(ch, 32);
end;
UARTSendChar(char(ch));
end;
sei;
until 1 = 2;
end.