Forum: Compiler & IDEs ISR(USART_TX_vect) atmega88 Verhalten


von Alf (Gast)


Lesenswert?

Wenn ich es richtig verstehe, wird dieser Int immer dann ausgeführt, 
wenn 1 Byte komplett gesendet wurde, also wenn auch das Stop-Bit mit 
raus ist.

Wenn ich mehrere Bytes unmittelbar hintereinander sende, löst der Int 
bei mir nicht nach jedem Einzelbyte aus, sondern nur wenn das letzte 
eines Blockes raus ist. Ist dieses Verhalten immer so, oder von mega zu 
mega anders? Hat vermutlich was mit der Pipline zu tun. Ich könnte damit 
leben.

von Sash (Gast)


Lesenswert?

Hallo,

im Datenblatt steht:
1
The Transmit Complete (TXCn) Flag bit is set one when the entire frame in the Transmit Shift
2
Register has been shifted out and there are no new data currently present in the transmit buffer.
3
The TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it
4
can be cleared by writing a one to its bit location. The TXCn Flag is useful in half-duplex communication
5
interfaces (like the RS-485 standard), where a transmitting application must enter
6
receive mode and free the communication bus immediately after completing the transmission.
7
When the Transmit Compete Interrupt Enable (TXCIEn) bit in UCSRnB is set, the USART
8
Transmit Complete Interrupt will be executed when the TXCn Flag becomes set (provided that
9
global interrupts are enabled). When the transmit complete interrupt is used, the interrupt handling
10
routine does not have to clear the TXCn Flag, this is done automatically when the interrupt
11
is executed.

Ich bin kein wirklich erfahrener Nutzer ... aber mein erster Versuch das 
von Dir beschriebene Verhalten zu ändern wäre, ein neues Byte erst in 
den Puffer zu schreiben wenn der Transmit Complete Interrupt 
angesprungen wurde (z.B. indem man in genanntem Interrupt ein flag 
setzt, auf das die Funtion die die Bytes in den Transmitpuffer schreibt 
wartet).

^^ Falls hier grobe Fehler vorliegen kann der Beitrag bitte gelöscht 
werden ... ist das erste Mal das ich antworte statt nur selber zu 
Fragen, um auch mal was beizutragen. Hoffe es ist nicht ganz falsch was 
ich geschrieben habe.

von Hc Z. (mizch)


Lesenswert?

Der TXC-Interrupt löst aus, wenn der Tx-Teil des UARTs arbeitslos ist. 
Es stehen dann keine neuen Daten zum Senden mehr an und das letzte 
Zeichen ist komplett hinausgeschoben.  Dieses Verhalten ist für alle 
AVRs gleich (und nicht nur dort).  Die Hauptanwendung ist die Steuerung 
von externer Sendehardware, z.B. das Abschalten des RS485-Sendetreibers.

Der Interrupt, der bei jedem Zeichen auslöst, heißt beim AVR UDRE.  Der 
zeigt an, dass der UART in der Lage ist, ein neues Sendezeichen zu 
akzeptieren, also (in CPU-Größenordnungen) lange bevor das letzte 
Zeichen komplett abgesendet ist.

von Falk B. (falk)


Lesenswert?

@  Alf (Gast)

>wenn 1 Byte komplett gesendet wurde, also wenn auch das Stop-Bit mit
>raus ist.

Nicht ganz, wenn das letzte Byte gesendet wurde und kein neues Datenbyte 
im Sendepuffer liegt.

>Wenn ich mehrere Bytes unmittelbar hintereinander sende, löst der Int
>bei mir nicht nach jedem Einzelbyte aus, sondern nur wenn das letzte
>eines Blockes raus ist.

So soll das auch sein.

> Ist dieses Verhalten immer so,

Ja.

> oder von mega zu
>mega anders? Hat vermutlich was mit der Pipline zu tun. Ich könnte damit
>leben.

Siehe 
http://www.mikrocontroller.net/articles/Interrupt#UART_mit_Interrupts

MFG
Falk

von Alf (Gast)


Lesenswert?

Ok dann passt es. Es geht um RS-485 Sender Ein- und Ausschaltung. Die 
soll erst nach dem letzten Byte sein.

von Ulrich P. (uprinz)


Lesenswert?

Nur als Hinweis:

Wenn Deine Software noch andere Dinge per Interrupt tut, kann es 
passieren, dass Du vereinzelt auch TXC Interrupts bekommst, obwohl noch 
weitere Zeichen zu senden wären. Das passiert immer dann, wenn die 
Software z.B. ein cli() macht, einie zeit benötigt und dann sei() gibt 
und innerhalb dieser Zeit der Zustand UDRE und danach TXC auftritt wegen 
der gesperrten Interrupts

Es ist daher sinnvoll die Zeichen per UDRE Interrupt aus dem Puffer in 
das UDR zu schieben und dort auf das letzte Zeichen zu prüfen. Wenn es 
das letzte Zeichen ist, den TXC Interrupt aktivieren, den UDRE Interrupt 
deaktivieren.

Der TXC Interrupt schaltet dann den RS4xx Bus um und deaktiviert sich 
selbst.

D3er UDRE Interrupt wird in der putc() erneut aktiviert, wenn erneut 
Zeichen zu senden sind.

Gruß, Ulrich

von Alf (Gast)


Lesenswert?

>Nur als Hinweis:

Danke für die Infos, gut mal von dem Verhalten gehört zu haben.

Bisher läuft es ohne Probleme. TXC Int. kommt zeitlich korrekt. Habe 
auch noch andere Interrupts laufen. Allerdings vermeide ich generell in 
einem Programm die zeitweise globale Interruptsperrung mit cli/sei.

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.