tefanus F. schrieb:
>> Ich denke, es ist eine ganz schlechte Idee, in der Receive ISR
>> darauf zu warten, dass du etwas senden darfst. Während dessen
>> verpasst du andere empfangene Zeichen.
AVR schrieb im Beitrag #5603251:
> wie würde es denn sauber gelöst aussehen?
Zunächst mal kann man ausnutzen, dass der UART genau so schnell sendet,
wie er empfängt. Wenn es Dir lediglich darum geht, ein Echo zurück zu
schicken, mach das ruhig so.
Du sendest aber mehrere Zeichen, spätestens ab dem 2. musst du warten,
dass der Sendepuffer frei wird. Das ist der Moment, wo du andere
Empfangdaten verpasst.
Richtig löst man das zum Beispiel mit Puffern. Alle empfangenen Daten
werden (wie gehabt) von der Receive-ISR in den Puffer gelegt. Die
Verabeitung der empfangenen Daten findet aber in der Haputschleife
statt, nicht in der ISR.
Für das Senden hast du einen zweiten Puffer. Alle zu sendenden Zeichen
legst du in diesen Puffer ab, mit Ausnahme des ersten Zeichens, das
legst du direkt in das UDR Register, damit der Sender aktiv wird.
Also musst du beim Senden für jedes einzelne Zeichen unterscheiden:
a) Ist der Puffer leer, dann UDR=c, sonst
b) c in den Puffer legen.
Die ISR für UDRE wird nach dem Senden jedes Zeichens aufgerufen. Nun ist
es Aufgabe der entprechenden ISR, das nächste Zeichen aus dem
Sende-Puffer in das UDR Register zu schreiben. Wenn es nichts mehr zu
senden gibt, dann endet die ISR einfach, der Tx Sender wird dadurch
inaktiv.
Dafür gibt es sicher einige Tutorials, die es vorführen.
Ich verzichte in meinem Programmen meistens auf diese Komplexität. Ich
empfange mit ISR und Puffer, aber sende immer direkt (ohne Puffer). Der
Nachteil dieser Vorgehensweise ist, dass mein Programm während des
Senden in Warteschleifen hängt und nichts anderes tun kann.
Auf jeden Fall soll man in der Receive ISR entweder gar nichts senden
oder maximal ein Zeichen. Sonst musst du nämlich wie oben Warteschleifen
in die ISR einbauen und damit stellt man sich selbst ein Bein.
Warteschleifen und delays in ISR sind sehr häufig der Anfang von neuen
Problemen.
Ein häufiger Fall ist, Kommandos zeilenweise zu empfangen. Man will bis
zum Zeilenumbruch empfangen und danach diese eine Zeile verarbeiten.
Dazu kannst du in der Receive-ISR prüfen, ob der Zeilenumbruch erreicht
wurde. Wenn ja, setzt du ein globales Flag auf 1. Das Hauptprogramm
beschäftigt sich derweil mit anderen Aufgaben oder wartet einfach nur,
bis dieses Flag auf 1 geht. Verarbeitete es die empfangene Zeile und
setzt das Flag wieder auf 0, um für die nächste Zeile bereit zu sein.
Vergiss nicht, die Variable für das Flag als volatile zu deklarieren und
dass sie 8bit klein sein muss.