Forum: Mikrocontroller und Digitale Elektronik FIFO: Problem beim lesen wenn UART-Initialisierung in anderer Datei


von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Forum,
ich hab da ein kleines Problem mit meinem FIFO-Buffer. Bereits gestern 
konnte ich ein Teil des Problems mit eurer Hilfe lösen.

Folgendes: Mit Hilfe der UART Lib von Peter Fleury will ichserielle 
Daten empfangen und sofort wieder versenden. Mein Code hab ich zunächst 
in eine Datei (new2) geschrieben und es funktioniert. Da die Übertragung 
meiner seriellen Daten (Gerät --> uC) länger dauert, als die Zeitspanne, 
in
denen mein uC den FIFO leert, werden dazwischen 0x00 gesendet. Diese 
filtere ich raus, sodass ich am Hyperterminal nur meine vom Gerät 
gesendeten Strings sehe. Das funktioniert soweit.

Nun wollte ich aber die UART Initialisierung in eine separate Datei 
ablegen (new10), sodass ich sie auch in andere Projekte einbinden kann. 
Allerdings klappt das noch nicht so ganz. Nun ist es aber so, dass 
zwischen den Strings plötzlich nicht mehr 0x00 sondern Zeichen wie 0x03, 
0x04, 0x06 etc. gesendet werden.

Zudem erhalte ich dann noch die Warnmeldung
../new10uart.c:52: warning: 'data' may be used uninitialized in this 
function

Es wäre nett wenn mir jemand weiterhelfen könnte...ich weiß wirklich 
nicht mehr weiter!
Grüße,
Klaus

von Guru (Gast)


Lesenswert?

Ich bin gerade zu faul die Zeile 52 zu suchen. Markiere die mal bitte.

Diese Mimik mit dem FIFO Head und Tail sieht merkwürdig aus, wenn die 
Buffergrössen keine Zweierpotenzen sind. Ich kenne mich mit der Lib von 
Peter Fleury nicht aus, habe mal reingeguckt und siehe da, gleich am 
Anfang von uart.c steht:

"    The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
    the buffer size in bytes. Note that these variables must be a
    power of 2."

von Guru (Gast)


Lesenswert?

Der tiefere Grund ist, dass P. F. mit der Maskierungsoperation eine 
Modulo-Arithmetik erreicht. Er ersetzt also
1
tmp_head = (uart0_rx_head + 1 ) % UART0_RX_BUFFER_MASK;

durch
1
tmp_head = (uart0_rx_head + 1 ) & UART0_RX_BUFFER_MASK;

Der Grund ist, das letzteres schneller geht.

Das ist nun der zweite Fall wo Dir das lesen der Unterlagen (einmal ein 
C-Buch, einmal die Beschreibung der Lib die Du einsetzen willst) 
geholfen hätte. Ich bitte Dich höflich, Dich in Zukunft mehr vorab zu 
informieren.

von Klaus (Gast)


Lesenswert?

Hallo Guru,Danke für deine Antwort. Das mit der Maskierung ist mir 
durchaus bewusst, hab das im Code aber leider vergessen abzuändern. 
Sorry!

Allerdings glaub ich den Fehler gefunden zu haben. Allerdings weiß ich 
nicht ob meine Interpretation dazu richtig ist.

Die Funktion getc() wartet nicht bis ein Zeichen kommt. Gut, hier hab 
ich nur den Fall ( uart0_rx_head != uart0_rx_tail ) definiert, nicht 
aber wenn (uart0_rx_head == uart0_rx_tail) ist. Meine Annahme ist, dass 
mein uC aus diesem Grund willkürliche Zeichen sendet und teilweise 
abschmiert.

unsigned int uart0_getc( void )
{
  unsigned char tmp_tail;
  unsigned char data;


  if( uart0_rx_head != uart0_rx_tail )
  {
    tmp_tail = ( uart0_rx_tail + 1 ) & UART0_RX_BUFFER_MASK;
    uart0_rx_tail = tmp_tail;
    data = uart0_rx_buffer[tmp_tail];
  }
  return data;
}

Aus diesem Grund muss ich für den Fall das uart0_rx_head == 
uart0_rx_tail ist einen Rückgabewert festlegen, das meinem Programm 
sagt, dass keine Zeichen vorhanden sind. Ich habe hier nun mal den 
Rückgabewert 0 festgelegt.
Sprich in meinem Hauptprogramm kann ich nun mit if(getc != 0x00) die 
Nullen rausfiltern und erhalte meine Strings.

unsigned int uart0_getc( void )
{
  unsigned char tmp_tail;
  unsigned char data;


  if( uart0_rx_head == uart0_rx_tail )
  {
    return 0;
  }
else
{
  tmp_tail = ( uart0_rx_tail + 1 ) & UART0_RX_BUFFER_MASK;
  uart0_rx_tail = tmp_tail;
  data = uart0_rx_buffer[tmp_tail];
}
  return data;
}

Passt meine Überlegung soweit? Ich bin noch Anfänger und würde mich über 
jeden Tipp und Hinweis freuen.Grüße

von Guru (Gast)


Lesenswert?

>hab das im Code aber leider vergessen abzuändern. Sorry!

Eine Entschuldigung ist nicht nötig. Aber deswegen gibt es in der 
Netiquette den Hinweis immer den Code zu posten, mit dem Du auch 
arbeitest.

Schau Dir den Code von Peter Fleury an. Da ist auch ein getc dabei und 
Du kannst sehen, was wann passiert.

Du schriebst doch, dass Du die Lib von Peter Fleury verwendest. Warum 
erfindest Du jetzt getc neu? Warum musst Du nun den Rückgabewert nochmal 
anders setzen als in dem Code von Peter? Wenn Du schon Anfäger bist, 
dann lass doch den Code so wie er ist und versuche erstmal ihn zu 
verstehen. Wenn Du ihn verstehst, dann sind auch Deine Änderungen daran 
sinnvoller und Deine Fragen, verzeihe mir bitte, nicht so unnötig.
Vor allem: Was ist wenn Du mal eine 0x00 senden/empfangen willst?

Ich muss zugegeben, dass ich jetzt noch weniger Geduld habe als vorhin.
Es fällt mir schwer zu akzeptieren, das Du einerseits Peter Fleurys Lib 
zu verwenden vorgibst, aber dann hier Fragen stellst, die unter der 
Voraussetzung unnötig sind.

Wenn dann noch so Dinger kommen, wie: "Ach, sorry, das ist garnicht der 
Code", dann nervt das zusätzlich.

von Guru (Gast)


Lesenswert?

Hmm. Veränderst Du deswegen die Fleury-Lib?

>Da die Übertragung meiner seriellen Daten (Gerät --> uC) länger dauert, als >die 
Zeitspanne, in denen mein uC den FIFO leert, werden dazwischen 0x00 >gesendet.

Das musst Du mal genauer erklären.
Warum ist das ein Problem, wenn der uC die Daten schneller ausliest, als 
der PC sie sendet?
Normalerweise ist das kein Problem. Wenn nicht genügend Daten da sind, 
damit der uC damit was anfangen kann, dann lass ihn einfach warten, bis 
genug Daten da sind. Das mit den Dummy-Nullen ist unnötig.

von Klaus (Gast)


Lesenswert?

Ich hab mich da in irgend etwas verfangen und rein gesteigert. Im Grunde 
macht es wirklich keinen Sinn die Lib zu verändern. Allerdings kann ich 
beim Auftreten von....

#define UART_FRAME_ERROR      0x0800              /* Framing Error by 
UART       */
#define UART_OVERRUN_ERROR    0x0400              /* Overrun condition 
by UART   */
#define UART_BUFFER_OVERFLOW  0x0200              /* receive ringbuffer 
overflow */

..meistens programmtechnisch ja eh nicht eingreifen. Allerdings kann ich 
sagen, dass wenn diese Fehler auftreten der String im Buffer nicht für 
die weitere Verarbeitung verwendet werden soll, was natürlich wiederum 
eine zusätzliche Sicherheit bedeuten würde.

Mit der 0x00 hast du eigentlich auch Recht. chars haben ja eine 
Wertebereich von 0...255 mit...

#define UART_NO_DATA          0x0100              /* no receive data 
available   */


...würde ich also drüber liegen und es käme zu keiner 
Fehlinterpretation. Wenn ein String mit Leezeichen gesendet wird, hab 
ich dann ein Problem.

Danke für deine Antwort!

von Guru (Gast)


Lesenswert?

>Wenn ein String mit Leezeichen gesendet wird, hab
>ich dann ein Problem.

Was für ein Problem hast Du dann?

Was Dir fehlt, denke ich, ist ein Konzept für das Protokoll und ein 
Schema für den Ablauf der Empfangsseite. Oder wie siehst Du das?

Ich würde Dir empfehlen, einfach mal die P.F.-Lib (soweit wie möglich im 
Originalzustand) mit einem simplen Echo zum laufen zu bringen.

Das übliche wäre auf der Empfängerseite eine Zustandsmaschine, die mit 
dem Startzustand beginnend, auf ein Startzeichen im Empfangsbuffer 
wartet, dann in den nächsten Zustand übergeht und dort Zeichen sammelt 
bis die richtige Anzahl an Zeichen empfangen worden ist. In einem 
dritten Zustand verarbeitest Du die Daten und gehst wieder in den 
Startzustand.

(Man kann das parsen der Empfangsdaten auch als Zustände implementieren, 
aber das ist erst die nächste Komplexitätsstufe denke ich).

Mit dieser Mimik nutzt Du den FIFO genau wie er gedacht ist. Nämlich zur 
Entkopplung der Erzeugungsgeschwindigkeit der Daten und deren Konsum 
durch den uC.

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.