Holla,
ich versuche gerade NMEA Daten zu filtern,
und das scheint schwieriger als man denkt -__-
so empfange ich per funktionierendem Interrupt
die Daten
Interrupt:
nun versuche ich die Daten sauber zu seperieren!
als bedingung suche ich V und T für $GPVTG Datensatz!
Ich weiß dass nach dem 7ten kommata
die Zahl anfängt, durch ein Punkt getrennt wird, und dannach die
Nachkommastellen bis zum nächsten Komma da sind.
Beispiel
GPVTG,309.62,T, ,M,0.13,N,0.2,K,A*23
0.2 brauch ich!
Ich habe folgende Funktion
mit dieser Funktion sendet mir die Uartschnittstelle nichts!
nehme ich USART_SendData(USART1, GPS1[i]
vor die schleife und setze für i einen beliebigen wert ein,
dann sehe ich zwar die stelle,
aber bringt mich nicht wirklich weiter
also wie kann ich GPS1 über Uart anzeigen lassen?
oder gibs eine bessere möglichkeit der Filterung?
jepp -_-
und dabei zähle ich schon die ganze zeit an meiner hand
wann wo die richtige stelle ist :P
aber abgesehen von diesem missgeschick,
müsste der mikrocontroller mir doch
GPS1 bis der counter halt 8 ist anzeigen, oder nicht?
Achja, Du könntest auch schauen ob es zu STM eine String.h gibt wo
solche Dinge wie
1
char*strtok(char*string,char*delimiters);
bereits für Dich implementiert worden sind.
Dann kannst Du die fertigen Token seperat abspeichern, in Zahlen wandeln
und feddisch.
Hier noch ein Link dazu:
http://www.c-howto.de/tutorial-strings-zeichenketten-stringfunktionen-zerteilen-strtok.html
Oder eben nur stur nach dem Trennzeichen suchen und zwischen den
Trennzeichen in einen seperaten String speichern. Dann brauchst Du nur
noch das richtige Token auswählen (Nebenbei hast Du auch noch die
anderen).
Grüße
ja gibt es, werde es mir mal anschauen...
danke dir für den tipp
aber sagt mal, habt ihr vielleicht einen tipp,
warum ich zum beispiel nicht
char GPS1[] = [a,b,c,d,e,f,g,h];
int i = 0;
for (i=0; i > 7; i++)
{
USART_SendData(USART1, GPS1[i]);
}
machen kann?
Dein Interrupt ist ausbaufähig. USART_ReceiveData() sollte man nur
einmal aufrufen, und sich das Ergebnis merken - der 2. Aufruf könnte
u.U. ein anderes Ergebnis liefern.
USART_ClearITPendingBit() wird nur am Stringende aufgerufen. Wenn man
das wirklich bräuchte, würde sich dein IRQ Handler bei allen anderen
Zeichen ständig selbst wieder aufrufen. Aber das Lesen aus dem "Receive"
Register hat normalerweise denselben Effekt - Rücksetzen des
Empfängerflags - daher ist auch dieser Aufruf unnötig.
Guten morgen,
den Fehler in meinem zweiten Beispiel,
mit '' und geschweifter klammer ist mir auch aufgefallen
Also die Idee war folgende,
da die NMEA Datensätze Blockweise schön geordnet kommen,
lese ich jede Zeile ein, und vergleiche diese mit meiner Bedingung
(Stellen für V un T)
(Zur Veranschaulichung: NMEA allgemein
http://murlowsky.homedns.org/cmsimple/images/Bastelei/SiRFDemo/nmea.jpg)
Jede Zeile endet mit <cr><lf>,
deswegen das beenden mit 0x0A
Aber was Uart angeht bin ich ziehmlich frisch,
also die Fehler die man machen kann,
werde ich auch wohl machen -_-
jim, was meinst du mit der Frage in deinem Code "wieso nur am Ende"
meinst du das Anschalten der LED?
Danke schonmal bis dato
Sooo nochmal, ich glaube hier sind zuviele Fehler die mich wahnsinnig
machen.
Lösen wir sie Step by Step
Problem 1:
einzelne Char (oder so ein selfmade string)
kann ich über den Befehl USART_SendData(USART1, "Test")
senden,
aber sobald in einer schleife integriert, egal wo,
passiert nichts.
z.B.
1
charGPS1[]=['a','b','c','d','e','f','g','h'];
2
inti=0;
3
for(i=0;i!8;i++)
4
{
5
USART_SendData(USART1,GPS1[i]);
6
}
es passiert nichts!
Liegt es am USART Interrupt,
da ich nur für RXNE konfiguriert habe?
Wo ist die Null Terminierung
char GPS1[] = ['a','b','c','d','e','f','g','h',0];
Bitte unterscheide zwischen chars und strings
Du solltest dir noch mal die Kapitel Felder (Arrays) und Pointer sowie
Strings durchlesen ( in deinem C Buch )
das mit der Nullterminierung ist richtig!
denke ich habe ein anderes Problem:
dadurch das das Nmea Protokoll so lang ist,
schaffe ich es nicht einen Teilstring zu entnehmen,
und bearbeiten zu lassen, ohne das es überschrieben wird
Beispiel (mit nur 3 NMEA Datensätzen):
Pause
$GPGPA(Daten...)<LF><CR>$GPRMC(Daten...)<LF><CR>$GPGP(Daten...)<LF><CR>
Pause
$GPGPA(Daten...)<LF><CR>$GPRMC(Daten...)<LF><CR>$GPGP(Daten...)<LF><CR>
Pause
$GPGPA(Daten...)<LF><CR>$GPRMC(Daten...)<LF><CR>$GPGP(Daten...)<LF><CR>
Pause
(...)
Während USART
$GPGPA(Daten...)<LF><CR> ausliest, und ins Array schreibt,
bei <cr> den Counter auf 0 setzt, und weiterhin ausliest
fängt meine Funktion an das Array auszulesen,
aber durch das Counter auf 0 setzen,
wird das Array schneller überschrieben als die Funktion es auslesen kann
ist meine Befürchtung richtig und wie würde man am besten vor gehen?
Ganzes NMEA in String erstellen,
Teilstring durch <cr><lf> separieren,
nach bestimmten Charreihenfolge suchen,
und dann wieder separieren,
um die zwei zahlenwerte die ich brauche zu suchen?
Hi
>Position UP-DATE Rate: 5 Hz
Und da soll ein 32-Bit-Controller so einen läppischen NMEA-String nicht
zerpflücken können bevor der nächste rein kommt? Kann ich nicht glauben.
Das habe ich schon mit einem AVR geschafft, nebenbei noch ein
Grafikdisplay mit Karte bedient, und der hat sich gelangweilt.
Dein Fehler liegt mit großer Sicherheit wo anders.
MfG Spess
Vielleicht blöde ausgedrückt,
ich mache ja aus dem
Pause
$GPGPA(Daten...)<LF><CR>$GPRMC(Daten...)<LF><CR>$GPGPS(Daten...)<LF><CR>
Pause
das hier
Pause
$GPGPA(Daten...)<LF><CR>
$GPRMC(Daten...)<LF><CR>
$GPGPS(Daten...)<LF><CR>
Pause
und gedanklich,
während ich
$GPGPA(Daten...)<LF><CR> nutzen möchte wirds mir durch
$GPRMC(Daten...)<LF><CR> und $GPGPS(Daten...)<LF><CR>
ich vermute es nur, ich weiß es nicht wirklich,
weil ich ein Zahlen, Punkt und Buchstaben wirrwar herausbekomme
Double buffer (oder mehr)
Du schreibst in einen Puffer und wenn CR/LF kommt wechselst du zum
anderen Empfangpuffer wärend du den ersten auswertest.
z.B. könntest du auch nach GPGPA suchen und alles was dahinter kommt bis
zum CR/LF in Puffer 1 schreiben alles was hinter GPRMC bis zum CR/LF in
puffer 2 usw. Eine andere Routine wertet diese dann im Hintergrund aus.
Dazu muß aber zu jedem Puffer ein Flag gesetzt und abgefragt werden ob
der Puffer gültige Daten enthält.
Die Idee war folgende, es wird geschaut ob '$' empfangen wurde,
wenn ja, wird der zähler für die buffer inkremetiert,
sollte allerdings der zähler bei 4 sein, setze diesen wieder auf 0.
derCounter für die Arrays (Ucounter) wird auf 0 gesetzt.
wird jetzt kein '$' empfangen,
weiß das system anhand des letzten gesetzten flags,
welchen buffer er nutzen soll.
dieser buffer wir aufgefühlt,
und zur kontrolle über uart rausgeschickt,
bis wieder ein '$'empfangen worden ist.
da ein '$' wieder empfangen wurde... fängt das spielchen von vorne an
für mich ist es logisch und richtig was ich da hingeschrieben habe,
aber wieso funktioniert das nicht?
wieso schafft er es nicht ins nächste bufferfeld zu springen und dort
seine arbeit zu verrichten? das muss irgendwas mit *pflag zu tun haben,
aber was?
Jetzt hab ich eine Verständnisfrage,
wenn ich in meinem Interrupt eine Funktionaufrufe,
diese fängt an was zu bearbeiten,
und das selbe Interrupt wird wieder angesprochen
wird die ursprünglich angesprochene Funktion weiterbearbeitet,
oder wird wiederholt die Funktion durch das zweite Interrupt gestartet,
und die alte wird abgebrochen?
Ich komme auf diese Frage,
weil
1
voidtest(char*GPS1,intAnzahl)
2
{
3
intmp;
4
Anzahl+=1;
5
GPS1[Anzahl+1]='0';
6
7
8
for(mp=0;mp<6;)
9
{
10
USART_SendData(USART1,GPS1[mp++]);
11
}
kommt nur Müll raus, obwohl ich eigentlich
die ersten 7char Zeichen des Arrays erwartet hätte!
Mache ich eine einfache Char sendung
1
voidtest(char*GPS1,intAnzahl)
2
{
3
4
Anzahl+=1;
5
GPS1[Anzahl+1]='0';
6
USART_SendData(USART1,GPS1[3]);
7
}
Kommt wie erwartet die 4 Stelle der jeweiligen Strings raus!
TGSSSSLM
für GPV'T'G, GPG'G'A, GPG'S'A, GPG'S'V, GPG'S'V, GPG'S'V, GPG'L'L,
GPR'M'C...
Ist nun die Funktion zu langsam um 5Char Zeichen zu senden???
Das senden dient erstmal nur zur Kontrolle,
diese Strings sollen noch Teilen abgesucht werden -_-
Als omit den Interupts macht man das so :
Man versucht so wenig Zeit wie möglich im Handler zu verbringen.
Du solltest im Interupthandler nur EIN EINZELNES Zeichen in einen Puffer
schreiben und einen der vier Zähler hochzählen und sich um die start und
Stop bzw. Daten Gültig Bedingung kümmern.
Also z.B. ne Statemachine (auch FSM) im Interupt die immer nur durch
einen State läuft und dann aus dem Handler zurückspringt.
im Handler der aufgerufen wird wenn EIN Zeichen im RX Register steht
wird geguckt in welchem State wir uns befinden
die Variable State machst du dir nen eigenen type mit enum oder einfach
per define der einzelnen States damit Sie im Switch benutzt werden
können.
und du brauchst noch i, x, und char puffer[2][32] usw.
state=next_state;
switch(state)
{
case WartenaufDollar:
if(RX=='$')
{
puffer[x][i++]=RX;
next_state=DatenSammelnbis<LF><CR>Kommt;
}
break;
case DatenSammelnbis<LF><CR>Kommt:
puffer[x][i++]=RX;
if(RX==0x0A && Puffer[x][i-1]==0x0D)
{
if(x==1)
{
x=0;
}
else
{
x=1;
}
next_state=WartenaufDollar;
}
break;
}
Danke Dir Uwe,
das mit dem Umfang der Anweisungen im Interrupt war mir schon bewußt,
nur als Programmierneuling,
sind mir nicht alle Verfahren so bekannt.
So hänge ich seit Tagen an diesem Problem,
und du zauberst mal kurz was dahin ;)
so siehts jetzt bei mir aus,
und der compiler hatte auch nichts zu meckern...
jetzt muss ich mich mit übergaben und nutzen von mehrdimensionalen
arrays beschäftigen...
Danke nochmal
Ich brauche noch ne Hilfe von fähigen Programmierer,
denn ich bekomme trotz langens suchen im Netz nicht weiter raus.
Also ich habe ein zweidimensionales Array,
und da ich nur die "hälfte" brauche,
würde ich gerne das in ein einfaches Array kopieren.
Dannach würde ich das normale Array nehmen und mit strtok
aufteilen. Indem ich nun auf den Teil des Strings zeige was ich brauche,
würde ich es wieder nehmen und in ein richtiges Array kopieren da es
wieder geteilt wird. Wieder zeige ich auf beide Teile und kopiere sie
jeweils wieder in ein Array. Nun kann ich die Werte mit Atoi zu Integer
machen und berechnen.
Bei dem anderen Part sind die Werte immer an selber stelle, deswegen ist
eine einfache Verschiebung...
Nun habe ich mit meinem jämmerlichen Wissenstand was versucht,
kann bitte mir erklären wie man es besser macht?
Ich habe wirklich keine vernünftigen Beispiele gefunden.