Forum: Mikrocontroller und Digitale Elektronik Unterschied zwischen TXCn und UDREn beim USART eines Atmega128


von Luke (Gast)


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

von Falk B. (falk)


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;

von Luke (Gast)


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;
}

von Sascha W. (sascha-w)


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

von Carl D. (jcw2)


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.

: Bearbeitet durch User
von Falk B. (falk)


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.

von Falk B. (falk)


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.

von Luke (Gast)


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 ?

von Carl D. (jcw2)


Lesenswert?

Hab ich schon weiter oben.

von Luke (Gast)


Lesenswert?

Alles klar, danke.

Ich hab es nur mehrmals lesen müssen bis ich es verstanden habe :)

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.