Hallo zusammen! kann mir jemand mal sagen, was hier eigentlich passiert: while(!(UCSRA & (1<<UDRE))); Es geht hier darum, mit dem USART zu senden. Mir ist schon klar, wozu diese Programmzeile da steht, nämlich um zu warten bis der Sendepuffer wieder leer und bereit zum Senden ist! Was ich aber nicht verstehe ist die Bitmanipulation! Ich verstehe zwar sehr wohl was beispielsweise PORTB&=~0xFF; macht! Hier wird PORTB verändert(gelöscht)! Worauf wartet man jetzt aber oben (bittechnisch gesehen) bis was genau "true" ist? UCSRA ist ja ein ganzes Register, wie kann man da jetzt beurteilen ob da was true ist oder nicht? Ist diese Operation einfach nur auf das UDRE Register bezogen? Vielen Dank!
> while(!(UCSRA & (1<<UDRE)));
Kurzfassung:
1 | "Mache nichts ('leere Schleife'), |
2 | solange ('while') |
3 | nicht ('!') |
4 | ein bestimmtes Bit (das mit der Nummer UDRE) |
5 | in einem bestimmten Register ('UCSRA') |
6 | gesetzt ist" |
> UCSRA ist ja ein ganzes Register, wie kann man da jetzt > beurteilen ob da was true ist oder nicht? alles was !=0 ist logisch wahr, 0, 0.0, "" sind falsch ("0" ist wahr, weil die Länge des Strings !=0 ist ;) ) hth. Jörg
UDRE ist der Name eines Bits (genauer gesagt: eines Flags) im UCSRA. UDRE wird von der Hardware automatisch gesetzt, wenn der Sendepuffer leer ist, also wenn ein neues Zeichen in den Puffer (UDR) geschrieben werden kann. In der Device-Headerdatei des verwendeten Controllers steht irgendwo eine Definition dieses Namens, der ihm eine Nummer zuweist, und zwar die Nummer, die das Bit im Register hat. Das sieht so aus:
1 | #define UDRE 5
|
Das #define sorgt dafür, dass an allen Stellen im Code, an denen "UDRE" auftaucht, dieser Name durch die Zahl "5" ersetzt wird. In der Schleifenbedingung steht jetzt der ominöse Ausdruck
1 | 1 << UDRE |
Da der Präprozessor das "UDRE" durch eine "5" ersetzt, steht da
1 | 1 << 5 |
Das wiederum bedeutet, dass eine binäre "1" (0b00000001) um 5 Stellen nach links geschoben wird. 1 << 5 entspricht also der Binärzahl 0b00100000. Mit dieser Binärzahl, die in diesem Zusammenhang auch als "Maske" bezeichnet wird, wird jetzt das UCSRA bitweise UND-verknüpft. Das führt dazu, dass alle Bits bis auf das mit der Nummer 5 (nämlich das UDRE) "ausgeblendet" werden. Ist das Bit gesetzt, dann liefert der Ausdruck "(UCSRA & (1<<UDRE))" ein 0b00100000 zurück, andernfalls eine 0 (0b00000000). Dieser Ausdruck wird jetzt noch logisch negiert. Das wiederum bedeutet, dass aus allem, was ungleich 0 ist eine 0 wird, und aus 0 eine 1. Ist das Bit "UDRE" also gesetzt, dann steht nach Auswertung des Ausdrucks "!(UCSRA & (1<<UDRE))" effektiv eine 0 in der Klammer, was dazu führt, dass die Schleife verlassen wird. Ist das Bit UDRE nicht gesetzt, steht da eine 1 ("wahr") und die Schleife wird weiterhin durchlaufen.
@ john (Gast) >"true" ist? UCSRA ist ja ein ganzes Register, wie kann man da jetzt >beurteilen ob da was true ist oder nicht? Wird ja gar nicht. Das Register UCSRA wird mit einer Bitmaske verknüpft, welche durch die Schiebeopreation (1<<UDRE) erzeugt wird. (1<<UDRE) ergibt 0x20, (eine 1 um 5 Stellen nach links geschoben) Das Register UCSRA wird mit 0x20 UND verknüpft, was bewirkt dass alle Bits ausser UDRE auf Null gesetzt werden, UDRE bleibt wie es ist. Dieses Ergebniss wird nun mit Null verglichen Ergebis==Null -> False, While Schleife wird noch eimal durchlaufen Ergebis!=Null -> True, While Schleife wird abgebrochen >Ist diese Operation einfach nur auf das UDRE Register bezogen? Auf das Bit UDRE im Register UCSRA. MFG Falk
hey vielen dank für die kompetente antwort! so was ist einfach super! danke!
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.