Forum: Mikrocontroller und Digitale Elektronik längerer Text per UART/falscher ansatz?


von Christian Schreiber (Gast)


Lesenswert?

Hallo,

ich versuche gerade eine Lüftersteuerung zu schreiben, die per Telnet 
den aktuellen Zustand(Temperatur/Lüfterdrehzahl) ausgibt und 
Einstellungen für die Regelung entgegennimmt.

Zur Ausgabe der Daten möchte ich per UART einfach Zeilenweise den Text 
senden. Da ich auch Zahlenwerte aus Variablen mitsenden möchte, habe ich 
mich für sprintf() entschieden.
Die Ausgabe läuft so ab:
char text[80];
//uart_putc(12);//FormFeed. Clearen des Terminals
sprintf(text,"\n\rWakue-Steuerung Version 0.91\n\r\n\r");
uart_putstring(text);
sprintf(text,"Temperaturen:\n\r");
uart_putstring(text);

Das Uart ist Interruptbasierend und ich hab die Funktionen von 
Roboternetz 
(http://www.roboternetz.de/wissen/index.php/UART_mit_avr-gcc#Mit_Interrupts). 
Dahinter steht ein FIFO Buffer, in den die zu sendene Zeichenkette 
geschoben wird und dann nach und nach gesendet wird.

Ich habe nur kommischerweise sehr Merkwürdiges Verhalten. Einige Teile 
werden problemlos ausgegeben, aber manchmal kommt nur Müll. Es ist auch 
teilweise so, dass der erste Teil wunderbar am Terminal ankommt und 2 
Zeilen später ist die Formatierung hin(teilweise mit Zeichen, die nicht 
da sein sollten)
Ich kann dabei aber kein Muster erkennen.

Z.B. erzeugt
sprintf(text,"Drehzahlregelung\n\r");
uart_putstring(text);
sprintf(text,"Bottom: 30C = 50p \n\rUpper: 60C = 100p\n\r");
im moment gerade
"Botto00p00Wakue-Steuerung Version 0.91) pDrae"
und andere Zeilen produzieren keinen output.

Bin ich vielleicht auf dem flaschen Weg? Gibts eine andere, einfachere 
Lösung? Oder sollte ich das Uart nicht Interruptgesteuert machen?

Danke schonmal für jeden Tipp, denn mir gehen langsam die Ideen aus.
Christian

von Hansi L. (fabian87)


Lesenswert?

baudrate richtig?
hast du krasse störsender neben deiner leitung?

von Christian Schreiber (Gast)


Lesenswert?

Bautrate ist richtig

Störsender.... hmm meinen Rechner, sonnst nichts

Christian

von Chief Brady (Gast)


Lesenswert?

Ich habe die UART-Routinen nur überflogen, aber kann es sein, dass der 
FIFO zu klein ist? Soll heissen, kann es sein, dass du schneller Texte 
in den Buffer schreibst als gesendet werden können?

Ich würde zum Testen mal vor jedem 'uart_putstring(text)' eine 
Warteschleife einbauen.

von Christian Schreiber (Gast)


Lesenswert?

sehr guter Tipp ...

ich hab mal die Bufferlänge hochgesetzt und sieheda: die Fehler 
verschwinden. Nur muss ich jetzt meine uart routine umändern, denn ich 
kann ja nicht die Bufferlänge auf 300 bis 400 byte setzen.
Damit blockiere ich doch dann den ganzen Ram,oder sehe ich das falsch?

vielen Dank
Christian

von Chief Brady (Gast)


Lesenswert?

Ich schätze mal, dein 'uart_putstring()' ist die 'uart_puts()' aus den 
UART-Routinen. In dieser wird 'uart_putc' verwendet, um die einzelnen 
Zeichen des Strings in den FIFO zu schreiben. 'uart_putc' gibt einen 
wert zurück, der angibt, ob das Zeichen in den FIFO geschrieben wurde 
oder ob der Puffer voll ist (steht so im Text). Dieser Wert wird aber 
nicht ausgewertet. Das funktioniert so nur mit kurzen Texten.

Wenn du genügend RAM hast, würde ich den Puffer schrittweise 
vergrössern, bis es passt. 300 Byte weden wohl nicht gebraucht, denke 
ich. Ich tippe mal so auf 60 Byte.

Alternativ kannst du natürlich den Return-Wert von 'uart_putc' auswerten 
und immer warten, bis der FIFO wieder frei ist.
CB

von Christian Schreiber (Gast)


Lesenswert?

Ja, meine uart_putstrin() ist die uart_puts() ich fand, dass muss man 
zur besseren Kennzeichnung umbennenen.

Ich hab mich durch die Funktionen gekwühlt und hab das ganze anders 
gelöst.
ich hab die uart_putc() um folgendes erweitert

fifo_t *fn = &outfifo;
while(fn->count >= fn->size){;};

also die Abbruchbedingung aus dem Fifo verwendet.
so wartet er nun, wenn der Buffer voll ist. Ich denke, so ist es am 
einfachsten, da ich mir keine Gedanken über die Auswertung machen muss.

Ich würd es ja auch im RN angeben, doch irgendwie hab ich keine Lust 
mich da jetzt erst groß anzumelden.

Aber dir erstmal vielen Dank
hast mein Wochenende gerettet :)
Christian

von Chief Brady (Gast)


Lesenswert?

> hast mein Wochenende gerettet :)
bitte bitte...


Ich hätte dass vielleicht so gemacht:

Die Zeile

  int ret = fifo_put (&outfifo, c);

in 'uart_putc' ersetzt durch

  int ret;
  do
  {
    ret = fifo_put (&outfifo, c);
  }
  while (ret=0);

Sollte doch auch gehen, oder? Aber wenn deine Lösung funktioniert...

BC

von Christian Schreiber (Gast)


Lesenswert?

also zu aller erst, ich will nicht besserwisserisch sein, nur zum 
Verständniss, aber ich glaube nicht,
denn es wird immer zuerst einmal versucht das Zeichen in den Buffer zu 
schieben. Schlägt das fehl, ist das Zeichen verlohren.
Es geht gut, bis einmal -1 zurückgeliefert wird.
dann bricht die Schleife ab, und das Zeichen wird verworfen, oder?
Also verhindert die Schleife zwar effektiv den Überlauf des Puffers, 
doch die Ausgabe wird dennoch verfälscht.

Oder liege ich da gerade daneben?
Christian

von Chief Brady (Gast)


Lesenswert?

Es wird versucht, ein Zeichen in den FIFO zu schreiben

 ret = fifo_put (&outfifo, c);

Wenn ret 0 ist, war der FIFO voll und es wird weiter versucht, bis ret 
nicht mehr 0 ist

  while (ret=0);

ret wird 1, wenn das Zeichen im FIFO ist. Warum sollte das Zeichen 
verloren gehen? Ich denke nicht, das die Routine fifo_put das Zeichen 
('c') ändert (weiss ich allerdings nicht, da ich fifo.h nicht kenne)

CB

von Peter D. (peda)


Lesenswert?

Ein Returnwert beim Senden ist Blödsinn, wer soll den denn auswerten ?

Eine Sende-FIFO muß einfach immer solange warten, bis wieder Platz im 
Puffer ist. Nur so geht nichts verloren.


Eine andere Möglichkeit wäre noch eine Funktion, die die aktuelle freie 
Pufferlänge zurückgibt.
Dann kann man mit der Ausgabe solange warten, bis auch genügend Platz 
ist und die Zwischenzeit anderweitig nutzen.
Trotzdem sollte die Sendefunktion warten, falls man sich mal mit der 
benötigten Paketlänge verschätzt hat.


Lieber die Daten etwas später senden, als total falsch.


Peter

von Chief Brady (Gast)


Lesenswert?

> Eine Sende-FIFO muß einfach immer solange warten, bis wieder Platz im
> Puffer ist. Nur so geht nichts verloren.

Ja, aber genau dieses warten ist anscheinend nicht implementiert, was 
ich mit meinem Vorschlag nachholen wollte. Oder übersehe ich da 
irgendetwas?

von Christian Schreiber (Gast)


Lesenswert?

Nabend

ich glaub ich lag falsch.
Ich bin davon ausgegangen, dass -1 zurückgeleifert wird, wenn die 
Funktion nicht erfolgreich war, deshalb hats keinen Sinn für mich 
gemacht.

Hast also Recht.
Habs aber so implementiert, wie oben und es läuft soweit.

Wünsch euch noch ne gute Nacht und danke :)
Christian

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.