LEcture GPS Xbee sous interruption
gps-ea-acc023.cpp
- Committer:
- pascalreygner
- Date:
- 2018-08-09
- Revision:
- 3:9a24090ff482
- Parent:
- 2:824735b4c3a3
File content as of revision 3:9a24090ff482:
/* Gestion carte GPS au format XBEE * fournisseur : Embedded Artists * Réf : EA-ACC-023 * utilise Chipset MT3339 (Mediatek Labs) */ #include <gps-ea-acc023.h> #include "mbed.h" #include <stdlib.h> #include <stdio.h> using namespace gpsxbee_MT3339; static GpsXbee gpsxbee; RawSerial gps_uart(P4_22, P4_23); void GpsXbee::GpsXbeeInit(void) { NmeaSentence = NMEA_INVALID; gpsTrameRMC = TRAME_WAIT; gpsTrameGGA = TRAME_WAIT; gpsState = StateStartGps; gpsBufPos =0; gps_uart.baud(9600); gps_uart.attach(this,&GpsXbee::lecture,gps_uart.RxIrq); } GpsXbee::~GpsXbee() { gps_uart.attach(NULL);// bloque IRQ réception GPS } void GpsXbee::InitRMC(void) { rmc_hours =0; rmc_minutes =0; rmc_seconds =0; rmc_milliseconds =0; rmc_warning = 'V'; rmc_latitude =0; rmc_longitude =0; rmc_nsIndicator = 'N'; rmc_ewIndicator = 'W'; rmc_speedKnots =0; rmc_jours =0 ; rmc_mois =0 ; rmc_ans =0 ; } void GpsXbee::InitGGA(void) { gga_hours = 0; gga_minutes = 0; gga_seconds = 0; gga_milliseconds = 0; gga_latitude = 0; gga_longitude = 0; gga_nsIndicator = 0; gga_ewIndicator = 0; gga_fix = 0; gga_satellites = 0; gga_hdop = 0; gga_altitude = 0; gga_geoidal = 0; } void GpsXbee::lecture(void) // réception d'un caractère - analyse trame { char car=0; if((LPC_UART2->LSR & 0x01)==1) { // solution si getc fonctionne pas car = LPC_UART2->RBR; // if(gps_uart -> readable() == 1) { // d = gps_uart -> getc(); // lecture caractère reçu switch(gpsState) { case StateStartGps: if (car == '$') { gpsBuf[0] = '$'; gpsBufPos = 1; gpsState = StateDataGps; } break; case StateDataGps: if (gpsBufPos >= MTK3339_BUF_SZ) { // erreur trame gpsState = StateStartGps; gpsTrameRMC = TRAME_ERR; gpsTrameGGA = TRAME_ERR; } else if (car == '\r') { // fin de trame gpsBuf[gpsBufPos] = 0; gpsState = StateStartGps; parseData(gpsBuf, gpsBufPos); // analyse trame if (NmeaSentence == NmeaRmc ) { // décodage trame type "RMC" if (rmc_warning == 'A') { // si données GPS valables : les afficher sprintf(gpsDataRMC,"%.2i/%.2i/%.2i:%.2iH%.2imn%.2is - Lat. = %f%c - Long. = %f%c",rmc_jours,rmc_mois,rmc_ans,rmc_hours,rmc_minutes,rmc_seconds,getLatitudeAsDegrees(rmc_latitude,rmc_nsIndicator),rmc_nsIndicator,getLongitudeAsDegrees(rmc_longitude,rmc_ewIndicator),rmc_ewIndicator); gpsTrameRMC = TRAME_OK; // Trame complète OK } else { sprintf(gpsDataRMC,"NMEARMC : %.2i/%.2i/%.2i:%.2iH%.2imn%.2is --- Valeurs GPS incorrectes",rmc_jours,rmc_mois,rmc_ans,rmc_hours,rmc_minutes,rmc_seconds); } } /* pour afficher les autres protocoles */ else if (NmeaSentence == NmeaGga) { // décodage trame type "RMC" if (gga_fix == 1) {// si données GPS valables : les afficher sprintf(gpsDataGGA,"%.2iH%.2imn%.2is --- Latitude = %f%c --- Longitude = %f%c - Nb sat = %i",gga_hours,gga_minutes,gga_seconds,getLatitudeAsDegrees(gga_latitude,gga_nsIndicator),gga_nsIndicator,getLongitudeAsDegrees(gga_longitude,gga_ewIndicator),gga_ewIndicator,gga_satellites); gpsTrameGGA = TRAME_OK; // Trame complète OK } else sprintf(gpsDataGGA,"NMEAGGA : %.2iH%.2imn%.2is --- Valeurs GPS incorrectes",gga_hours,gga_minutes,gga_seconds); } // pour les autres types (VTG/GGA/GSV) affiche uniquement la trame reçue else memcpy(gpsDataRMC,gpsBuf,sizeof(gpsBuf)); } else { gpsBuf[gpsBufPos++] = car; // enregistre caractère suivant de la trame } break; } } } /* $GPRMC,hhmmss.ss,A,llll.ll,a,yyyyy.yy,a,x.x,x.x,ddmmyy,x.x,a*hh 1 = UTC of position fix 2 = Data status (V=navigation receiver warning) 3 = Latitude of fix 4 = N or S 5 = Longitude of fix 6 = E or W 7 = Speed over ground in knots 8 = Track made good in degrees True 9 = UT date 10 = Magnetic variation degrees (Easterly var. subtracts from true course) 11 = E or W 12 = Checksum */ void GpsXbee::parseRMC(char* data, int dataLen) { double tm = 0; char* p = data; int pos = 0; InitRMC(); p = strchr(p, ','); while (p != NULL && *p != 0) { p++; switch(pos) { case 0: // time: hhmmss.ss (heure GMT) tm = strtod(p, NULL); rmc_hours = (int)(tm / 10000); rmc_hours+=2; // remise à l'heure d'été Paris if (rmc_hours == 24) rmc_hours = 0; if (rmc_hours == 25) rmc_hours = 1; rmc_minutes = ((int)tm % 10000) / 100; rmc_seconds = ((int)tm % 100); rmc_milliseconds = (int)(tm * 100) % 100; break; case 1: // V = warning rmc_warning = *p; break; case 2: // latitude: ddmm.mmmm rmc_latitude = strtod(p, NULL); break; case 3: // N/S indicator (north or south) if (*p == 'N' || *p == 'S') { rmc_nsIndicator = *p; } else rmc_nsIndicator = '?'; break; case 4: // longitude: dddmm.mm rmc_longitude = strtod(p, NULL); break; case 5: // E/W indicator (east or west) if (*p == 'E' || *p == 'W') { rmc_ewIndicator = *p; } else rmc_ewIndicator = '?'; break; case 6: // speed in knots rmc_speedKnots = strtod(p, NULL); break; case 7: // ? break; case 8: // Date : ddmmyy tm = strtod(p, NULL); rmc_jours = (int)(tm / 10000); rmc_mois = ((int)tm % 10000) / 100; rmc_ans = ((int)tm % 100); break; } pos++; p = strchr(p, ','); } } void GpsXbee::parseGGA(char* data, int dataLen) { //http://aprs.gids.nl/nmea/#gga double tm = 0; InitGGA(); char* p = data; int pos = 0; p = strchr(p, ','); while (p != NULL && *p != 0) { p++; switch(pos) { case 0: // time: hhmmss.sss tm = strtod(p, NULL); gga_hours = (int)(tm / 10000); gga_minutes = ((int)tm % 10000) / 100; gga_seconds = ((int)tm % 100); gga_milliseconds = (int)(tm * 1000) % 1000; break; case 1: // latitude: ddmm.mmmm gga_latitude = strtod(p, NULL); break; case 2: // N/S indicator (north or south) if (*p == 'N' || *p == 'S') { gga_nsIndicator = *p; } break; case 3: // longitude: dddmm.mmmm gga_longitude = strtod(p, NULL); break; case 4: // E/W indicator (east or west) if (*p == 'E' || *p == 'W') { gga_ewIndicator = *p; } break; case 5: // position indicator (1=no fix, 2=GPS fix, 3=Differential) gga_fix = strtol(p, NULL, 10); break; case 6: // num satellites gga_satellites = strtol(p, NULL, 10); break; case 7: // hdop gga_hdop = strtod(p, NULL); break; case 8: // altitude gga_altitude = strtod(p, NULL); break; case 9: // units // ignore units break; case 10: // geoidal separation gga_geoidal = strtod(p, NULL); break; } pos++; p = strchr(p, ','); } } int GpsXbee::parseData(char* data, int len) { // verify checksum if (len < 3 || (len > 3 && data[len-3] != '*')) { // invalid data return(-1); } int sum = strtol(&data[len-2], NULL, 16); for(int i = 1; i < len-3; i++) { sum ^= data[i]; } if (sum != 0) { return(-1); } NmeaSentence = NMEA_INVALID; if (strncmp("$GPGGA", data, 6) == 0 ) { parseGGA(data,len); NmeaSentence = NmeaGga; } else if (strncmp("$GPRMC", data, 6) == 0) { parseRMC(data, len); NmeaSentence = NmeaRmc; } return(0); } double GpsXbee::getLatitudeAsDegrees(double l,char ns) { // convert from ddmm.mmmm to degrees only // 60 minutes is 1 degree int deg = (int)(l / 100); l = (l - deg*100.0) / 60.0; l = deg + l; if (ns == 'S') l = -l; return l; } double GpsXbee::getLongitudeAsDegrees(double l,char ew) { // convert from ddmm.mmmm to degrees only // 60 minutes is 1 degree int deg = (int)(l / 100); l = (l - deg*100) / 60; l = deg + l; if (ew == 'W') l = -l; return l; }