Hallo, Ich wollte gerne den Sendepuffer abfragen, ob der schon leer ist (d.h. ob alle Zeichen raus sind) Benutze AVR Studio 7 und ATMEGA 8 Gruß Mathias p.s.: Sorry nicht gesehen, das ich in Bearbeiten war und damit mein ersten Post ausversehen verwuselt....
:
Bearbeitet durch User
Direkt aus dem Datenblatt
1 | void USART_Transmit( unsigned char data ) |
2 | {
|
3 | /* Wait for empty transmit buffer */
|
4 | while ( !( UCSRA & (1<<UDRE)) ); |
5 | /* Put data into buffer, sends the data */
|
6 | UDR = data; |
7 | }
|
Bits aus einem Register abfragen/testen ist elementarstes C.
Mathias G. schrieb: > ob die Zeichen raus sind Ist es nicht so, dass das UDRE nur sagt, dass das Byte aus dem UDR ins Shift Register übertragen wurde. Dann folgt das Heraustakten und erst dann meldet TXC den Transmit Complete?
Adam P. schrieb: > Dann folgt das Heraustakten und erst dann meldet TXC den Transmit > Complete? Bei der Fragestellung aus dem Eingangspost hätte ich jetzt auch geprüft ob Transmit Complete vorliegt und würde nicht über das UDRE gehen aber wer kann schon sagen, was der TE überhaupt machen will. Möglicherweise ist auch das Prüfung von UDRE das, was der TE sucht ;)
Hallo, an das Abfragen des Bits direkt habe ich schon gedacht wie: Mike R. schrieb: > while ( !( UCSRA & (1<<UDRE)) ); Aber da ich Zeichen mit uart_putc einzeln Sende, funktioniert das nicht so mit der Abfrage. Werde das mal als kompletten String mit uart_puts senden. Gruß Mathias
Mathias G. schrieb: > Aber da ich Zeichen mit uart_putc einzeln Sende, funktioniert das nicht > so mit der Abfrage. Warum nicht? Mathias G. schrieb: > Werde das mal als kompletten String mit uart_puts > senden. uart_puts() ist doch auch nur eine Übergelagerte Funktion die uart_putc verwendet. (In den meisten Implementierungen zumindest um doppelten Code zu vermeiden). Code von oben erweitert:
1 | void USART_Transmit( unsigned char data ) |
2 | {
|
3 | /* Wait for empty transmit buffer */
|
4 | while ( !( UCSRA & (1<<UDRE)) ); |
5 | /* Put data into buffer, sends the data */
|
6 | UDR = data; |
7 | }
|
8 | |
9 | void USART_Send_Blocked(const unsigned char *str) |
10 | {
|
11 | while (*str) |
12 | {
|
13 | USART_Transmit(*str++); |
14 | }
|
15 | }
|
:
Bearbeitet durch User
Adam P. schrieb: > Warum nicht? > > uart_puts() ist doch auch nur eine Übergelagerte Funktion die uart_putc > verwendet. (In den meisten Implementierungen zumindest um doppelten Code > zu vermeiden). Er führt meinen Code weiter aus, obwohl die Zeichen noch nicht vollständig gesendet sind. Das Auswerten des TXC müsste in diesem Fall besser funktionieren. Hintergrund: Ich muss vor dem Senden über einen Pin ein Signal setzen, was nach dem vollständigen senden wieder zurückgesetzt wird. Dieses Signal geht zu einer Umschaltlogik, das von einem anderen uart Sender zu meinem ATMega umschaltet.
:
Bearbeitet durch User
Mathias G. schrieb: > Er führt meinen Code weiter aus, obwohl die Zeichen noch nicht > vollständig gesendet sind. Würde für TXE als Lösung sprechen. Oder bastel dir doch ein FIFO, schreib deine Daten da rein und wenn du dann dein Sende-Trigger aktivierst, dann setzt du dein PIN, aktivierst die Interrupts, lässt die ganze Arbeit vom Interrupt erledigen und wenn TXE sich meldet und dein FIFO auch "empty" ist, dann bist du fertig. So als Spontane Idee :-) Mathias G. schrieb: > Er führt meinen Code weiter aus Das wirkt wohl nur so, denn die while() in der Transmit Funktion sagt was anderes. Oder meinst du eher, dass das UDRE Flag sich meldet aber noch Bits vom letzten Byte getaktet werden?
Blockierend zu arbeiten ist doch viel schwieriger wie mit Interrupt. Zumal der PC, ein PC, sowieso ein schlechtes Verhalten hat. Mit einem PC arbeitet man am effizientesten mit moeglichst grossen Bloecken falls man etwas wie Performance haben will. USB-2-Serial hat ein unpassendes Timing verhalten. Da sollte man nicht zuviel erwarten. Und genau diese Performance ist auf Controller Seite weg wenn man blockierend arbeitet, wie auf ein Bit zu warten. Aber wir wissen ja nich was der poster effektiv moechte
Hm. Vielleicht zeigst Du mal Deinen eigenen Code. An sollte die Übertragung mit der der while-Schleife vor dem erneuten setzen von UDR so gehen. Was funktioniert daran nicht? Allerdings musst Du tatsächlich, auch das TXC-Flag verwenden, falls Du erkennen willst, das der Transfer des letzten Bytes abgeschlossen ist. Als Hinweis noch ein Satz aus dem Datenblatt: "The TXC Flag can be used to check that the Transmitter has completed all transfers, and the RXC Flag can be used to check that there are no unread data in the receive buffer. Note that the TXC Flag must be cleared before each transmission (before UDR is written) if it is used for this purpose." D.h., spätestens vor der Übertragung des letzten Bytes, musst Du das TXC-Flag löschen.
Mathias G. schrieb: > Er führt meinen Code weiter aus, obwohl die Zeichen noch nicht > vollständig gesendet sind. Wäre ja auch so richtig. Das while wartet ja nur drauf, dass das UDR wieder leer ist, das bedeutet eben nicht, dass bereits alles gesendet wurde. Ist das für dich wichtig dann solltest du in der Tat nach TXC schauen. ;)
M. K. schrieb: > Wäre ja auch so richtig. Das while wartet ja nur drauf, dass das UDR > wieder leer ist, das bedeutet eben nicht, dass bereits alles gesendet > wurde. Ist das für dich wichtig dann solltest du in der Tat nach TXC > schauen. ;) Ich habe jetzt den TXC genommen while (!(UCSRA & 1<<TXC)); … und mit dem Hinweis: Theor schrieb: > D.h., spätestens vor der Übertragung des letzten Bytes, musst Du das > TXC-Flag löschen. UCSRA = UCSRA & (0xff - 1<<TXC); … scheint es zu funktionieren. Danke Gruß Mathias
Theor schrieb: > @ Mathias > > Na Prima. > > Und schön, dass Du eine Rückmeldung gibst. Irgendwie habe ich noch Schwierigkeiten, habe im AVR-GCC-Tutorial/Der UART den Hinweis gefunden: Um das Bit zu löschen muss eine 1 an die entsprechende Position geschrieben werden! Ist das so richtig? Das würde erklären, das beim ersten senden funktioniert. Wenn ich später in einer anderen Stelle nochmal was sende, funktioniert es nicht! ? Gruß Mathias
Mathias G. schrieb: > Um das Bit zu löschen muss eine 1 an die entsprechende Position > geschrieben werden! > > Ist das so richtig? Hallo, habe gerade festgestellt, es ist tatsächlich so. Naja, war ja immer von löschen die Rede... :-) Danke nochmal Gruß Mathias
Mathias G. schrieb: > Theor schrieb: >> @ Mathias >> >> Na Prima. >> >> Und schön, dass Du eine Rückmeldung gibst. > Irgendwie habe ich noch Schwierigkeiten, habe im AVR-GCC-Tutorial/Der > UART den Hinweis gefunden: > Um das Bit zu löschen muss eine 1 an die entsprechende Position > geschrieben werden! > > Ist das so richtig? > > Das würde erklären, das beim ersten senden funktioniert. Wenn ich später > in einer anderen Stelle nochmal was sende, funktioniert es nicht! ? > Gruß > Mathias Das ist richtig. Du musst eine 1 schreiben. Steht im Datenblatt auf Seite 138 Zitat: "... or it can be cleared by writing a one to its bit location." Das ist aber nicht grundsätzlich bei allen uC oder auch nur bei allen Peripherieeinheiten der AVRs so. Am besten immer ins Datenblatt schauen, wenn Du mir den Rat erlaubst.
Theor schrieb: > Das ist aber nicht grundsätzlich bei allen uC oder auch nur bei allen > Peripherieeinheiten der AVRs so. Am besten immer ins Datenblatt schauen, > wenn Du mir den Rat erlaubst. Habe ich wohl übersehen... :-( Gruß Mathias
Mathias G. schrieb: > Mathias G. schrieb: >> Um das Bit zu löschen muss eine 1 an die entsprechende Position >> geschrieben werden! >> >> Ist das so richtig? > Hallo, > habe gerade festgestellt, es ist tatsächlich so. Naja, war ja immer von > löschen die Rede... :-) > > Danke nochmal > Gruß > Mathias Darüber könnte ich und würde ich gerne eine längere Sprach-philosophische und -geschichtliche Vorlesung halten. Mache ich aber nicht. Glück gehabt. ;-) Am besten Du merkst es Dir einfach, dass Eingangssignale einer Mimik nicht zwingend auch mit dem inneren Zustand dieser Mimik übereinstimmen müssen. Das ist nur eine menschliche Assoziation, keine Regel. Schliesslich erscheint auf der Ampel auch kein, gedrückter metallener Knopf mit Pfeil, um Dir anzuzeigen, dass Du drauf gedrückt hast. Auch in der Ampelsteuerung selbst, gibt es das nicht.
> Um das Bit zu löschen muss eine 1 an die entsprechende Position > geschrieben werden! > Ist das so richtig? Mir fällt so schnell kein Flag-Bit ein, das nicht mit '1', oder mit Ausführung des Interrupts gelöscht wird. Im einfachsten Fall: Flag-Register lesen, die interessanten Bits mit AND herausfiltern und in's Flag-Register zurückschreiben. Es ist häufig günstiger, zugehörige Flag-Bits zu löschen, bevor ein Interrupt "enabled" wird. Sonst arbeitet die Interruptfunktion gleich mal veraltete Ereignisse ab, womit die erhoffte Reaktion auf folgende Ereignisse vermurkst wird...
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.