Moin,
ich habe Probleme beim Empfangen von Strings auf meinem ATMEGA168.
Hintergrund: Ich versende vom PC mehrere Strings mit Header und /crlf am
Ende an den Controller. Mit Hilfe der Header sollen verschiedene
Aktionen ausgeführt werden. Zum Testen habe ich zwei Strings genommen,
die einmalig per Knopfdruck im Abstand von 250ms versendet werden.
Der erste String wird richtig übernommen, nur der zweite ist immer Null.
Als Empfangsroutine nutze ich die hier in der Wiki eingetragene
Funktion. Der restliche Quellcode sieht wie folgt aus:
Es lohnt sich, Variablen die als Kommunikation zwischen ISR und
Hauptprogramm dienen, als 'volatile' zu erklären. Denn der Compiler
sieht im Unterprogramm der ISR erstmal ein Software Stückchen, das nie
ausgeführt wird. Im Hauptprogramm wird z.B. 'uart_str_complete' immer
nur gelesen, und das erkennt der Compiler.
Also
1
volatileuint8_tuart_str_complete=0;
2
volatileuint8_tuart_str_count=0;
3
volatilecharuart_string[UART_MAXSTRLEN+1]="";
sollte dich weiterbringen. Leider schreibst du ja nix über das
Verhalten der Test LEDs.
Es könnte auch sein, das es sich lohnt, das alles zu vereinfachen. Zum
Stellen der Uhr würde auch ein 'h0945' String reichen. die ersten beiden
Stellen sind dann Stunden und die letzten die Minuten.
BHour ist nur 10 Zeichen lang, Received_String kann aber bis 20 Zeichen
enthalten.
Welche Strings überträgst du denn?
Was willst du damit immer erreichen?
1
strcpy(Received_String," ");
Was soll das Leerzeichen im String? Wenn du den String leer machen
willst, dann schreibe einfach ein \0 rein. Aber das ist eigentlich gar
nicht notwendig, weil der Inhalt ja eh immer überschrieben wird.
1
Received_String[0]=0;
µC haben wenig Speicher, warum verschwendest du ihn dann?
1
charBMinute[10],BHour[10],BSecond[10];
du brauchst doch immer nur einen davon, dann kann man immer die gleiche
Variabel nutzen. Es ist sogar so, das du es überhaupt nicht bracuhst.
Matthias S. schrieb:> Es könnte auch sein, das es sich lohnt, das alles zu vereinfachen. Zum> Stellen der Uhr würde auch ein 'h0945' String reichen.
Daran hatte ich auch schon gedacht, nur fehlt mir die richtige Idee, um
die Stunden daraus zu extrahieren. Die Minuten wären kein Problem, da
kann ich ja einfach die entsprechende Anzahl von Stellen Springen. Ich
könnten bei den Stunden ja zweimal den String mit strcpy bearbeiten,
einmal von vorne gezählt und einmal von hinten. Aber es muss doch auch
einfacher gehen.
Die Leds machen was sie sollen. ich erhalte auch die Ausgabe der
Variablem auf dem PC
Peter II schrieb:> Wenn du den String leer machen> willst, dann schreibe einfach ein \0 rein. Aber das ist eigentlich gar> nicht notwendig, weil der Inhalt ja eh immer überschrieben wird.
Stimmt, aber ich sende nicht immer einen String. Das heißt ich würde
immer in einer der if-Abfragen landen.
Johann L. schrieb:> Argumente von strstr sind "Heuhaufen" und "Nadel", nicht umgekehrt: In> einem Heuhaufen "m" wirst nicht viele Nadeln finden :o)
Sehr schöner Vergleich, der stimmt. Habe ich jetzt korrigiert.
Auf den ersten Blick schein es jetzt zu funktionieren. Ich muss noch mal
weiter testen.
Vielen Dank schon einmal für die Tipps.
Marco G. schrieb:> Matthias S. schrieb:>> Es könnte auch sein, das es sich lohnt, das alles zu vereinfachen. Zum>> Stellen der Uhr würde auch ein 'h0945' String reichen.>> Daran hatte ich auch schon gedacht, nur fehlt mir die richtige Idee, um> die Stunden daraus zu extrahieren.
Du weißt, dass das erste Zeichen der Befehl ist, das zweite und dritte
Zeichen die Stunden, das vierte und fünfte Zeichen die Minuten. Außerdem
weißt du, dass ein C-String ein Array aus Zeichen ist, und dass der
ASCII-Code für die Ziffern aufsteigend ist und mit '0' anfängt. Fertig
ist der simple Parser:
Vermutlich ist es sinnvoll, noch abzuprüfen, ob Received_String[1..4]
auch Ziffern sind (d.h. zwischen einschließlich '0' und '9' liegen) und
ob der String auch vollständig empfangen wurde.
Nachtrag: BCD ist übrigens des Teufels. ;-)
Du brauchst den String nicht vom UART extra kopieren, weil du nach dem
Parsen sämtliche Informationen daraus extrahiert hast und eleganter (in
Integern) speicherst. Der String kann danach weg.
Den Parser selbst kannst du übrigens - je nach Komplexität der Eingaben
- auch direkt im UART-Interrupt als Zustandsautomat implementieren.
Jedes Zeichen wird direkt beim Empfang ausgewertet und wenn der String
vollständig war, wird das Hauptprogramm informiert. Damit bekommst du
keine Probleme, wenn jemand zehntausend 'X' schickt, denn die werden
alle nacheinander ignoriert.