Forum: Compiler & IDEs Kompletten *Buffer++ auslesen


von Simon (Gast)


Lesenswert?

ich fuege einem Buffer immer etwas hinzu.

char* Buffer;

if (booler.gpsstart == 1 && StringLen < 5) {
 *Buffer++ = c;
 StringLen++;
 setData(c);
}


jetzt wuerde ich gerne abfragen ob die ersten 5 zeichen des Buffers
GPGGA heiszen.

so z.B.
if (Buffer == "GPGGA") {

}


Es geht mir dabei darum, folgende GPS Daten die ich per UART bekomme,
in einzelne Teile zu zerlegen, um es in getrennte Variablen zu packen.
(Navilock NL501-TTL)

$GPGGA,053740.000,2503.6319,N,12136.0099,E,1,08,1.1,63.8,M,15.2,M,,0000* 
64

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:
> ich fuege einem Buffer immer etwas hinzu.
>
> char* Buffer;

Ich hoffe mal, dass das nicht alles ist :-)

> jetzt wuerde ich gerne abfragen ob die ersten 5 zeichen des Buffers
> GPGGA heiszen.
>
> so z.B.
> if (Buffer == "GPGGA") {
>
> }

[C]
  if( strncmp( Buffer, "GPGGA", 5 ) == 0 )
[/C

> Es geht mir dabei darum, folgende GPS Daten die ich per UART bekomme,
> in einzelne Teile zu zerlegen, um es in getrennte Variablen zu packen.
> (Navilock NL501-TTL)
>
> $GPGGA,053740.000,2503.6319,N,12136.0099,E,1,08,1.1,63.8,M,15.2,M,,0000* 64

per strtok am , aufbrechen und umkopieren.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Simon schrieb:
> ich fuege einem Buffer immer etwas hinzu.
>
> char* Buffer;
>
> if (booler.gpsstart == 1 && StringLen < 5) {
>  *Buffer++ = c;
>  StringLen++;
>  setData(c);
> }
>
>
> jetzt wuerde ich gerne abfragen ob die ersten 5 zeichen des Buffers
> GPGGA heiszen.
>
> so z.B.
> if (Buffer == "GPGGA")

Nein. Schau dir strncmp aus der libc an!

Ausserdem veränderst du Buffer, d.h er zeigt nach Abspeichern des 
Strings dahiner !

von Simon (Gast)


Lesenswert?

mmh das funzt so nicht,

if( strncmp( Buffer, "GPGGA", 5 ) == 0 )

ist immer ungleich 0

von Ahem (Gast)


Lesenswert?

>mmh das funzt so nicht,

Das funktioniert schon, aber das immer was ungleich 0 rauskommt, 
bedeutet,  das da eben nicht "GPGGA" am Anfang des Buffers steht. Du 
musst also rausfinden, warum das so ist. Der Vergleich ist in Ordnung.
Gib doch mal den String aus, dann weisst Du was drinsteht.

von Ahem (Gast)


Lesenswert?

Das war doch so ein '$'-Zeichen in dem String bei Deinem ersten Posting.

von Karl (Gast)


Lesenswert?

Du musst in "Buffer" ja auch einen Zeiger auf den Anfang des Strings 
übergeben.

von Ahem (Gast)


Lesenswert?

>Du musst in "Buffer" ja auch einen Zeiger auf den Anfang des Strings
>übergeben.

Buffer ist schon der String. Man kann "darin" nicht einen Zeiger 
übergeben.
Das erste Argument von strncmp ist der Zeiger auf einen String. Soweit 
ist das korrekt.

von Simon (Gast)


Lesenswert?

das $ hab ich vorher schon raus genommen.


1
 while( 1 ) { 
2
3
     c = uart_getc();
4
    if ( c & UART_NO_DATA )
5
        {
6
            
7
        }
8
        else
9
    {
10
    //lcd_puts(0x4B);
11
    if (booler.gpsstart == 1 && StringLen < 5) {
12
      *Buffer++ = c;
13
      StringLen++;
14
      setData(c);
15
    }
16
17
18
     if( strncmp( Buffer, "GPGGA", 5 ) == 0 ) {
19
      lcd_puts('JA');
20
21
    }
22
23
    if ( c == '$') { booler.gpsstart = 1; }
24
    
25
26
27
    }
28
29
 }

von Karl (Gast)


Lesenswert?

>>Du musst in "Buffer" ja auch einen Zeiger auf den Anfang des Strings
>>übergeben.

>Buffer ist schon der String. Man kann "darin" nicht einen Zeiger
>übergeben.
>Das erste Argument von strncmp ist der Zeiger auf einen String. Soweit
>ist das korrekt.

Blödfug/Haarespalterei. "Buffer" ist eine Variable und darin ist ein 
Zeiger, der irgendwo hinzeigt. Buffer ist KEIN string, nur die Daten auf 
die er zeigt können als string interpretiert werden.

Abgesehen davon, das in der folgenden Zeile für meinen Geschmack ein 
paar Klammern fehlen, wird auch der Zeiger in Buffer erhöht.
1
*Buffer++ = c;

Deswegen sieht das strcmp nur noch das Ende des Strings und kann 
folglich auch nicht richtig funktionieren. Deswegen entweder sowas wie 
"Buffer - StringLen" als Zeiger übergeben, oder (meinen Präferenz), sich 
den Anfang in einer eigenen Variable merken und nicht immer verändern, 
z.B. so:
1
Buffer[StringLen] = c;
2
      StringLen++;
3
      setData(c);
4
    }

von Simon (Gast)


Lesenswert?

aah funzt bestens :-) danke

Wie funktioniert das mit dem strtok ?

von Karl (Gast)


Lesenswert?

Ach komm jetzt. "strtok" in google eintippen und dann lesen sollte schon 
noch drin sein, oder? Wenn es konkrete Probleme gibt, und der Quelltext 
dafür vorliegt, werden sie hier sicher gerne geholfen...

von Ahem (Gast)


Lesenswert?

@ Karl

>Blödfug/Haarespalterei.

>Ach komm jetzt. "strtok" in google eintippen

So? Dann tipp mal "Netiquette" ein. Das hast DU nötig.

von Simon (Gast)


Lesenswert?

ja, genau das ist ja mein Problem, die AVR-libc dokumentation
beschreibt die funktion nur kurz.

http://www.nongnu.org/avr-libc/user-manual/group__avr__string.html#g6ace85338eafe22a0ff52c00eb9779b8

char * strtok_r (    char *      string,
    const char *    delim,
    char **    last
  )


meinevar = strtok(Buffer, ",", ??)

ein weiteres problem was ich habe, der ganze string den ich vom GPS 
empfaenger bekomme, geht garnicht in den buffer.
waere schoen ich koennte das mit einmal in buffer einlesen

von Ahem (Gast)


Lesenswert?

>ja, genau das ist ja mein Problem, die AVR-libc dokumentation
beschreibt die funktion nur kurz.

Das ist durchaus nicht alles. In den Zeilen darunter steht noch mehr.
Ausserdem bist Du ja nicht gezwungen ausschliesslich dort zu schauen.


Parses the string s into tokens.

strtok parses the string s into tokens. The first call to strtok should 
have s as its first argument. Subsequent calls should have the first 
argument set to NULL. If a token ends with a delimiter, this delimiting 
character is overwritten with a '\0' and a pointer to the next character 
is saved for the next call to strtok. The delimiter string delim may be 
different for each call.

Ausserdem bist Du ja nicht gezwungen ausschliesslich dort zu schauen.


>ein weiteres problem was ich habe, der ganze string den ich vom GPS
>empfaenger bekomme, geht garnicht in den buffer.
Mach doch den Buffer einfach länger.

von Simon (Gast)


Lesenswert?

Wenn ich den groesser mache mit [100] vergroessert sich natuerlich 
wieder der speicher den ich belge.
das is doch auch kacke,
ich muesste doch nur das start signal abwarten ($GPGGA).
danach alles was kommt in nen kleinen buffer bis ein "," auftritt.

von Ahem (Gast)


Lesenswert?

>das is doch auch kacke,
Das mag ja sein, aber mit dieser Beschreibung

>ich muesste doch nur das start signal abwarten ($GPGGA).
>danach alles was kommt in nen kleinen buffer bis ein "," auftritt.

hast Du ja schon festgelegt wie es auch mit kleinem Buffer geht.
Mach es doch einfach so.

von Christian R. (supachris)


Lesenswert?

Mach´s doch so:
Erst mal alles ignorieren. Wenn ein $ kommt, globale Variable setzen, 
dass du jetzt im Datensatz bist. Wenn du im Datensatz bist, 5 Zeichen in 
einen 6 Byte großen Buffer einsortieren. Wenn du das 5. Zeichen 
eingesammelt hast, vergleichen, ob GPGGA ist. Wenn ja, 2. globale 
Variable setzen, dass du im korrekten Datensatz bist. Dann halt alles 
einsammeln, entweder von Komma zu Komma gleich beim Empfangen sortieren 
(Datensatzabschnitte mitzählen) oder alles bis zum Zeilenumbruch in 
einen großen Buffer. Dann auswerten und nach der Auswertung die globalen 
Variablen zurücksetzen.
Mit strtok bekommst du bei den meisten GPS Empfängern ein Problem. 
Manchmal steht in den Teilabschnitten nix, also gleich das nächste 
Komma. Dann funktioniert die Geschichte mit dem Token nicht richtig. 
Jedenfalls hat´s auf der Implementierung des MSPGCC nicht hingehauen.

von Simon (Gast)


Lesenswert?

genau so dachte ich mir das.
setData gibt ein byte auf dem lcd aus.

char* Buffer[12];
char* tim[12];
volatile uint8_t GPSc = 0;
1
    c = uart_getc();
2
    if ( c & UART_NO_DATA )
3
        {
4
            
5
        }
6
        else
7
    {
8
      if ( GPSc == 1 && StringLen < 6) {
9
        Buffer[StringLen] = c;
10
        StringLen++;
11
        if( strncmp( Buffer, "GPGGA,", 6 ) == 0 ) {
12
           GPSc = 2;
13
           StringLen = 0;
14
        }
15
      }
16
17
      if ( GPSc == 2 && StringLen < 6) {
18
        if (c != ",") {
19
          tim[StringLen] = c;
20
          StringLen++;
21
          setData(c);
22
        } else
23
        {
24
        GPSc = 3;
25
        StringLen = 0;
26
        }
27
      }
28
29
30
      if (GPSc == 3) {
31
     
32
      }
33
34
      if ( c == '$' && GPSc == 0) { GPSc = 1; }
35
36
    
37
    }
38
39
 }
40
}

von Simon (Gast)


Lesenswert?

Warum springt der beim vergleichen mit == "." niemals in
das untere else feld?

obwohl das LCD display ein . zeigt?
er findet nie einen . darin, werder wenn ich es
so: '.'
noch so "."
noch 0x2E
schreibe
1
  c = uart_getc();
2
3
  if ( (GPSc == 2) && (StringLen < 8) ) {
4
        if ( c == "." )  {
5
          GPSc = 3;
6
          StringLen = 0;
7
          lcd_puts("P3");
8
        } else
9
        {
10
          tim[StringLen] = c;
11
          StringLen++;
12
          setData(c);
13
        }
14
      }

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:
> Warum springt der beim vergleichen mit == "." niemals in
> das untere else feld?

Was mich viel mehr verblüfft ist, dass dir dein Compiler dabei keine 
Warnung ausgegeben hat.

In C gilt
  Alles zwischen doppelten Gänsefüschen (also ") ist ein String
  Alles zwischen einfachen Gänsefüschen (also ') ist ein Character

Du willst Character vergleichen, also


>         if ( c == "." )  {

          if ( c == '.' )  {

von Simon (Gast)


Lesenswert?

Der Witz daran ist ja das selbst das nicht funktioniert
1
    if ( (GPSc == 2) && (StringLen < 8) ) {
2
      
3
                     if ( c == '.' )  {
4
          GPSc = 3;
5
          StringLen = 0;
6
          lcd_puts("P3");
7
        } else
8
        {
9
          tim[StringLen] = c;
10
          StringLen++;
11
          setData(c);
12
        }
13
      }

er muesste ja sobald er ein '.' erkennt, auf dem LCD ein P3 ausgeben.
tut er aber nicht.
er gibt einen punkt aus und macht weiter bis StringLen <8 erreicht hat.
und da er GPSc = 3 ausgibt, duerfte er niemals mehr keins der beiden 
anspringen.

von Simon (Gast)


Lesenswert?

Ich hab den Fehler gefunden.


unsigned int c;  <- funktioniert nicht
char c; <- funktioniert

aber zum verstaendnis... warum?

 if ( c == '.' )  { }

von Matthias L. (matze88)


Lesenswert?

unsigned int ist größer als char. Ich weiß nicht genau, was der Compiler 
aus if (c == '.') macht bzw. was du überhaupt in die Variable c 
reinliest. Kannst dir ja mal den erzeugten Assembler anschauen. Ich 
meine ganz ganz dunkel was im Kopf zu haben, dass er das vll falsch 
"verbreitert". Deshalb sollte man auch, wenn man mit 32 bit Werten 
hantiert, immer so: var &= 0x00000012 und nicht so: var &= 0x12 
verknüpfen.

Matthias

von Karl H. (kbuchegg)


Lesenswert?

1
     c = uart_getc();
2
    if ( c & UART_NO_DATA )
3
        {
4
            
5
        }
6
        else

Sind das die UART Routinen vom Fleury Peter?

Wenn ja, dann haben die im HighByte Kennungen enthalten und damit ist 
der komplette unsigned int nicht mehr '.', selbst wenn im Low-byte ein 
'.' kodiert ist. Du musst aber c auf unsigned int lassen, sonst kriegst 
du nie die UART_NO_DATA Benachrichtigung.
1
   if( ( c & 0xFF ) == '.' )
2
     ...

Aber der ganze Ansatz, den du da treibst ist IMHO eher auf der schwachen 
Seite angesiedelt. Würd ich nicht so machen. Ich würde erst mal 
abwarten, bis ein $ daherkommt. Ist es da, dann beginnt das Sammeln von 
Zeichen. Und zwar solange, bis ein ',' oder ein \n daherkommt. Jedesmal 
wenn ein ',' daherkommt ist wieder ein Bestandteil der Zeile komplett 
da. Je nachdem, das wievielte das war, wird es entsprechend ausgewertet. 
Deine ganze Steuerung mit GPSc ist mir viel zu kompliziert.

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.