Forum: Mikrocontroller und Digitale Elektronik Probleme beim parsen von UART string


von Markus M. (mmax)


Angehängte Dateien:

Lesenswert?

Hi,

Ich kämpfe jetzt schon seit zwei Tagen damit die empfangene Zeichenkette 
von einem GPRS Modul (SIM900 via uart) zu parsen. Wobei es hier nur mal 
darum geht bis zum CR/LF zu lesen und dann auszugeben. Vielleicht findet 
jemand von euch den Fehler. Im Anhang findet ihr meine uart Routinen, 
die ich hier verwende.

Prinzipiell wird bei jeder Eingabe am Computer via Terminal (via uart0) 
die Zeichenkette "AT+CSQ" an das GPRS Modul geschickt und dann die 
empfangenen Zeichen zurück ans Terminal geschrieben.

Setzt man das WORKING define auf 1, wird zeichenweise mit usart_getc() 
ausgelesen und man sieht am Terminal folgendes:
1
AT+CSQ
2
3
+CSQ: 4,0
4
5
OK

Das ist die korrekte Antwort laut Datenblatt. Jetzt versuche ich via 
usart_read() immer eine komplette Zeile zu lesen (WORKING auf 0 setzten) 
um diese in eckiger Klammer auszugeben. Da kommt dann folgendes daher:
1
[AT+CSQ]
2
[]
3
[Q: 4,0]
4
[]
5
[]

Die erste Zeile passt. Die zweite ist auch OK weil nur CR/LF aber dann 
kommt alles durcheinander. In der dritten Zeile werden Zeichen am Anfang 
abgeschnitten (nicht gelesen?) und das "OK" kommt nie an.

Bitte schaut mal meinen code durch - vielleicht fällt auch was auf. Der 
Fehler muss irgendwo in meinen Leseroutinen vom UART sein.


Hier meine main routine:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#include "usart.h"
5
6
#define WORKING 1
7
8
uint8_t tmp;
9
char buff2[64];
10
11
int main(void) {
12
    usart_init(USART0, 9600L);
13
    usart_init(USART1, 9600L);
14
15
    while (1) {
16
        
17
        if( usart_rx_available(USART0) ) {
18
            tmp = usart_getc(USART0);
19
            usart_write(USART1,"AT+CSQ\r\n");
20
        }
21
        
22
#if WORKING
23
        if (usart_rx_available(USART1)) {
24
            tmp = usart_getc(USART1);
25
            usart_putc(USART0, tmp);
26
        }
27
#else
28
        while( usart_rx_available(USART1) ) {
29
            usart_read(USART1, buff2, sizeof(buff2));
30
            
31
            usart_putc(USART0,'[');
32
            usart_write(USART0,buff2);
33
            usart_write(USART0,"]\r\n");
34
        }
35
#endif
36
    }
37
}

Danke,
Max

von Pandur S. (jetztnicht)


Lesenswert?

Dieses Vorgehen ist Schrott. Mit blockierend Lesen und Schreiben ist 
nichts. Vergiss das schnell mal. Das Standardvorgehen nennt man 
Zustandsmaschine. Eine zum Lesen und eine zum Schreiben. Ob mit oder 
ohne Interrupt kann man immer noch festlegen.

von Markus M. (mmax)


Lesenswert?

OK. Heisst ich soll zuerst mal alles rausschreiben und dann erst 
einlesen?

von Pandur S. (jetztnicht)


Lesenswert?

Nein die koennen parallel nebeneinander arbeiten. Das wichtige ist nicht 
zu warten.

von Andreas S. (Firma: Schweigstill IT) (schweigstill) Benutzerseite


Lesenswert?

Markus M. schrieb:
> OK. Heisst ich soll zuerst mal alles rausschreiben und dann erst
> einlesen?

Nein, das wäre exakt das Gegenteil von dem angesprochenen 
Zustandsautomaten.

Sinnvollerweise sollte die Kommunikation in beiden Richtungen 
zeichenweise erfolgen, wenn nicht durch die Puffergrößen des USARTs und 
ggf. eines Interrupthandlers sichergestellt wird, dass kein empfangenes 
Zeichen abhandenkommen kann, während der Sendevorgang nicht 
abgeschlossen ist.

Eine mögliche Vorgehensweise besteht darin, einen lokalen 
Nachrichten-FIFO anzulegen, in den Ereignisse wie z.B. ein empfangenes 
Zeichen oder auch andere externe Ereignisse eingetragen werden. 
Anschließend lässt man einen Zustandsautomaten auf diesen FIFO los, der 
die Ereignisse herausholt, abarbeitet und ggf. neue Ereignisse 
hinzufuegt. Sobald der FIFO leer ist, wird die Bearbeitung beendet, und 
das ganze Spiel beginnt von vorne.

Es gibt aber auch noch Unmengen anderer Realisierungsmöglichkeiten für 
Zustandsautomaten.

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.