AVR Sendepuffer prüfen

OP #6180905
Lesenswert?

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....
#6180926
Lesenswert?

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 ;)
#6180947
Lesenswert?

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
}
OP #6180953
Lesenswert?

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.
#6180960
Lesenswert?

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?
#6180966
Lesenswert?

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
Gast #6180992
Lesenswert?

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.
OP #6181085
Lesenswert?

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
OP #6181279
Lesenswert?

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
Gast #6181285
Lesenswert?

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.
Gast #6181293
Lesenswert?

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.
Gast #6183040
Lesenswert?

> 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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren