Nun habt ihr wahrscheinlich alle schon Daten vom Controller zum PC geschickt. Es gibt aber durchaus auch Anwendungen, bei denen wir Informationen vom PC oder anderen Geräten über die serielle Schnittstelle an den Controller schicken können.
Bevor wir Daten über den UART einlesen können müssen wir diesen natürlich
auch wieder initialisieren. Ich erinnere dazu auch an den UART,
Teil 1, in welchem das Senden besprochen wurde.
Um grundsätzlich mal Empfangen zu können, muss das Receiver Enable Bit
im UART Control Register gesetzt werden:
outp ((1 << RXEN), UCR);
Wenn wir senden und empfangen wollen muss zusätzlich das Transmitter Enable Bit gesetzt werden. Dann sieht der Befehl so aus:
outp ((1 << RXEN) | (1 << TXEN), UCR);
Und denkt daran, dass wir auch noch die Baudrate festlegen müssen.
#define F_CPU 4000000
// Zum Beispiel 4Mhz-Quarz
#define UART_BAUD_RATE 9600 // Wir versuchen mal mit 9600 Baud
outp (F_CPU / (UART_BAUD_RATE * 16L) - 1, UBRR);
Sodele, jetzt müssen wir in unserer Programmschleife bloss noch prüfen, ob eventuell ein Zeichen empfangen wurde. Dies wird vom UART im Status Register angezeigt, indem das RXC Bit gesetzt wird. Nun müssen wir möglichst schnell das UART Daten Register auslesen, damit das nächste Zeichen empfangen werden kann.
char ch; // Variable zur Speicherung
des gelesenen Zeichens
for (;;)
{
// Endlosschleife
if (inp (USR) & (1 << RXC)) { //
Bit RXC im USR gesetzt ?
ch = inp (UDR);
// Datenregister auslesen
}
...
...
}
Wenn wir sicher sein wollen, dass wir auch alle Zeichen empfangen haben müssen wir jeweils noch das OverRun Bit testen. Wenn wir nämlich zu lange warten mit dem Auslesen des Datenregisters kann es passieren, dass bereits wieder ein Zeichen in das Empfangs-Schieberegister eingelesen wurde. Da aber das Datenregister noch belegt ist schmeisst der UART das neue Zeichen weg und setzt das OR Bit im Status Register.
char ch; // Variable zur Speicherung
des gelesenen Zeichens
for (;;)
{
// Endlosschleife
if (inp (USR) & (1 << RXC)) { //
Bit RXC im USR gesetzt ?
ch = inp (UDR);
// Datenregister auslesen
if (inp (USR) & (1 << OR))
{ // OverRun Bit gesetzt ?
// Autsch,
jetzt ist
// was
verloren gegangen
...
}
}
...
...
}
Wer jetzt glaubt, eine serielle Schnittstelle könne nur mit denjenigen AVR's
realisiert werden welche auch einen UART an Bord haben, der hat sich
geschnitten.
Selbstverständlich können wir mit einer entsprechenden Software eine serielle
Schnittstelle auf 2 beliebigen Pin's des Controllers realisieren. Allerdings ist
der Aufwand für eine entsprechende Software schon erheblich. Beispiele dafür
findet ihr auf den einschlägigen Seiten im Internet. Man spricht in diesem Fall
von einem Software-UART.
Mit dieser Methode ist es auch möglich, einen AVR mit mehreren seriellen
Schnittstellen zu versehen.
Wir haben jetzt gesehen, wie wir mit dem UART ohne Verwendung der Interrupts
Daten senden und empfangen können.
Wenn wir die Interrupts zur Hilfe nehmen geht das ganze noch viel komfortabler,
aber dazu später mehr.
|