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
@ 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; |
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; }
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
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
@ 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.
@ 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.
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 ?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.