Forum: Mikrocontroller und Digitale Elektronik Meine UART verschluckt sich- sieht jemand einen Fehler?


von Stephan (Gast)


Lesenswert?

Hallo!
In gutgläubiger Marnier habe ich folgenden Code "geschrieben".
Leider sind die ausgegebenen Strings (ab dem zweiten) nicht vollständig. 
Der FIFO arbeitet jedenfalls tadellos. Sieht jemand handwerkliche 
Fehler?


int main(void)
{
  init_stk600();
  while(1)
  {
     if ((UART0_RxHead != UART0_RxTail) && (uart0_complete == 
0))readout_uart0();
     if (uart0_complete == 1) uart0_ready();
  }
}


void readout_uart0 (void)
{
  while (!(UART0_RxHead == UART0_RxTail) && (uart0_complete == 0))
  {
  uart0_newchar = uart0_getc();
    if ((uart0_newchar != '\r') && (uart0_count < UART_RX_BUFFER_SIZE ))
    {
      uart0_array[uart0_count] = uart0_newchar;
      uart0_count++;
    }
    else
    {
      uart0_array[uart0_count] = '\0';
      uart0_count = 0;
      uart0_complete = 1;
    }
  }
}

void uart0_ready(void)
{
  uart0_puts(uart0_array); //oder den String anders bearbeiten
  uart0_complete = 0;
}

von Eumel (Gast)


Lesenswert?

Taktquelle?

von Stephan (Gast)


Lesenswert?

Eumel schrieb:
> Taktquelle?

Interner Oszilator des AT2560

von Eumel (Gast)


Lesenswert?

Stephan schrieb:
> Interner Oszilator des AT2560

Den kannste knicken. Du brauchst einen Quarz.

von Stephan (Gast)


Lesenswert?

Ich kann dem µC einen ununterbrochenen String mit 200 Zeichen schicken, 
er sendet ihn fehlerlos zurück. Nur wenn die FIFO ins Spiel kommt, 
hakts.
Spricht dass nicht für die Quali des intOC?

von Eumel (Gast)


Lesenswert?

Stephan schrieb:
> Ich kann dem µC einen ununterbrochenen String mit 200 Zeichen schicken,
> er sendet ihn fehlerlos zurück. Nur wenn die FIFO ins Spiel kommt,
> hakts.
> Spricht dass nicht für die Quali des intOC?

Nö, nur für Glück. Nimm einen anständige Taktquelle, ansonsten ist jede 
Fehlersuche vergebens.

von Stephan (Gast)


Lesenswert?

Fertig!
Stk600 sei dank ganz einfach, Ergebnis: gleiches Verhalten.

von Eumel (Gast)


Lesenswert?

Stephan schrieb:
> Fertig!
> Stk600 sei dank ganz einfach, Ergebnis: gleiches Verhalten.

Na, dann hast jetzt eine Fehlerquelle ausgeschlossen. Ist doch ein 
Schritt in die richtige Richtung :)

von Stephan (Gast)


Lesenswert?

Eumel schrieb:
> Ist doch ein
> Schritt in die richtige Richtung :)

Ha! Den Satz hab ich vor zwei Wochen schon mal gehört! (Da wurd ich 
Papa.) Ich hab das Gefühl, das wird heut nix mehr mit meiner UART. Zu 
viel BabyBier.

von Stephan (Gast)


Lesenswert?

Erläuterung:

Die Ausgabe auf die direkte Eingabe des ABC (abgeschlossen mit \r) 
lautet

abcdefghijklmnopqrstuvwxyz<\n>
abcvwxyz <\n>
 abdefghijklmnopqrstuvwxyz<\n>
abcvwxyz<\n>
abcdefghijklmnopqrstuvwxyz<\n>

von Oliver J. (skriptkiddy)


Lesenswert?

Ist dein Ringpuffer zu klein?

Gruß Oliver

von Karl H. (kbuchegg)


Lesenswert?

Stephan schrieb:
> Erläuterung:
>
> Die Ausgabe auf die direkte Eingabe des ABC (abgeschlossen mit \r)
> lautet

Gibst du das händisch ein, oder werden die Texte per Programm 
eingespielt?

von Stephan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Gibst du das händisch ein, oder werden die Texte per Programm
> eingespielt?

Die sende ich per HTerm in direkter Folge:
ABC...XYZ<13>ABC...XYZ<13>ABC...XYZ<13>

von Stephan (Gast)


Lesenswert?

Achso: mit der Größe des Ringbuffers habe ich schon gespielt, selbst 
wenn er 200Bytes groß ist, das gleiche.

von Karl H. (kbuchegg)


Lesenswert?

Stephan schrieb:
> Karl Heinz Buchegger schrieb:
>> Gibst du das händisch ein, oder werden die Texte per Programm
>> eingespielt?
>
> Die sende ich per HTerm in direkter Folge:
> ABC...XYZ<13>ABC...XYZ<13>ABC...XYZ<13>


Also händisch.
(Es geht darum abzuschätzen, ob es irgendwo eine race condition ist, die 
aufgrund Übertragungsgeschwindigkeit sichtbar wird. Denn wenn während 
des
uart0_puts(uart0_array);
der Sender weitersendet, dann muss die FIFO das aufnehmen können, weil 
ja keiner in dieser Zeit die Zeichen aus der FIFO abholt.
Mit händischer Eingabe ist das kaum zu machen. Aber ein Sendeprogramm 
schafft das natürlich mit links, wenn die FIFO zu klein dimensioniert 
ist.


Wie groß ist die FIFO eingestellt?
(in dem Codeausschnitt seh ich erst mal nichts. Kannst du mal alles 
posten?)

von Stephan (Gast)


Lesenswert?

Noch was:

Wenn ich einen GPS-Empfänger anschließe, der einen String mit zwei 
Stringzeilen sendet, nämlich

$GPGGA,120035.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*6C 
<\r><\n>
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02<\r><\n>

(danach ist 1s Pause)

kommt als Antwort zuerst

$GPGGA,120040.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*6E 
<\n>
<\n>

und anschließend nur noch

$G$GPGGA,120041.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000* 
6F<\n>
<\n>

von Stephan (Gast)


Lesenswert?

uart.h

  #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
  #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
  #define UART0_TRANSMIT_INTERRUPT  USART0_UDRE_vect
  #define UART0_RECEIVE_INTERRUPT   USART0_RX_vect
  #define UART0_STATUS   UCSR0A
  #define UART0_CONTROL  UCSR0B
  #define UART0_DATA     UDR0
  #define UART0_UDRIE    UDRIE0

  #define UART_RX_BUFFER_SIZE 300
  #define UART_TX_BUFFER_SIZE 300



ISR(UART0_RECEIVE_INTERRUPT)
{
    unsigned char tmphead;
    unsigned char data;
    unsigned char usr;
    unsigned char lastRxError;

    usr  = UART0_STATUS;
    data = UART0_DATA;

  lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
    tmphead = ( UART0_RxHead + 1) & UART_RX_BUFFER_MASK;    /* calculate 
buffer index */
    if ( tmphead == UART0_RxTail ) {
        lastRxError = UART_BUFFER_OVERFLOW >> 8;        /* error: 
receive buffer overflow */
    }
  else
  {
        UART0_RxHead = tmphead;        /* store new index */
        UART0_RxBuf[tmphead] = data;        /* store received data in 
buffer */
    }
    UART0_LastRxError = lastRxError;
}

von Uwe (de0508)


Lesenswert?

so so 300 Bytes Puffer und dann den Index per and berechnen wollen ?

von Karl H. (kbuchegg)


Lesenswert?

Stephan schrieb:

>
>   #define UART_RX_BUFFER_SIZE 300
>   #define UART_TX_BUFFER_SIZE 300


Wenn du schon bei Fleury Code klaust (wogegen ich nichts habe), dann 
musst du das auch konsequent machen.
Im Original heißt es nämlich
1
/** Size of the circular receive buffer, must be power of 2 */
2
#ifndef UART_RX_BUFFER_SIZE
3
#define UART_RX_BUFFER_SIZE 32
4
#endif

und das 'must be a power of 2' steht da nicht ohne Grund.

von Stephan (Gast)


Lesenswert?

Oh. Geändert auf 200. Es hat sich was an der Ausgae getan:

$GPVTG$GPGGA,095701.060,5417.2093,N,01006.3587,E,1,09,1.0,36.1,M,41.8,M, 
,0000*60<\n>

von Uwe (de0508)


Lesenswert?

Und auch <=256 sein.

von Stephan (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> und das 'must be a power of 2' steht da nicht ohne Grund.

Grübelgrübel.. das hab ich jetzt flux mit "Vielfachem von zwei" 
übersetzt. Stimmt das nicht?

von Uwe (de0508)


Lesenswert?

gemeint ist damit 2 hoch n , 2^n.
Das sind die Zahlen 2,4,8,16,32,..

von Udo S. (urschmitt)


Lesenswert?

Stephan schrieb:
> In gutgläubiger Marnier habe ich folgenden Code "geschrieben".

Karl Heinz Buchegger schrieb:
> Wenn du schon bei Fleury Code klaust (wogegen ich nichts habe)

Dann sollte er zumindest sagen wo er den Code herhat und nicht behaupten 
ihn selbst geschrieben zu haben.
Das hätte dir und anderen dann ggf. einiges an Zeit erspart.

von Stephan (Gast)


Lesenswert?

Udo Schmitt schrieb:
> Dann sollte er zumindest sagen wo er den Code herhat und nicht behaupten
> ihn selbst geschrieben zu haben.

Nicht ohne Grund habe ich die Anführungszeichen gemacht.
Dass das bei Fleury geklaut ist -dacht ich- sieht man.

Update: mein geklauter Code funktioniert nun tadellos.

Aber Frage zum Handwerk: mir gefällt selbst nicht, die Abfrage, ob der 
Buffer teilgefüllt ist, in der mainloop unterzubringen. Macht das Sinn, 
diese ständig und unsichtbar durch einen Timer zu machen?

von Karl H. (kbuchegg)


Lesenswert?

Stephan schrieb:

> Nicht ohne Grund habe ich die Anführungszeichen gemacht.
> Dass das bei Fleury geklaut ist -dacht ich- sieht man.

Scroll zum Eröffnungsposting.
Woran soll man da erkennen, dass du den Fleury Code umgearbeitet hast.
Das einzige was da steht ist, dass deine FIFO tadellos arbeitet, was ja 
dann wohl doch nicht der Fall war.

Warum hast du eigentlich den Fleury Code umgearbeitet?
So wie ihn Peter veröffentlicht hat, funktioniert der tatsächlich 
wunderbar. Eventuell muss man einen neueren Prozessor einarbeiten, aber 
mehr muss man nicht tun, um eine erstklassige und gut funktionierende 
UART zu haben-


> Aber Frage zum Handwerk: mir gefällt selbst nicht, die Abfrage, ob der
> Buffer teilgefüllt ist, in der mainloop unterzubringen. Macht das Sinn,
> diese ständig und unsichtbar durch einen Timer zu machen?

Was soll denn der Quatsch schon wieder?
Dein GPS ballert dir 1 mal pro Sekunde 80 Zeichen bei 4800 Baud rüber. 
Das kann eine 128-er FIFO locker zwischenspeichern und wahrscheinlich 
brauchts noch nicht mal das. Denn wenn das Programm die Daten nicht 
schneller wieder lowird (weitergibt, verarbeitet) als sie vom GPS 
geliefert werden, dann hilft auch die größte FIFO nix.

Das einzige was mir nicht gefällt, das ist dass du da hemmungslos auf 
Head und Teil in main zugreifst. Das hat niemanden zu interessieren, wie 
das UART MOdul seine Zeichen verwaltet. Maximal gibt es im UART MOdul 
eine Funktion mit Namen "cAvailable" (das c ist das Pendant zum c in 
getc), die die main() benutzen kann. Aber eigenttlich ist die Variante 
die Fleury vorgegeben hat eine gute Lösung, dass die getc Funktionen 
einen Returnwert hat, aus dem man ablesen kann, ob ein Zeichen vorliegt 
oder nicht.

von Uwe (de0508)


Lesenswert?

@Karl Heinz Buchegger

damit kann der Thread ja geschlossen werden - der Fehler wurde gefunden.

von Stephan (Gast)


Lesenswert?

Ja, kann er.
Vielen Dank!

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.