Forum: Mikrocontroller und Digitale Elektronik Absturzproblem mit MSP430 NMEA Daten parsen


von reflection (Gast)


Angehängte Dateien:

Lesenswert?

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

von Uhu U. (uhu)


Lesenswert?

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.

von Spess53 (Gast)


Lesenswert?

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

von Rainer (Gast)


Lesenswert?

@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.

von reflection (Gast)


Lesenswert?

@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

von Uhu U. (uhu)


Lesenswert?

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.

von Spess53 (Gast)


Lesenswert?

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

von Spess53 (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.