Unterschied zwischen TXCn und UDREn beim USART eines Atmega128

Gast #5079023
Lesenswert?
• ▲
▼
Hallo ich habe mal ein Frage zum UCSRnA Register eines Atmega128.

Dort gibt es unter anderem die zwei folgenden Bits:

TXCn: Wird 1 wenn die Daten im TXBn Register erfolgreich gesendet 
wurden.

UDREn: Wird 1 wenn UDRn Register bereit ist für neue Daten.

UDRn besteht ja aus den zwei Registern TXBn (Transmit data buffer) und 
RXBn (Receive data buffer).

Wenn ich nun Daten im Pollingbetrieb sende, dann kann ich das in C ja 
mit folgendem Code bewerkstelligen:

while (UCSR1A&(1<<UDRE1)==0); //Warten bis UDR1 Register bereit ist
UDR1=byte_to_send; //Daten senden

Könnte ich an dieser Stelle, statt zu prüfen ob UDRE1 gesetzt ist auch 
prüfen ob TXC1 gesetzt ist, ohne das die Funktionalität sich ändert ?

Danke im Voraus.

LG Luke
#5079037
Lesenswert?
• ▲
▼
@ Luke (Gast)

>TXCn: Wird 1 wenn die Daten im TXBn Register erfolgreich gesendet
>wurden.

UND es gibt kein weiteres Byte im Sendepuffer UDRn!

>UDREn: Wird 1 wenn UDRn Register bereit ist für neue Daten.

Ja.

>UDRn besteht ja aus den zwei Registern TXBn (Transmit data buffer) und
>RXBn (Receive data buffer).

Ja, es werden 2 verschiedene Register unter dem selben Namen 
angesprochen. Ist ein wenig ungnstig, logisch aber OK. Denn man kann 
Sendedaten nur sinnvollerweise schreiben und Empfangsdaten nur lesen.

>Wenn ich nun Daten im Pollingbetrieb sende, dann kann ich das in C ja
>mit folgendem Code bewerkstelligen:

>while (UCSR1A&(1<<UDRE1)==0); //Warten bis UDR1 Register bereit ist
>UDR1=byte_to_send; //Daten senden

>Könnte ich an dieser Stelle, statt zu prüfen ob UDRE1 gesetzt ist auch
>prüfen ob TXC1 gesetzt ist, ohne das die Funktionalität sich ändert ?

Ja. Allerdings muss man es vorher löschen!

1
UCSR1A = (1<<TXC1);
2
while (!(UCSR1A & (1<<TXC1));
3
UDR1=byte_to_send;
Gast #5079066
Lesenswert?
• ▲
▼
Verstehe,

ich muss es löschen weil ich trotz eintreffenden Interrupt keine ISR 
aufrufe, die es selbst löschen würde !!!

Und man löscht es indem man eine logische 1 dort rein schreibt !!

Alles klar.

Eine Frage noch:

Was wenn es andersherum wäre und was wenn ich mit ISR arbeite.

Also der Fall das ich den receiver benutze.

Kann ich statt den Interrupt-Vektor USART1_RX_vect (Receive complete) 
auch den Interrupt-Vektor USART1_UDRE_vect (Data register empty) nutzen 
?

Hier nochmal der Code zu Verdeutlichung:

ISR(Interrupt-Vektor){
received_byte=UDR1;
}
#5079118
Lesenswert?
• ▲
▼
Falk B. schrieb:
>
1
> UCSR1A = (1<<TXC1);
2
> while (!(UCSR1A & (1<<TXC1));
3
> UDR1=byte_to_send;
4
>
Das gibt u.U. einen Deadlock, TXC wird ja nur gesetzt wenn das senden 
abgeschlossen wird. Wenn der UART beim löschen von TXC schon nix mehr 
zu tun hatte wird es auch nicht gesetzt und die Schleife wartet ewig. 
Man müsste die gesamte  Ausgabe umstellen, erst Datenbyte ausgeben dann 
auf das Ende der Übertragung warten.
Die Methode nutzt halt die doppelte Pufferung des UART nicht und 
verschenkt so etwas  Rechenleistung.

Sascha
#5079127
Lesenswert?
• ▲
▼
TXCn bedeutet "Sende-Schieberegister leer", d.h. das letzte Bit ist auf 
der Leitung. UDREn sagt, "Puffer vor dem Sende-Schieberegister frei", 
wärend gerade gesendet wird. Im letzteren Fall hat man eine 
Zeichenübertragungszeit um für Nachschub zu sorgen, im Ersten Fall ist 
man eigentlich schon zu spät dran, besonders wenn man das Flag als 
Interruptquelle nimmt.

UDREn sorgt also für kontinuierlichen Datenstrom,
TXCn signalisiert, daß das Senden tatsächlich beendet ist.
Z.B. wenn man bei Halbduplex von Sende- auf Empfangsrichtung umschalten 
muß, da sollte das letzte Zeinen auch tatsächlich raus sein.

Beide Flags/INT's sind für Senden.
RXn ist der Empfangs-Fall.
#5079182
Lesenswert?
• ▲
▼
@ Luke (Gast)

>Was wenn es andersherum wäre und was wenn ich mit ISR arbeite.

>Also der Fall das ich den receiver benutze.

Der hat aber erstmal nicht direkt was mit dem SENDER zu tun.
Oder meinst du den TCX-Interrupt?

>Kann ich statt den Interrupt-Vektor USART1_RX_vect (Receive complete)
>auch den Interrupt-Vektor USART1_UDRE_vect (Data register empty) nutzen
>?

>ISR(Interrupt-Vektor){
>received_byte=UDR1;
>}

Ja klar, das ist die Interrupt-Version.
#5079188
Lesenswert?
• ▲
▼
@ Sascha Weber (sascha-w)


>> UCSR1A = (1<<TXC1);
>> while (!(UCSR1A & (1<<TXC1));
>> UDR1=byte_to_send;
>>

>Das gibt u.U. einen Deadlock, TXC wird ja nur gesetzt wenn das senden
>abgeschlossen wird.

Nö. Wenn diese Funktion nur im Polling-Betrieb genutzt wird, passt das.

> Wenn der UART beim löschen von TXC schon nix mehr
>zu tun hatte wird es auch nicht gesetzt und die Schleife wartet ewig.

Ahhh, mein Fehler! Zeilen verdreht! Eher so.
1
UCSR1A = (1<<TXC1);
2
UDR1=byte_to_send;
3
while (!(UCSR1A & (1<<TXC1));

>Die Methode nutzt halt die doppelte Pufferung des UART nicht und
>verschenkt so etwas  Rechenleistung.

Deswegen macht man es nur sehr selten so.
Gast #5079275
Lesenswert?
• ▲
▼
Verstehe,

da die beiden Interrupts ja für ähnliche bzw identische Aufgaben genutzt 
werden können, ist meine Frage nun:
Kann mir jemand ein explizites Beispiel nennen in dem nur das eine oder 
nur das andere zum Einsatz kommt ?

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.