#include #include #include "stdio.h" //const char chaine1[10]="123.456,\0"; const char chaine2[10]="789,\0"; const char chaine3[10]=",\0"; const char chaine1[300]="$GPRMC,154936.000,A,4338.6124,N,00126.7337,E,0.26,326.08,200113,,,A*60\r\n$GPRMC,154937.000,A,4338.6124,N,00126.7337,E,0.26,326.08,200113,,,A*60\r\n$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n\0"; //const char chaine1[300]="$GPRMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68\r\n\0"; struct gps_data { char valid ; //trame valide float time ; //champ time de la trame float lat ; //champ latitude de la trame float lon ; //champ longitude de la trame unsigned char received_checksum; }; unsigned char computed_checksum=0; char parserState=0; unsigned char counter=0; unsigned char dp_counter=0; #define SYNC 0 #define HEADER 1 #define TIME 2 #define VALID 3 #define LAT 4 #define LAT_DIR 5 #define LONG 6 #define LONG_DIR 7 #define IGNORE 8 #define CHECKSUM 9 char header[6]="GPRMC"; gps_data gps_d; //structure de stockage de la trame ///////////////////////////////////////////////////////////////////////////////////// char parseFloatField(char c, float * val, unsigned char * count, unsigned char * dp_count) //La fonction renvoie 0 tant que le décodage n'est pas terminé // 1 lorsque le décodage est terminé correctement // -1 lorsque le décodage a échoué { if (c >= '0' && c <= '9') { (*val) *= 10; (*val) += c - '0'; (*count) = (*count) + 1; return 0; } else if (c == '.') { (*count) = 0; (*dp_count) ++ ; return 0; } else if (c == ',') { while (*count > 0 && *dp_count > 0) // équivalent à *val = *val/(10^*count) { (*val) = (*val) / 10; (*count) = (*count) - 1; } if((*dp_count) > 1) return -1 ; (*count) = 0 ; (*dp_count) = 0 ; return 1; } else { (*count) = 0; // caractère non supporté dans un float return -1; } } ///////////////////////////////////////////////////////////////////////////////////// char parseHexField(char c, unsigned char * val, unsigned char * count) { if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { (*val) = (*val) << 4; if(c < 'A') { (*val) += c - '0' ; } else { (*val) += c - ('A') + 10; } (*count) = (*count) + 1 ; return 0; } else if ((c == '\n') || (c == '\r')) { (*count) = 0; return 1; } else { (*count) = 0; return -1; } } ///////////////////////////////////////////////////////////////////////////////////// void convAngle(float * val){ float t1,t2,t3; int signe; if ((*val)<0){ signe=-1; (*val)=-(*val); } else signe=+1; t1=floor(*val/100); //troncature t2=(*val)-(t1*100); t3=t2/60; (*val)=t1+t3; (*val)=signe*(*val); } /* void convAngle(float * val) { float degre; float minu; if ((*val)>0) degre = floor((*val)/100.); // attention arrondi, TODO vérifier sur les négatifs et sur les parties fractionnaires >0.5 else degre = ceil((*val)/100.); // attention arrondi, TODO vérifier sur les négatifs et sur les parties fractionnaires >0.5 minu = (*val) - (float)(degre*100); //Serial.println((*val) - 4300.); minu = minu / 60.; *val = degre + minu; } */ ///////////////////////////////////////////////////////////////////////////////////// char parseGPS(char c, struct gps_data * dataP) { char ret; switch (parserState) { case SYNC: counter = 0; if (c == '$') { dataP->lat = 0; //maz de la structure de stockage de la trame dataP->lon = 0; dataP->time = 0; dataP->valid = -1; dataP->received_checksum = 0; computed_checksum = 0; parserState = HEADER; //evolution de l'etat } break; case HEADER: computed_checksum = computed_checksum ^ c; // a faire dans chaque etat jusqu'​au caractere '​*'​ exclu // le calcul de la somme de controle est fait par le XOR -> ^ if ( (c == ',') && (counter==5) ) { parserState = TIME; counter = 0; dp_counter = 0; } else if (c != header[counter]) { parserState = SYNC; } else { counter++; } break; case TIME: computed_checksum ^= c; ret = parseFloatField(c, &dataP->time, &counter,&dp_counter); if (ret == 1) { parserState = VALID; return 0; } else if (ret == -1) { parserState = SYNC; return 0; } break; case VALID: computed_checksum ^= c; if (c == ',') { parserState = LAT; counter = 0; dp_counter = 0; } else if (c == 'A') { dataP->valid = 1; } else { dataP->valid = -1; } break; case LAT: computed_checksum ^= c; ret = parseFloatField(c, &dataP->lat,&counter,&dp_counter); if (ret == 1) { parserState = LAT_DIR; } else if (ret == -1) { parserState = SYNC; } break; case LAT_DIR: computed_checksum ^= c; if (c == ',') { parserState = LONG; counter = 0; dp_counter = 0; } else if (c == 'W') { dataP->lat = -dataP->lat; } break; case LONG: computed_checksum ^= c; ret = parseFloatField(c, &dataP->lon,&counter,&dp_counter); if (ret == 1) { parserState = LONG_DIR; } else if (ret == -1) { parserState = SYNC; } break; case LONG_DIR: computed_checksum ^= c; if (c == ',') { parserState = IGNORE; } else if (c == 'S') { dataP->lon = -dataP->lon; } break; case IGNORE: if (c == '*') { counter=0; parserState = CHECKSUM; }else { computed_checksum ^= c; if (c == '\n') { parserState = SYNC; } } break; case CHECKSUM: ret = parseHexField(c, &dataP->received_checksum ,&counter); if (ret!=0) { parserState = SYNC; if ((computed_checksum == dataP->received_checksum) && (dataP->valid!=0)) { return 1; }else{ return -1; } } break; default: parserState = SYNC; break; } return 0; } ///////////////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { // QCoreApplication a(argc, argv); // return a.exec(); float val; unsigned char ret; char c; unsigned int i=0; while (chaine1[i]!=0) { c=chaine1[i]; i++; //ret=parseFloatField(c,&val,&count, &dp_count); ret=parseGPS( c, &gps_d) ; if (ret==1) { printf("----------Trame decodee------------\n"); printf("lat: %f \n",gps_d.lat); printf("lon: %f \n",gps_d.lon); printf("time: %f \n",gps_d.time); printf("valid: %d \n",(int)gps_d.valid); printf("ck: %02x \n",gps_d.received_checksum); //conversion vers angles en degrés convAngle(&gps_d.lat); convAngle(&gps_d.lon); printf("lat: %f \n",gps_d.lat); printf("lon: %f \n",gps_d.lon); } if (ret=-1) { printf("----------Trame erronée------------\n"); } if (ret==-2) { printf("----------Trame erronée au niveau du checksum-----------\n"); } } // printf("%f",val); fflush(stdout); }