Salu zusammen Ich habe hier ein ganz komisches Prob. Manchmal läuft das Programm drei vier mal durch und dann bleibt es einfach stehen. unsigned char nmeabuffer[512];// Empfangsbuffer GPS Daten (NMEA Format) int j = 0; interrupt (UART1RX_VECTOR) usart1_rx(void) { _DINT(); nmeabuffer[j] = RXBUF1; j += 1; _EINT(); } char GPRMC[100] = ""; char GPGGA[100] = ""; char GPVTG[100] = ""; if (j >= 510) { _DINT(); parse_nmea(nmeabuffer, GPRMC, GPGGA, GPVTG); j = 0; _EINT(); } wenn ich nun nach parse_nmea einen Breakpoint setze, läuft er da auch rein und ich sehe das er die einzelnen Datensätze abgefüllt hat. Nach dem zweiten, dritten mal bleibt er dann einfach hängen und geht nicht mehr weiter. Nun habe ich die Zeile parse_nmea(nmeabuffer, GPRMC, GPGGA, GPVTG); als Kommentar eingefügt. Problem besteht weiterhin. Erst wenn ich die Deklaration der Buffer GPRMC[100], GPGGA[100], GPVTG[100] auch als Kommentar setze, läuft das Prog durch. Es kann doch dem Prog egal sein ob ich Buffer deklariere die ich nicht verwende. Wieso habe ich das Prob. ich seh es einfach nicht. Manchmal springt mir der Debugger auch einfach wieder auf die erste main Zeile, dort wo ich den Watchdog abschalte und Resetet sich sozusagen. Wäre toll wenn mal jemand schauen könnte. im Anhang finded ihr noch die Funktion parse_nmea Gruss relflection
1. Dein Puffer ist genau 512 Byte groß. parse_nmea rufst du aber, wenn mindestens 512 Byte reingeschrieben wurden. Das bedeutet, daß du eine recht hohe Wahrscheinlichkeit hast, daß der Puffer überläuft und andere Daten zerschossen werden. Das kann dazu führen, daß das Programm sich aufhängt. 2. j wird von der ISR und vom Hauptprogramm benutzt. Wenn man sowas macht, muß die Variable als volatile deklariert sein. 3. In der ISR brauchst du keine Interrupts zu sperren - die sind schon gesperrt und du solltest sie nicht freigeben, denn das kann u.U. dazu führen, daß die ISR erneut aufgerufen wird, wenn sie noch läuft. Die Interruptsperrung und -freigabe macht die Hardware automatisch.
Hi Warum liesst du die NMEA-Strings nicht einzeln ein? Anfang und Ende sind durch '$' und CR LF (oder umgekehrt) eindeutig gekennzeichnet. Zwischen den einzelnen Datensätzen ist genügend Zeit zu Analyse. Durch deinen Ansatz erreicht du nämlich einen erheblichen zeitlichen Versatz, d.h. zur Zeit der Auswertung sind die Daten eigentlich nicht mehr aktuell. MfG Spess
@1: parse_nmea wird aufgerufen, wenn mindestens 510 Byte drinstehen! @2: volatile ist nicht schlecht, aber auch verhindern, dass über den Puffer hinaus geschrieben wird! Bei der Folge von if-Abfragen innerhalb von parse_nmea kannst Du locker über das Ende des Puffers rauskommen, so dass Du noch prüfen solltest, ob (i+x)<510 ist! Eine kleine Verbesserung noch: wenn Du ein Anfangszeichen findest, Du aber mit der folgenden Nachricht nichts anfangen kannst, dann kannst Du bei i+=1 eine Schleife einbauen, in der Du das nächste Endezeichen suchst.
@Spess53 Wie meinst Du das, soll ich in der Interruptroutine prüfen ob ich den Datensatz brauche? Dachte immer ich soll nur so wenig wie möglich in der Interruptroutine machen? Müsste ja dann einen Datensatz einlesen und den ganzen if Zauber auch noch in die ISR... Greets
Ich denke, Wechselpuffer wären besser: Die ISR sammelt Daten für einen kompletten NMEA-Datensatz in einen Puffer und schaltet dann auf den anderen um. Wenn ein vollständiger Puffer vorhanden ist, rufst du parse_nmea dafür auf. Die Synchronisation zwischen ISR und dem Hauptprogramm machst du über eine Byte-Variable. Die Puffer müssen nur so lang sein, daß sie jeweils einen vollständigen NMEA-Satz speichern können. In der ISR machst du so wenig wie möglich.
Hi Nur zu Information: Ich programmiere notorisch in Assembler und mit AVR. Interruptroutinen sollte man natürlich so kurz wie möglich halten. 'kurz' ist aber nur eine Programmier-Philosiphische Definition. Ich mache meine Interruptroutinen so kurz wie möglich und so lang wie nötig. zu deinem Programm: Es ist kein Problem in der ISR zu prüfen, ob das empfangene Zeichen ein '$' ist. Danach wird ein Flag gesetzt.Solange das gesetzt ist,werden die Zeichen in den Puffer eingelesen bis <CR LF> empfangen wird.Danach ein zweites Flag setzen, das dem Hauptprgramm signalisiert, daß ein Datensatz vorliegt. Dein Hauptprogramm sollte dann den Inhalt des Puffers in einen zweiten Puffer kopieren,das beide Flags zurücksetzen und das eigentliche Parsen des Datensatzes ausführen. MfG Spess
Hi Sollte heissen: 'kopieren, beide Flags zurücksetzen und das ...' MfG Spess
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.