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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Luke (Gast)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht 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)


Bewertung
0 lesenswert
nicht lesenswert
Hab ich schon weiter oben.

von Luke (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Alles klar, danke.

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.