Forum: Mikrocontroller und Digitale Elektronik Atmega32 TX per ISR "triggern"


von Phillip H. (philharmony)


Lesenswert?

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?

von Hc Z. (mizch)


Lesenswert?

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.

von Klaus F. (kfalser)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Phillip H. (philharmony)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Phillip H. (philharmony)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Uwe .. (uwegw)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.