NMEA is a set of standard information that defines the output of the receiver. There are several different formats, each of which is an independent ASCII format that separates data streams. The data stream length ranges from 30 to characters, the output is usually selected at intervals per second. The most commonly used format is "GGA". It contains the positioning time, latitude, longitude, height, number of satellites used for positioning, and other indicators with velocity, tracking, date, etc.
The NMEA-0183 Protocol defines a lot of statements, but the commonly used or most compatible statements only $ gpgga, $ gpgsa, $ gpgsv, $ gprs mc, $ gpvtg, $ gpgll, etc., are described as follows:
$ Gpgga (Location Information)
Eg: $ gpgga, 092204.999, 4250.5589, S, 14718.5084, E, 24.4, 19.7, 0000, M, * 1f
$ Gpgsa (current satellite information)
Eg: $ gpgsa, A, 40.4, 20, 19, 13, 24.4, 32.2 * 0a
$ Gpgsv (Visible satellite information)
Eg: $ gpgsv, 78,331, 59,235, 41,069, * 70
$ Gpvtg (ground speed information)
Eg: $ gpvtg, 89.68, T, M, 0.00, N, 0.0, K * 5f
$ Gpgll (geographic location information)
$ Gpgll, 4250.5589, S, 14718.5084, E, 092204.999, A * 2D
The following code snippet describes the parsing process of $ gpgga, and so on. Assume that the string has been read from the serial port.
(1) structure information
Typedef struct {int year; int month; int day; int hour; int minute; int second;} date_time; typedef struct {date_time D; // time char status; // receiving status doublelatitude; // latitude double longpolling; // longitude char ns; // North/South char EW; // east/west double speed; // speed double high; // height} gps_info;
(2) obtain the comma position of the specified serial number to parse each definition segment.
Static int getcomma (INT num, char * Str) {int I, j = 0; int Len = strlen (STR); for (I = 0; I <Len; I ++) {If (STR [I] = ',') J ++; If (j = num) return I + 1; // return the next position of the currently found comma position} return 0 ;}
Obtain high-precision data, such as precision latitude.
Static double get_double_number (char * s) {char Buf [128]; int I; double Rev; I = getcomma (1, S); // obtain the Data Length strncpy (BUF, s, I); Buf [I] = 0; // Add the string end flag REV = atof (BUF); // convert the string to floatreturn Rev ;}
Convert Universal Time to Beijing Time
Static void utc2btc (date_time * GPS) {//************************************* * ************* // if the second number first goes out, after the time data is output, add the time data + 1 second GPS-> second ++; // Add a second if (GPS-> second> 59) {GPS-> second = 0; GPS-> minute ++; If (GPS-> minute> 59) {GPS-> minute = 0; GPS-> hour ++ ;}} //************************************** * ************ GPS-> hour + = 8; // Beijing time and UTC time are 8 hours apart if (GPS-> hour> 23) {GPS-> hour-= 24; GPS-> day + = 1; if (GPS-> month = 2 | GPS-> month = 4 | GPS-> month = 6 | GPS-> month = 9 | GPS-> month = 11) {If (GPS-> day> 30) {// the previous months are 30 days per month, and less than 30 GPS-> day = 1 in February; GPS-> month ++ ;}}else {If (GPS-> day> 31) {// the remaining months are 31 days, with GPS-> day = 1; GPS-> month ++ }}if (GPS-> year % 4 = 0) {// If (GPS-> day> 29 & GPS-> month = 2) {// The month of a leap year is 29 days GPS-> day = 1; GPS-> month ++ ;}}else {If (GPS-> day> 28 & GPS-> month = 2) {// The other February days are the 28-day monthly GPS-> day = 1; GPS-> month ++ ;}} if (GPS-> month> 12) {GPS-> month-= 12; GPS-> year ++ ;}}}
(3) parse the GPS data and use line as the input string data. GPS is the global variable to be assigned a value. The first line below is the Character Sequence Number
// 0 7 0 4 6 0 6 8 0 90 0 3 0 9
// $ Gprs mc, 091400, A, 3958.9870, N, 11620.3278, E, 000.0, 000.0, 120302,005.6, w * 62
// $ Gpgga, 091400,395 8.9870, N, 11620.3278, E, 1.9, 114.2, 8.3, M,-, M, * 5E
Void gps_parse (char * line, gps_info * GPS) {int I, TMP, start, end; char C; char * Buf = line; C = Buf [5]; if (C = 'C') {// "uplmc" GPS-> D. hour = (BUF [7]-'0') * 10 + (BUF [8]-'0'); GPS-> D. minute = (BUF [9]-'0') * 10 + (BUF [10]-'0'); GPS-> D. second = (BUF [11]-'0') * 10 + (BUF [12]-'0'); TMP = getcomma (9, Buf ); // get the next character serial number GPS-> D of the 9th comma. day = (BUF [TMP + 0]-'0') * 10 + (BUF [TMP + 1]-'0'); GPS-> D. month = (BUF [TMP + 2]-'0') * 10 + (BUF [TMP + 3]-'0'); GPS-> D. year = (BUF [TMP + 4]-'0') × 10 + (BUF [TMP + 5]-'0') + 2000; // ------------------------------ GPS-> Status = Buf [getcomma (2, Buf)]; // status GPS-> latitude = get_double_number (& Buf [getcomma (3, Buf)]); // latitude GPS-> NS = Buf [getcomma (4, Buf)]; // latitude and South GPS-> longpolling = get_double_number (& Buf [getcomma (5, buf)]); // longitude GPS-> ew = Buf [getcomma (6, Buf)]; // things are utc2btc (& GPS-> D ); // Beijing time} If (C = 'A') {// "$ gpgga" GPS-> high = get_double_number (& Buf [getcomma (9, buf)]) ;}}
Show resolution results
void show_gps(GPS_INFO *GPS){printf("DATE : %ld-%02d-%02d \n",GPS->D.year,GPS->D.month,GPS->D.day);printf("TIME : %02d:%02d:%02d \n",GPS->D.hour,GPS->D.minute,GPS->D.second);printf("Latitude : %10.4f %c\n",GPS->latitude,GPS->NS);printf("Longitude: %10.4f %c\n",GPS->longitude,GPS->EW);printf("high : %10.4f \n",GPS->high);printf("STATUS : %c\n",GPS->status);}