Hallo Leute,
ich soll für meine Uni ein kleines Projekt realisieren das über einen
Altera FPGA Daten von einem ublox 5 GPS Modul filtert und umwandelt.
Das mit dem FPGA ist jetzt soweit realisiert. Bloß ich hab da ein
Problem das GPS Modul sendet mir daten im NMEA Protokoll Format, das
packet $GPRMC will ich filtern welches ich auch mit „strstr“ geschafft
habe und auslesen in ein Feld mache ich auch schon über eine einfach for
schleife, da liegt schon mein Problem denn wenn ich die Antenne abklemme
wird der gesendete string viel kleiner und des halb bräuchte ich eine
Variable Feld, bloß leider weiß ich nicht wie ich das machen kann ? hab
versucht über eine while schleife das Endzeichen welches mit gesendet
wird zu erkennen, laut NMEA Protokollangabe ist es ein „ENTER“ also „\n“
bloß da klappt dann gar nichts mehr.
Und da der string Beispielsweiße so aussieht:
$GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A*19
Will ich gerne die Daten zwischen denn Kommas auslesen? aber mir ist
leider noch nichts eingefallen wie dieses gehen könnte, vielleicht auch
mit einer while schleife, aber vielleicht geht dieses dann auch
irgendwie eleganter.
Über Tipps, Anregungen und Code beispiele / Schnippsel würde ich mich
freuen.
Mit Freundlichem Gruß
Kleiner Uni Student
Ich würde die Bibliotheksfunktion strtok in einer Schleife z.B. while
verwenden. Auf eine veränderliche Feldlänge (dynamischer Puffer statt
statischer Puffer) würde ich mich nur unter Zwang einlassen.
Bsp: http://www.imb-jena.de/~gmueller/kurse/c_c++/c_strtok.html
Hi,
ja da hast du auch irgend wie recht wollte das Feld auf 82 zeichen
beschränken, laut NMEA Protokoll können nicht mehr zeichen auftreten,
doch wie mache ich das, das es der einlesen in das Feld stoppt wenn ein
fehler eintritt ? z.b. antenne unterbrochen ? denn dann kommt von diesem
Stringpaar
$GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A*19
nur das an
$GPRMC,,V,,,,,,,,,,N*19 (ist nur als beispiel)
das V steht für Void und das N für not Valid .
Vielleicht ja wenn ich die beiden sachen überprüfe ob die auf V und N
stehen wenn ja soll er nichts mehr machen ? aber wie mache ich das mit
den kommas ? hab das mit dem strtok noch nicht ganz so verstanden.
vielen dank schon mal für die hilfe.
Kleiner Uni Student schrieb:> Hi,>> ja da hast du auch irgend wie recht wollte das Feld auf 82 zeichen> beschränken, laut NMEA Protokoll können nicht mehr zeichen auftreten,
Nimm das Doppelte.
Solche Felder sollte man nie zu klein dimensionieren.
Du brauchst nur einen Übertragungsfehler haben und einen \n nicht
richtig erkennen und schon läuft dir der String davon.
Bei solchen Sachen heißt die Devise: nicht kleckern sondern klotzen!
> fehler eintritt ? z.b. antenne unterbrochen ? denn dann kommt von diesem> Stringpaar> $GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A*19> nur das an> $GPRMC,,V,,,,,,,,,,N*19 (ist nur als beispiel)> das V steht für Void und das N für not Valid .
du zerlegst dir den String anhand der ',' und siehst nach, ob im
bewussten Feld ein N oder ein V steht?
> den kommas ? hab das mit dem strtok noch nicht ganz so verstanden.
Dann such dir im Web die Hilfe für strtok. Praktisch bei jeder
Beschreibung der strtok Funktion ist immer ein Beispiel angegeben.
Google: strtok C
und schon werden sie geholfen
Hi,
ich werde es mal berücksichtigen das ich das feld jetzt größer machen
werde, danke für den tipp.
Also hab mir das grade mal mit strtok() angeguckt
ich würde dann denn strink so als beispiel zerlegen:
kann das jetzt leider nicht am "Lebendem" Modell Testen denn bin grade
nicht vorort aber das müsste doch so funktionieren oder ?
Ah ja wie sag ich ihm denn das er es mir in verschiedene felder
schreiben soll ? und dann müsste ich ja noch die funktion atoi()
einbinden um die zahlenwerte als integer zu haben. Köntet ihr mir da
tipps geben wie man das so machen könnte ?
Jetzt habe ich noch eine frage wie sieht das jetzt aus wenn ich nur denn
einen strin absuchen will ?
denn er fängt mit $.... an und endet mit <CR><LF> ? wie kann ich das
suchen das er dort aufhört denn string zu "token" ?
Ah ja dann wollte ich noch die checksume bestimmen mit XOR und so dafür
muss ich von diesem string
$GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A*19
nur das haben umes zu berechen
GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0.4,E,A
wie übergebe ich nur einen teilstring ? der bei $ anfängt und bei *
aufhört ?
Vielen danke schon mal an euch und schon an die Hilfe die ihr mir
gegeben habt.
Deine Einlesefunktion sollte eine Maximalzahl von Zeichen einlesen
können, die von der Größe des Puffers abhängt und sie sollte einen
Rückgabewert haben - korrekt eingelesen, d.h. Zeilenende erkannt bzw.
nicht korrekt eingelesen d.h. Maximalzahl überschritten und kein
Zeilenende erkannt. Das Zeilenende muss die Funktion nicht unbedingt
speichern.
Die Weiterverarbeitung sollte nur korrekt eingelesene Zeilen bearbeiten.
strtokverändert den String. An die Stelle eines delimiters wird
ein '\0' geschrieben. Wenn die zu berechnende Prüfsumme also die ','
einschliesst (NMEA Standard nachsehen), solltest du die Prüfsumme vor
dem Zerlegen berechnen. Das '$' für den Stringanfang kannst du mit
strchr suchen und das '*' für das Stringende mit strrchr.
Tipp: Schau dir die Funktionsgruppe str... in string.h an und stöbere
etwas im Netz oder im Manual. Da sind nützliche Funktionen dabei.
Kleiner Uni Student schrieb:> kann das jetzt leider nicht am "Lebendem" Modell Testen denn bin grade> nicht vorort aber das müsste doch so funktionieren oder ?
Ja. Die grundsätzliche Funktion von strtok ist erkennbar.
> Ah ja wie sag ich ihm denn das er es mir in verschiedene felder> schreiben soll ?
// Dies Strings weiter behandeln, zb aus den 'Zahlenwerten' echte
19
// Zahlen machen, sofern(!) in den jeweilgen Variablen keine NULL
20
// Pointer sind.
21
...
> und dann müsste ich ja noch die funktion atoi()> einbinden um die zahlenwerte als integer zu haben. Köntet ihr mir da> tipps geben wie man das so machen könnte ?
Ja,
Mach ein paar C Vorübungen auf dem PC. Ein wenig C Grundkentnisse
solltest du schon haben, ehe du dich in die µC Hölle mit ihren
beschränkten Debug-Möglichkeiten wagst.
Stefan B. schrieb:> Deine Einlesefunktion sollte eine Maximalzahl von Zeichen einlesen> können, die von der Größe des Puffers abhängt und sie sollte einen> Rückgabewert haben - korrekt eingelesen, d.h. Zeilenende erkannt bzw.> nicht korrekt eingelesen d.h. Maximalzahl überschritten und kein> Zeilenende erkannt. Das Zeilenende muss die Funktion nicht unbedingt> speichern.
Danke für den guten ansatz bloß bei mir harperts irgend wie an der
realisierung, dieses punktes ich weiß nicht wie ich das machen soll ?
Also ich habe mir überlegt ich frage denn daten string die byte für byte
ab und sage wenn der anfang also '$' kommt soll er die ersten 5 zeichen
einlesen in das daten feld und sie nach den buchstageb "RMC" überprüfen,
also um zu prüfen ob das Richtige packet kommt in etwa so:
1
charnmea_data[164];
2
3
intmain()
4
{
5
.
6
.
7
.
8
if(send_data='$')
9
{
10
if(strstr(nmea_data,"RMC")==&nmea_data[3])
11
{
12
.
13
.
14
.
15
// Hier dann die for schleife
16
.
17
.
18
.
wie mache ich das denn jetzt mit der abfrage
Lowtzow .... schrieb:> ich habe es mal so ähnlich gelöst, habe es schnell mal versucht es für> dein bsp anzupassen. hoffe es gelingt ;-)> char nmea_packet[]="$GPRMC,191410,A,4735.5634,N,00739.3538,E,0.0,0.0,181102,0
.4,E,A*19";
> char delimiter[] = ",*";> char *ptr;>> // initialisieren und ersten Abschnitt erstellen> strtok( nmea_packet, "," ); // $GPRMC>> //und dann weiter zb. wobei mit jedem strtok der string weiter zerlegt wird
und daher nur noch NULL geschrieben werden muss
>> xy = strtok( NULL, "," ); // 191410> xyz = strtok( NULL, "," ); // A> xyzq = strtok( NULL, "," ); // 4735.5634
Vielen danke werde es gleich morgen ausprobieren und, dann hier mal mein
ergebniss preis geben.
Karl heinz Buchegger schrieb:> Mach ein paar C Vorübungen auf dem PC. Ein wenig C Grundkentnisse> solltest du schon haben, ehe du dich in die µC Hölle mit ihren> beschränkten Debug-Möglichkeiten wagst.
Vielen dank für das Code beispiel werde es mal auch so ausprobieren,
grundkenntnisse in c habe ich ja schon, nur mir fällt es schwer diese
praktisch auf mein problem anzuwenden, denn habe das ja schon 2 semester
Studiert. Aber Deine und Eure Hilfe hier ist super so gehen mir überall
kleine lichter auf :) .
Kleiner Uni Student schrieb:> Danke für den guten ansatz bloß bei mir harperts irgend wie an der> realisierung, dieses punktes ich weiß nicht wie ich das machen soll ?> Also ich habe mir überlegt ich frage denn daten string die byte für byte> ab und sage wenn der anfang also '$' kommt soll er die ersten 5 zeichen> einlesen in das daten feld und sie nach den buchstageb "RMC" überprüfen,> also um zu prüfen ob das Richtige packet kommt in etwa so:
Das ist imho schon der falsche Ansatz.
Deine Empfangsroutine soll sich mit Ausnahme des \n und \r nicht um den
Inhalt kümmern. \n und \r auch nur deswegen, weil sie das Ende einer
Zeile kennzeichnen.
Solange das empfangene Zeichen nicht \n ist (\r wird einfach ignoriert)
wird das Zeichen ohne Ansehen des Zeichens im Buffer hinten angehängt
(solange noch Platz ist). Ist das Zeichen ein \n, so wird in den Buffer
noch ein \0 hinten drann gehängt um das Ganze zu einem gültigen C-String
zu machen und ein globales Flag gesetzt, welches anzeigt, dass eine
fertige Zeile Text zur Weiterverarbeitung ansteht. Und erst dort geht es
dann an die Feinarbeit.
Der entscheidende Punkt ist:
Trennen von
* Empfang einer Textzeile
* Auswertung der Textzeile
Das sind 2 Dinge die direkt nichts miteinander zu tun haben (ausser das
das Ergebnis des ersten die Basis für das zweite bildet)
Kleiner Uni Student schrieb:>> Mach ein paar C Vorübungen auf dem PC. Ein wenig C Grundkentnisse>> solltest du schon haben, ehe du dich in die µC Hölle mit ihren>> beschränkten Debug-Möglichkeiten wagst.>> Vielen dank für das Code beispiel werde es mal auch so ausprobieren,> grundkenntnisse in c habe ich ja schon,
Mit Verlaub: Das Thema "Stringverarbeitung" scheint für dich noch ein
Buch mit 7 Siegeln zu sein. Da schwimmst du ordentlich. C bringt einige
Funktionen im Header string.h mit, die man schon kennen sollte und auch
wie sie angewendet werden.
Aha.... also erst einlesen egal was kommt bis halt das zeichen \n kommt
und dann soll er erst filtern.
Aber was ist wenn er mitten im string anfängt zu speichern ?
und wie kann ich denn sowas realisieren das er weis das das zeichen \n
kommt ?
vielleicht so ?
Karl heinz Buchegger schrieb:> Mit Verlaub: Das Thema "Stringverarbeitung" scheint für dich noch ein> Buch mit 7 Siegeln zu sein. Da schwimmst du ordentlich. C bringt einige> Funktionen im Header string.h mit, die man schon kennen sollte und auch> wie sie angewendet werden.
Da hast du natürlich recht das wurde bei mir im Studium nicht so
intensiv behandelt und ich habe mich damit noch nicht ganz so
auseinander gesetzt, außerdem wusste ich auch noch nicht das es so viele
funktionen im Header string.h gibt die mir das leben erleichtern.
Deshalb frage ich hier ja ob man mir so, da oder da mal etwas unter die
arme greifen kann, weil es an einigen stellen Recht mühsählig ist, drauf
zu kommen welche funktion jetzt die richtige ist und welche gibt es die
ich vielleicht anwenden kann.
Kleiner Uni Student schrieb:> Aha.... also erst einlesen egal was kommt bis halt das zeichen \n kommt> und dann soll er erst filtern.
richtig
> Aber was ist wenn er mitten im string anfängt zu speichern ?
Dann findet das die Auswertefunktionalität sofort raus, indem die Zeile
nicht mit einem $ anfängt. Die Auswertung verwirft dann die Zeile sofort
und macht nichts weiter damit.
(*)
> und wie kann ich denn sowas realisieren das er weis das das zeichen \n> kommt ?
Das kommt jetzt daraufan, wie in deinem µC die serielle Schnittstelle
bedient wird und wie man dort konkret 1 Zeichen von der seriellen
Schnittstelle einliest, sofern eines verfügbar ist. Im Idealfall kann
man sich eine Interrupt-Funktion bauen, die im Hintergrund Zeichen
einliest und wegspeichert. Ist die Zeile fertig, dann benachrichtigt sie
(mit einem globalen Flag) das restliche Programm, dass eine Zeile
verfügbar ist und legt sich weiter auf die Lauer
> int nmea_stream_buffer()> {> int i=0;>> while(data != "\n")
wo hat data denn seinen Wert her?
> {> nmea_data[i] = IORD (GPS daten stream);> i++;> }>> data[i]='\0';
wieso auf einmal data?
Bitte achte auch bei Programm-Skizzen auf Sinnhaftigkeit.
Aber grundsätzlich: Ja, kann man auch machen. Das ist halt die Polling
Methode. Da muss man eben darauf aufpassen, dass man nicht jedesmal den
Zeilenanfang verschläft, sonst kriegt man keine einzige gültige Zeile
rein. Interrupt hat den Vorteil, dass man prinzipbedingt (solange
Interrupts enabled sind natürlich) schon kein Zeichen verpassen kann.
(*) Das ist 1 Möglichkeit.
Eine Abwandlung davon könnte natürlich auch noch das Wissen, das jede
Zeile mit $ beginnt in die Empfangsroutine reintragen. Die
Empfangsroutine stellt dann fest, dass sie auf den Zeilenanfang wartet
und verwirft alle Zeichen bis sie ein $ empfängt. Und erst dann gehts
mit der Zeile los, solange bis der \n daher kommt, der die Zeile wieder
abschliesst.
Ist auch eine Möglichkeit. Manchmal kann man es sich leisten, nicht
päpstlicher als der Papst zu sein :-) Wenn das Protokoll soweit fix ist,
dass Zeilenanfang und Zeilenende fix definiert sind, dann spricht nichts
dagegen, dieses Wissen in der Empfangsroutine zu benutzen. Und sei es
nur um sich potentiellen Bufferoverflows zu entziehen (wenn auch nicht
allen).
Oh je da ist mir ja mal was nicht ganz so optimales passiert moment ich
mach es hier nochmal:
1
charnmea_data[164];
2
.
3
.
4
.
5
intnmea_stream_buffer()
6
{
7
inti=0;
8
9
while(nmea_data!="\n")
10
{
11
nmea_data[i]=IORD(GPSdatenstream);
12
i++;
13
}
14
15
nmea_data[i]='\0';
16
.
17
.
18
.
19
.
jetzt müsste es Richtig sein.
Karl heinz Buchegger schrieb:> Interrupt hat den Vorteil, dass man prinzipbedingt (solange> Interrupts enabled sind natürlich) schon kein Zeichen verpassen kann.
Leider habe ich mit interrupts noch nicht gearbeitet und das müsste ich
dann noch freischalten in meinem FPGA.
Ich wollte erstmal eine relativ "Einfache" Lösung für das einlesen und
auswerten realisieren und sie dann später optimieren mit den interrupts
und dann mit der check_sum.
Also wenn ich das jetzt soweit richtig verstanden habe, soll das
programm etwa so aussehen (nur schematisch):
1) Einlesen des Strings bis "\n"
2) String überprüfen ob am anfang "$"
3) wenn nicht dann neunen string einlesen 1) wenn ja
4) string auf zeichenfolge "RMC" über prüfen wenn nicht zurück zu 1)
wenn ja
5) die einzelnen teile mit strtok aufsplitten
6) dann mit atoi die werte umwandeln
ich hoffe mal nicht das der µc denn zeilen anfang verschläft bei dieser
"Polling methode" denn der GPS daten transfär ist recht langsam mit
9600baud
Das hier
> das über einen Altera FPGA
ist noch interessant.
Offenbar bist du ja nicht auf einem klassischen µC.
Inwiefern beeinflusst der FPGA die C-Progammierung?
(Sorry, aber mit FPGA oder Prozessorkernen auf FPGA hab ich keine
Erfahrung)
Karl heinz Buchegger schrieb:> Eine Abwandlung davon könnte natürlich auch noch das Wissen, das jede> Zeile mit $ beginnt in die Empfangsroutine reintragen. Die> Empfangsroutine stellt dann fest, dass sie auf den Zeilenanfang wartet> und verwirft alle Zeichen bis sie ein $ empfängt. Und erst dann gehts> mit der Zeile los, solange bis der \n daher kommt, der die Zeile wieder> abschliesst.> Ist auch eine Möglichkeit. Manchmal kann man es sich leisten, nicht> päpstlicher als der Papst zu sein :-) Wenn das Protokoll soweit fix ist,> dass Zeilenanfang und Zeilenende fix definiert sind, dann spricht nichts> dagegen, dieses Wissen in der Empfangsroutine zu benutzen. Und sei es> nur um sich potentiellen Bufferoverflows zu entziehen (wenn auch nicht> allen).
Diese Möglichkeit finde ich wesentlich eleganter und diese könnte doch
dann in etwa so aussehen oder ?
[c]
char nmea_data[164];
.
.
.
char data;
data = IORD ( GPS daten empfang);
if ( data == '$')
{
.
.
// Hier Fängt die Empfangsroutine an
int nmea_stream_buffer()
{
int i=0;
while(nmea_data != "\n")
{
nmea_data[i] = IORD (GPS daten stream);
i++;
}
.
.
Kleiner Uni Student schrieb:> Oh je da ist mir ja mal was nicht ganz so optimales passiert moment ich> mach es hier nochmal:>>
1
>charnmea_data[164];
2
>.
3
>.
4
>.
5
>intnmea_stream_buffer()
6
>{
7
>inti=0;
8
>
9
>while(nmea_data!="\n")
10
>{
11
>nmea_data[i]=IORD(GPSdatenstream);
12
>i++;
13
>}
14
>
15
>nmea_data[i]='\0';
16
>.
17
>.
18
>.
19
>.
20
>
> jetzt müsste es Richtig sein.
Das kann schon nicht stimmen
> while(nmea_data != "\n")
nmea_data ist ein character Array. Arrays kann man nicht vergleichen und
schon gar nicht so. Ausserdem: Wer garantiert, dass in nmea_data nicht
zufällig der String "\n" enthalten ist? Nach Betreten der Funktion hast
du ja gar nichts mit nmea_data gemacht, weißt daher gar nicht welchen
Inhalt dieses Array hat. Ausserdem willst du ja gar nicht wissen, was in
nmea_data drinnen steht, sondern du willst die Schleife beenden wenn
'das nächste empfangene Zeichen' ein \n ist. nmea_data ist aber nicht
das nächste empfangene Zeichen.
IORD, ist das eine Funktion die auf das nächste Zeichen wartet?
1
intnmea_stream_buffer()
2
{
3
inti=0;
4
charc;
5
6
c=IORD(GPSdatenstream);
7
while(c!='\n')
8
{
9
if(c!='\r')// \r wird kommentarlos einfach ignoriert
Also das mit dem FPGA ist so ganz interessant, da ist ein standart
NIOSII prozessor von Altera implementiert, im prinzip beeinfluß dieser
nur die ein und ausgangs bezeichnungen weil diese alle frei wählbar sind
und die UART schnittstelle muss auch noch parametriert werden, aber
sonst ist es wie ein normaler µc.
IORD ist eine Funktion die mich mit dem UART daten stream verbindet, so
das wenn ich IORD aufrufe mit der base adresse und dem anschluss es mir
die daten von dort holt.
1
IORD(Base_adresse,UART-Connection)
ob neue daten gesendet werden bestimme ich mit einer while schile
1
while(read_uart==0){}
Die funktion read_uart gibt mir eine "1" raus wenn ein Byte gesendet
wird so springt der dann aus der schleife und liest mir die daten in
eine variable bsp:
Karl heinz Buchegger schrieb:> int nmea_stream_buffer()> {> int i = 0;> char c;>> c = IORD( GPS daten stream );> while( c != '\n' )> {> if( c != '\r' ) // \r wird kommentarlos einfach ignoriert> nmea_data[i++] = c;> c = IORD( GPS daten stream );> }>> nmea_data[i] = '\0';>> return i;> }
hmm... also würde es dann in etwa so klappen müssen, okay bin ich mit
einverstanden, bloß wie frage ich jetzt ab ob der stream '\0' enthält ?
und wie so "return i" und nicht z.b. return (1) ? um zu kennzeichnen das
ich daten im buffer habe bzw. einen string?
Kleiner Uni Student schrieb:> hmm... also würde es dann in etwa so klappen müssen, okay bin ich mit> einverstanden, bloß wie frage ich jetzt ab ob der stream '\0' enthält ?
okay die frage war überflüssig sorry.
Kleiner Uni Student schrieb:> und wie so "return i"
wofür wird sich der Aufrufer wohl interessieren?
zb. für die Länge des empfangenen Strings. i ist aber an dieser Stelle
diese Länge. Der Aufrufer kann dann zb eine komplett leere Zeile ganz
einfach ohne langes Testen verwerfen, indem er eine Zeile nur dann
zulässt, wenn ihre Länge größer 0 ist.
Du kannst natürlich auch etwas anderes als deinen Return Wert benutzen,
wenn du etwas sinnvolles dafür hast.
> z.b. return (1)
das ..... ist nicht wirklich sinnvoll. Wenn die Funktion sowieso dauern
1 zurückliefert, dann ist das für den Aufrufer keine sinnvolle
Information.
Karl heinz Buchegger schrieb:>> z.b. return (1)>> das ..... ist nicht wirklich sinnvoll. Wenn die Funktion sowieso dauern> 1 zurückliefert, dann ist das für den Aufrufer keine sinnvolle> Information.
Da hast du natürlich recht, das habe ich mir garnicht so überlegt, das
mit dem rückgabe wert wie lang der string ist, ist eigentlich ganz gut
so kann ich dann später das übergabe feld passend dafür bestimmen, bloß
wie kann ich es denn jetzt machen das ich weiß, ob der string jetzt
fertig ist ?
wie kann ich z.b. von der Einlese routine der überprüfungs routine
irgend wie sagen , so ich bin fertig nun komm Prüfroutine guck mal ob
ich das richtige ins feld geschrieben habe?
meine erste überlegung währe einfach unter die
1
nmea_data[i]='\0';
bedingung die überprüfung schreiben aber das würde die funktion nur
unnötig verschandeln.
Kleiner Uni Student schrieb:> so kann ich dann später das übergabe feld passend dafür bestimmen, bloß> wie kann ich es denn jetzt machen das ich weiß, ob der string jetzt> fertig ist ?
Ganz einfach.
Du bist momentan auf Polling aus.
Wenn deine Funktion zurückkehrt, dann ist der String fertig.
Andernfalls wäre sie ja nicht aus der while Schleife rausgekommen und
nie zum return gekommen.
1
intmain()
2
{
3
...
4
5
while(1){
6
7
// warte auf eine komplette Zeile
8
nmea_stream_buffer();
9
10
// jetzt ist die Zeile vollständig, werte sie aus
11
12
}
13
}
Dieses Polling ist nicht der Weisheit letzter Schluss. Aber ehrlich
gesagt denke ich, dass du erst mal damit genug zu tun hast, ehe man sich
komplexeren Konzepten zuwendet, die ein gewisses Mass an Multitasking
und Multithreading im Programm erlauben.
Karl heinz Buchegger schrieb:> Dieses Polling ist nicht der Weisheit letzter Schluss. Aber ehrlich> gesagt denke ich, dass du erst mal damit genug zu tun hast, ehe man sich> komplexeren Konzepten zuwendet, die ein gewisses Mass an Multitasking> und Multithreading im Programm erlauben.
Ja das mit dem Pooling da hast du recht, da habe ich echt schon genug
mit zu tun, mit den komplexen sachen weiß ich erstmal garnichts
anzufangen, werde mich dort aber noch einarbeiten müssen wegen dem
weiteren verlauf meines studiums welches dann wohl solcher methoden
bedarf.
Vielen dank für die Hilfe werde morgen das ganze mal ausprobieren und
mal schauen wie es läuft / Funktioniert.
Werde mich dann mal morgen melden mit "ergebnissen" und wohl tausend
weiteren fragen vielleicht hast du / ihr ja tipps was ich mir unbedingt
durchlesen sollte oder welche tutorials ich durcharbeiten sollte um da
noch tiefer in die materie einzusteigen um irgend wann mal dann mit den
komplexen sachen anzufangen.
Hi,
auf ein neues, also ich habe das jetzt mal an mein project angepasst
leider funktioniert das noch nicht ganz so mit den strtok() Funktion
habe diese so wie oben beschrieben:
Kleiner Uni Student schrieb:
1
>char*Kennung;
2
>
3
>char*Time;
4
>
5
>char*Latitude;
6
>
7
>char*NorthSouth;
8
>
9
>char*Longitude;
10
>
11
>
12
>
13
>Kennung=strtok(nmea_packet,",");// $GPRMC
14
>
15
>Time=strtok(NULL,",");
16
>
17
>KeinAhnung=strtok(NULL,",");
18
>
19
>Latitude=strtok(NULL,",");
20
>
21
>NorthSouth=strtok(NULL,",");
22
>
23
>Longitute=strtok(NULL,",");
24
>
25
>
26
>
27
>...
28
>
29
>
30
>
31
>// Dies Strings weiter behandeln, zb aus den 'Zahlenwerten' echte
32
>
33
>// Zahlen machen, sofern(!) in den jeweilgen Variablen keine NULL
34
>
35
>// Pointer sind.
36
>
37
>...
für mein progrämchen angepasst wenn ich jetzt die daten mit antenne
ausgebe kommt das raus:
GPRMC,092933.00,A,5133.61527,N,00806.84301,E,0.233,,290710,,,A*7E
Header: GPRMC
Time: 092933.00
Status: A
Latitude: 5133.61527
NorthSouth: N
Longitude: 00806.84301
EastWest: E
Speed: 0.233
Date: 290710
checksum: A*7E
scheint soweit alles ok zu sein bloß wenn ich diese ohne antenne ausgebe
kommt das:
GPRMC,,V,,,,,,,,,,N*53
Header: GPRMC
Time: V
Status: N*53
Latitude: (null)
NorthSouth: (null)
Longitude: (null)
EastWest: (null)
Speed: (null)
Date: (null)
checksum: (null)
das ist nicht gut, scheint so als ob der wenn zwischen zwei kommas keine
daten sind auch nichts ausgibt in die token. wie kann ich dieses problem
beheben das er mir da trotzdem was rein schreibt?
und dann habe ich da noch was, ich habe um nur die checksume zu
beckumen, also die beiden zeichen z.b. "7E" die vor dem "*" stehen
folgendes angewendet
1
checksum=strtok(NULL,"*");
leider bekomme ich dann als ausgabe denn header raus
GPRMC
wie so kommt das ?
über hilfe währe ich sehr dankebar.
Kleiner Uni Student schrieb:> für mein progrämchen angepasst wenn ich jetzt die daten mit antenne> ausgebe kommt das raus:
soweit so gut.
Damit denke ich, hast du verstanden wie strtok funktioniert.
> scheint soweit alles ok zu sein bloß wenn ich diese ohne antenne ausgebe> kommt das:>
Du hast soeben entdeckt, wo der Schwachpunkt (in meinen Augen) bei
strtok liegt: strtok sucht beim nächsten Feld auf jeden Fall nach einem
Anfang, leere Felder gibt es nicht.
> das ist nicht gut, scheint so als ob der wenn zwischen zwei kommas keine> daten sind auch nichts ausgibt in die token. wie kann ich dieses problem> beheben das er mir da trotzdem was rein schreibt?
ein eigenes strtok schreiben.
Da es nicht so flexibel sein muss wie das echte (nur 1 Delimiter), ist
das auch nicht weiter schwer.
> und dann habe ich da noch was, ich habe um nur die checksume zu> beckumen, also die beiden zeichen z.b. "7E" die vor dem "*" stehen> folgendes angewendet>
1
>checksum=strtok(NULL,"*");
2
>
>> leider bekomme ich dann als ausgabe denn header raus> GPRMC> wie so kommt das ?
das müsste man jetzt im Zusammenhang sehen. Würd ich allerdings so gar
nicht machen.
Karl heinz Buchegger schrieb:> das müsste man jetzt im Zusammenhang sehen. Würd ich allerdings so gar> nicht machen.
hmm... ich überlege grade ich ich sowas realisierin könnte also ein
strtok() funktion selber schreiben...
würde das mit einer while schleife machen wie beim string einlesen und
dann noch eine die überprüft ob ich am ende angekommen bin oder nicht
wenn ja springt die raus wenn nicht dann nicht?
sind die überlegungen so schonmal okay ?
Stefan B. schrieb:> strsep wäre dann die Funktion der Wahl.
Danke für den tipp dieses werde ich auch mal ausprobieren, ich habe die
Funktion doch richtig verstanden ich muss doch einfach nur das strtok()
gegen strsep() bei mir austauschen und dann läuft es oder habe ich da
irgend was übersehen ?
kann es genau wie gestern nicht ausprobieren weil ich nicht vorort bin
und es erst morgen machen kann...
habt vielen dank für die hilfe und anregungen so wie die ganzen tipps.
Es gibt hier [http://vancouver-webpages.com/pub/peter/mfcnmea.zip] eine
Klasse für das NMEA0183-Protokoll. Ist zwar in C++ aber vielleicht hilft
es Dir ja weiter. Auf dem PC habe ich die Klasse schon verwendet.
Grüße
Andreas
So Leute,
habe die tage etwas an dem Projekt rumgedoktort und es in einigen sachen
verändert und modifiziert, jetzt stört mich irgend wie die strsep()
funktion weil diese zu überdimensioniert ist, kann ich diese nicht
irgend wie selber realisieren ? währ das nicht einfacher ? also vom
handling her ? irgend wie mit einer while schleife ?
über einen tipp oder programm beispiel währe ich sehr dank bar.
mein vorschalg währe etwa so:
Kleiner Uni Student schrieb:> So Leute,> habe die tage etwas an dem Projekt rumgedoktort und es in einigen sachen> verändert und modifiziert, jetzt stört mich irgend wie die strsep()> funktion weil diese zu überdimensioniert ist
Für deine Zwecke ist sie das auch.
Die Überdimensionierung rührt daher, dass strsep mit mehr als einem
Delimiter gleichzeitig klar kommen muss. Da du nur 1nen hast, könnte man
sich ein strsep Derivat schreiben, das grundsätzlich gleich
funktioniert, aber als Delimiter lediglich einen einzelnen char anstelle
eines Strings nimmt. Damit fällt dann in strsep schon mal mehr als die
Hälfte Code raus.
>, kann ich diese nicht> irgend wie selber realisieren ?
Wenn du es kannst, sicher
> währ das nicht einfacher ? also vom> handling her ?
Nicht wirklich.
Die Grundidee, die hinter strtok, strsep steckt, ist grundsätzlich nicht
schlecht. Auch vom Handling der Funktionen her. Sie sind schnell,
kopieren keine Strings unnötig durch die Gegend und ihr Interface ist so
gestaltet, dass die typischen Anwendungsfälle einfach abzudecken sind.
Einziger Nachteil: der Originalstring wird verändert, sie sind nicht
reentrant geschrieben. Zumindest letzter Punkt ist durch strtok_r
behoben.
> über einen tipp oder programm beispiel währe ich sehr dank bar.
Der Tipp.
Lern endlich C Stringverarbeitung von der Pieke auf. Es ist nicht
trivial aber auch nicht so schwer.
>
Karl heinz Buchegger schrieb:> Der Tipp.>> Lern endlich C Stringverarbeitung von der Pieke auf. Es ist nicht>> trivial aber auch nicht so schwer.
Hast du vielleicht ein gutes tutorial dazu ? oder vll ein buch ?
Kleiner Uni Student schrieb:> Karl heinz Buchegger schrieb:>> Der Tipp.>>>> Lern endlich C Stringverarbeitung von der Pieke auf. Es ist nicht>>>> trivial aber auch nicht so schwer.>> Hast du vielleicht ein gutes tutorial dazu ? oder vll ein buch ?
Wie immer: Die C-Bibel
Kernighan&Ritchie
Programmieren in C
Allerdings: Stringverarbeitung steht und fällt damit, dass man die
C-Vereinbarung "Ein C-String ist: solange Zeichen bis ein '\0' Zeichen
kommt" ernst nimmt. Alles andere ist reines Arbeiten mit Arrays. Kann
man mit Arrays arbeiten (umkopieren, vergleichen, ein Element in einem
Array suchen, etc.) und nimmt noch dieses '\0' Zeichen als Abschluss mit
dazu, dann ist man bei C-Stringverarbeitung.
Dieses '\0' Zeichen hat 2 Implikationen
* zum einen ist es das Stoppschild, das einem sagt
"Hier ist der String zu Ende"
* zum anderen ist es das Zeichen, dass man bei jeglicher
Stringverarbeitung niemals vergessen darf an das Ende eines
Strings anzuhängen
Was strtok bzw. strsep im Grund machen, ist nichts anderes als in einen
String entsprechende '\0' Zeichen einzufügen (indem der Delimiter durch
'\0' ersetzt wird), um so den kompletten String in Teilstrings zu
zerlegen. Und damit man auch von aussen wieder an die jeweiligen Anfänge
dieser Teilstrings herankommt, machen sie das in mehreren Durchgängen,
wobei bei einem Durchgang immer nur der nächste Teilstring identifiziert
wird. Das ist alles was diese Funktionen machen.
Um es nochmal klar zu sagen:
Stringverarbeitung ist einfach nur eine kleine Erweiterung des Arbeiten
mit Arrays. Die Erweiterung besteht darin, dass es ein spezielles
Zeichen gibt.
Einen Character in einem String suchen unterscheidet sich in nichts
davon, den Wert x in einem Array zu suchen. Nur dass man im 2ten Fall
die Arraylänge kennen muss, während bei Stringverarbeitung das '\0'
Zeichen die Aufgabe übernimmt, die Schleife vor Überlauf zu schützen.
ah so ist das, hmm... dann muss ich mir mal was überlegen wie ich das
realisieren würde.... mit der ersetzung des delimeters durch '\0' und
dann dieses noch in felder zu schreiben....
danke für das buch werde mal gucken ob es sowas hier in der uni gibt.