www.mikrocontroller.net

Forum: Compiler & IDEs Kompletten *Buffer++ auslesen


Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mmh das funzt so nicht,

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

ist immer ungleich 0

Autor: Ahem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ahem (Gast)
Datum:

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

Autor: Karl (Gast)
Datum:

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

Autor: Ahem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das $ hab ich vorher schon raus genommen.


 while( 1 ) { 

     c = uart_getc();
    if ( c & UART_NO_DATA )
        {
            
        }
        else
    {
    //lcd_puts(0x4B);
    if (booler.gpsstart == 1 && StringLen < 5) {
      *Buffer++ = c;
      StringLen++;
      setData(c);
    }


     if( strncmp( Buffer, "GPGGA", 5 ) == 0 ) {
      lcd_puts('JA');

    }

    if ( c == '$') { booler.gpsstart = 1; }
    


    }

 }

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
*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:
Buffer[StringLen] = c;
      StringLen++;
      setData(c);
    }
 

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
aah funzt bestens :-) danke

Wie funktioniert das mit dem strtok ?

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Ahem (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Karl

>Blödfug/Haarespalterei.

>Ach komm jetzt. "strtok" in google eintippen

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

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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__...

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

Autor: Ahem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Ahem (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;
    c = uart_getc();
    if ( c & UART_NO_DATA )
        {
            
        }
        else
    {
      if ( GPSc == 1 && StringLen < 6) {
        Buffer[StringLen] = c;
        StringLen++;
        if( strncmp( Buffer, "GPGGA,", 6 ) == 0 ) {
           GPSc = 2;
           StringLen = 0;
        }
      }

      if ( GPSc == 2 && StringLen < 6) {
        if (c != ",") {
          tim[StringLen] = c;
          StringLen++;
          setData(c);
        } else
        {
        GPSc = 3;
        StringLen = 0;
        }
      }


      if (GPSc == 3) {
     
      }

      if ( c == '$' && GPSc == 0) { GPSc = 1; }

    
    }

 }
}

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
  c = uart_getc();

  if ( (GPSc == 2) && (StringLen < 8) ) {
        if ( c == "." )  {
          GPSc = 3;
          StringLen = 0;
          lcd_puts("P3");
        } else
        {
          tim[StringLen] = c;
          StringLen++;
          setData(c);
        }
      }

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 == '.' )  {

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Witz daran ist ja das selbst das nicht funktioniert
    if ( (GPSc == 2) && (StringLen < 8) ) {
      
                     if ( c == '.' )  {
          GPSc = 3;
          StringLen = 0;
          lcd_puts("P3");
        } else
        {
          tim[StringLen] = c;
          StringLen++;
          setData(c);
        }
      }

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.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab den Fehler gefunden.


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

aber zum verstaendnis... warum?

 if ( c == '.' )  { }

Autor: Matthias Larisch (matze88)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
     c = uart_getc();
    if ( c & UART_NO_DATA )
        {
            
        }
        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.

   if( ( c & 0xFF ) == '.' )
     ...

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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.