Forum: Mikrocontroller und Digitale Elektronik UART-Übertragung - Wartezeit?


von Björn Moosmann (Gast)


Lesenswert?

Hallo zusammen,

ich habe ein kleines Problem... Und zwar möchte ich an meinen
Mikrocontroller (AT90S8515) ein Zeichen senden, worauf mir dann der µC
mehrere Bytes zurücksenden soll.
Das vom PC per Hyperterminal gesendete Zeichen kommt an, die
zurückgeschickten Daten sind jedoch verstümmelt.
Dies liegt wohl daran, dass die UART nicht so schnell senden kann wie
ich Daten ins UDR schiebe. Also habe ich versucht mittels TXC bzw.
UDRE-Bit zu warten, bis die UART wieder frei ist. Beides jedoch ohne
Erfolg. Mittels einer festen Zeitverzögerung klappt es.
Was muß ich tun, damit auch die saubere Lösung mit Ausertung der
Statusbits funktioniert?

Vielen Dank!
Björn


Mein Sourcecode:

unsigned char x = 0;
while (RX_Text[x] != '\0')
{
  UDR = RX_Text[x];
  x++;

  unsigned char y = 4;    //mit manueller Schleife funktionierts
  while (y >0)
  {
                time();
    y--;
  }
//  while (!TXC)           // Bit-Auswertung geht nicht... :-(
//  {
//    asm volatile ("nop");
//  }
}

von Anton W. (antonwert)


Lesenswert?

Versuch doch mal die Daten im UART-Data-Register-Empty-Interrupt zu
senden (immer eins pro Interrupt). Dann muss es klappen.
Tipp: falls das Senden beendet ist einfach Interrupt deaktivieren.

von A.K. (Gast)


Lesenswert?

> while (!TXC)

TXC ist bloss die Bitnummer im Register, diese zeile ist also
äquivalent zu sowas wie "while(1)".

von Michael U. (Gast)


Lesenswert?

Hallo,

ich habe von C keine Ahnung, aber die Abfrage von UDRE geht hier schon
immer.

uart_send:
        sbis    UCSRA,UDRE                  ; Send-Register leer ?
        rjmp    uart_send                    ; nein

        out     UDR,TEMP_A
        ret

Gruß aus Berlin
Michael

von Björn Moosmann (Gast)


Lesenswert?

@ A.K.

Vielen Dank, jetzt klappt es!

Hab die entsprechende Zeile geändert:

    while (!USR && BITPOS_6)

wobei BITPOS_6 mit 0x40 definiert ist.

Gruß
Björn

von A.K. (Gast)


Lesenswert?

Erstaunlich, dass das funktioniert. Guck noch mal in dein C Buch rein.
Beispielsweise unter den Operatoren "&&" und "&".

Empfehlen würde ich eher die Version
  while (!(USR & BITPOS_6))
wobei UDRE (oder was auch immer für ein Bit das ist) sicher lesbarer
ist als BITPOS_6.

von Olaf K. (olaf_k)


Lesenswert?

Übrigens macht man sowas besser mit einem FIFO (= Ringpuffer) und per
Interrupt.
Prinzip: Alle zu sendenden Zeichen kommen in den FIFO, und der
UDRE-Interrupt wird freigegeben. In der UDRE-ISR wird jedesmal, wenn
der UART "frei" ist, ein Zeichen aus dem FIFO geholt und ins UDR
geschrieben. Wenn der FIFO leer ist, deaktiviert sich der Interrupt
selbst.
Vorteil: Man schreibt nur einmal die Daten in den FIFO, den Rest macht
die ISR dann von alleine, d.h. man verschwendet keine Zeit mit
Warteschleifen. Der µC kann z.B. auch schon wieder neue Daten empfangen
und verarbeiten, während er noch "alte" Zeichen aus dem FIFO sendet.

MfG Olaf

von A.K. (Gast)


Lesenswert?

@Olaf: Mal sachte, er macht grad seine ersten Gehversuche.

von inoffizieller WM-Rahul (Gast)


Lesenswert?

>while (!USR && BITPOS_6)
>Erstaunlich, dass das funktioniert.

!USR invertiert USR logisch: Alles, was ungleich 0 (wahr) ist, wird zu
0 (falsch).
BITPOS_6 ist immer wahr (könnte man sich also auch sparen).
Wenn also in USR irgendwas passiert (also irgendein Bit gesetzt
wird), wird die Schleife verlassen.

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
Noch kein Account? Hier anmelden.