Moin,
ich möchte den Datenversandt per USART nun per ISR machen lassen. Dh ich
schreibe vorher alle Daten in einen Sendepuffer und lasse dann die ISR
diesen "abarbeiten" (im Prinzip analog zum Senden per ISR).
Meine Frage ist jetzt, wie ich das ganze "anwerfe" sobald ich etwas zu
senden habe.
Kann ich dazu aus dem Program heraus einfach das USR->TXC Bit setzen,
wird daruch der Interrupt ausgelöst? Wenn das nicht geht, wie macht man
das dann?
Beendet wird der sendevorgang dann dadurch, daß nach dem letzten Zeichen
einfach nichts mehr ins UDR schreibe oder?
Nicht das TXCIE, sondern UDRIE. Letzteres kommt immer, wenn Platz für
neue Sendedaten da ist, ersteres nur, wenn eine Sendung eines Bytes
gerade abgeschlossen ist.
Nein,
das Anwerfen musst Du selbst machen, der Interrupt kommt nur, wenn der
Sendebuffer leer ist.
Wenn alle Daten im Buffer sind, dann aktivierst Du den Interrupt und
startest den 1. Transfer (UDR schreiben). Sobald der Atmega bereit ist,
also UDR mit dem nächsten Zeichen beschrieben werden kann, löst er einen
Interrupt aus.
Die ISR nimmt nun das nächste Zeichen, schreibt UDR, fertig.
Wenn der Atmega wieder bereit ist, kommt der nächste Interrupt usw.
Wenn die ISR nichts mehr zum Schreiben hat, dann hört das ganze auf,
eventuell kann die ISR die Interrupts deaktivieren.
> eventuell kann die ISR die Interrupts deaktivieren
Nicht nur eventuell.
Der UDRIE kommt immer solange das Senderegister leer ist und nicht nur
wenn das Senderegister leer wurde.
Deaktiviert man den Interrupt nicht, so kommt der andauernd sobald alles
abgearbeitet wurde.
Von daher muss man auch nicht das erste Zeichen ins UDR schreiben.
Buffer beschreiben und den Interrupt einschalten. Sobald die UDR Einheit
wieder was aufnehmen kann, kommt der erste Interrupt weil ja das
Senderegister leer ist.
UDRIE ist anders als der TXCIE
TXCIE zeigt ein Ereignis an (das Zeichen ist komplett draussen)
UDRIE zeigt einen Zustand an (das Senderegister ist leer)
Und konsequenterweise kommt der UDRIE daher auch, solange dieser Zustand
vorliegt.
Ok, dh zum "triggern" aktiviere ich das UDRIE, (das TXCIE bleibt immer
aus?).
Er merkt: "UDR I S T leer" daher wird die ISR routine aufgerufen. Wenn
ich nicht das letzte Zeichen sende dann füttere ich den UDR ein letztes
mal deaktiviere auch innerhalb der ISR den UDR-Interupt wieder. Weshalb
dann nach dem senden, wenn der UDR wieder leer ist nichts mehr passiert.
So richtig verstanden?
Phillip Hommel schrieb:
> Ok, dh zum "triggern" aktiviere ich das UDRIE, (das TXCIE bleibt immer> aus?).> Er merkt: "UDR I S T leer" daher wird die ISR routine aufgerufen. Wenn> ich nicht das letzte Zeichen sende dann füttere ich den UDR ein letztes> mal deaktiviere auch innerhalb der ISR den UDR-Interupt wieder. Weshalb> dann nach dem senden, wenn der UDR wieder leer ist nichts mehr passiert.> So richtig verstanden?
Klingt richtig.
Du kannst dich von der Vorstellung leiten lassen, dass der UDRIE-ISR
Aufruf die Rückfrage von der UART darstellt: "Hast du noch was für mich
zu tun?"
Und dementsprechend reagiert deine ISR darauf. Entweder sie füttert die
UART über UDR mit neuen Daten, oder sie schaltet ab, wenn im Buffer
nichts mehr vorliegt.
Wenn du das geschickt machst, kannst du zb in einen genügend großen
Buffer durchaus auch dann noch Zeichen einfügen, während die Abarbeitung
des bereits im Buffer enthaltenen noch läuft. Von daher würde ich auch
den Interrupt nicht unmittelbar nach dem Einstellen des letzten Zeichens
ins UDR Register abdrehen, sondern erst dann wenn ein ISR Aufruf erfolgt
und in der ISR festgestellt wird, dass nichts Versendbares vorhanden
ist.
So, klappt soweit aus der ISR raus. Danke schonmal dafür.
Zu Pufferwaltung habe ich auch schon einige Ideen, damit man wie Du
schon sagtest bereits nachfüllen kann während hinten noch gesendet wird.
Allerdings hänge ich an der Ausführung ein wenig. Ich erstelle bisher
immer einen String variabler Länge (ist zwar meist in einem gewissen
Bereich aber eben nicht fix) und sende dann diesen Puffer bis er an den
Nullterminator kommt und sende stattdessen dann noch ein Linefeed '\n'.
Jetzt schwimme ich ein wenig wie ich das managen soll mit mehreren
Puffern.
Eine Idee wäre, eine Art zweidimensionales Array benutze und dazu ein
Prüfbyte in dem das jeweilige Bit immer gesetzt wird wenn die
entsprechende Zeile einen neuen String zum senden übergeben bekommt.
Wenn die ISR diesen gesendet hat wird das prüfbyte wieder gelöscht und
der Pufferplatz ist wieder "frei". Die ISR schaut dann ob das byte
ungleich null ist und sucht dann ggf bitweise weiter nach dem nächsten
noch nicht gesendeten string...
Klingt das für euch vernünftig oder wird das normalerweise anders
gemacht. Kennt Ihr da ein paar Programmierbeispiele (am besten in C) wo
man sich das eine oder andere abgucken könnte?
Phillip Hommel schrieb:
> Jetzt schwimme ich ein wenig wie ich das managen soll mit mehreren> Puffern.
Nicht mehrere Buffer.
Ein Buffer, ausgeführt als Ringbuffer.
Alle auszugebenden Texte landen dort drinnen. Die Ringbufferverwaltung
benutzt nicht den Inhalt des Buffers, um festzustellen ob da etwas
enthalten ist, sondern ihr Buchhaltungs-Variablen.
Die Ausgabe über die UART ist eigentlich ein Musterbeispiel für die
Verwendung eines FiFos. Damit kann man zu beliebigen Zeitpunkten Daten
schreiben (sofern noch Platz im FiFo ist), die dann nach und nach
gesendet werden.
Eine eigene Frage?
Dieser Thread ist über 16 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.