C language to parse GPS source data

1. Introduction to GPS data format

The most common GPS (Global Positioning System) data format is NMEA 0183the format. The NMEA 0183 format is a standard format for transmitting data between navigation devices. It defines a set of specifications so that devices from different manufacturers can communicate through a serial communication interface (common is RS-232) for data exchange. This standard was originally launched by the National Marine Electronics Association (NMEA) in 1980 and is widely used in navigation systems around the world.

NMEA 0183The formatted data is usually transmitted in the form of an ASCII character stream. Each piece of data starts with $ and ends with carriage return (\r) and line feed (\n) characters. Data is divided into different message types, each of which has specific fields and meanings.

In navigation, the most common NMEA 0183 message types include:

  • GGA (Global Positioning System Fix Data): Contains positioning-related information, such as latitude, longitude, positioning quality indication, number of satellites used, horizontal positioning accuracy factor, etc.
  • GLL (Geographic Position – Latitude/Longitude): Provides latitude, longitude and time information.
  • GSA (GNSS DOP and Active Satellites): Contains information such as positioning mode, satellite number used and position accuracy factor.
  • GSV (GNSS Satellites in View): Provides information on visible satellites, including satellite numbers, elevation angles, azimuth angles, and signal-to-noise ratios.
  • RMC (Recommended Minimum Specific GNSS Data): includes positioning status, latitude, longitude, ground speed, ground heading, etc.
  • VTG (Course Over Ground and Ground Speed): Provides ground course and speed information.
  • ZDA (Time and Date): Contains UTC time and date information.

These message types cover positioning, navigation and time-related data and can be used for applications such as real-time positioning, navigation and time synchronization.

Data in NMEA 0183 format is usually generated by devices such as GPS receivers, navigators, and autonomous driving systems, and is output through the serial port. Other devices can read the serial port data and parse the data according to NMEA 0183 specifications. In this way, data can be exchanged and shared between different devices to achieve interoperability between devices.

With the development of technology, new generations of GPS devices have also begun to adopt more advanced data formats, such as NMEA 2000. However, due to widespread application and compatibility requirements, NMEA 0183 is still widely supported and used by many devices and navigation systems.

picture

The following is the positioning data output by the GPS module that supports NMEA 0183 format:

$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F
$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D
$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37
$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A
$GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B
$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C
$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F
$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62
$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D
$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14
$GNZDA,114955.000,06,11,2017,00,00*47
$GPTXT,01,01,01,ANTENNA OK*35

2. Meaning of GPS field

This piece of GPS data is in NMEA 0183 format. It contains different types of GPS messages, each of which has specific meanings and fields.

(1) $GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,*4F This is a GGA (Global Positioning System Fix Data) message, which contains the following key information:

Time: 11:49:55 (UTC time)

Latitude: 28 degrees 42.4158 minutes north latitude

Longitude: 115 degrees 49.5439 minutes east longitude

Positioning quality indicator: 1 (indicating that the positioning is valid)

Number of satellites used: 5 satellites

HDOP (Horizontal Dilution of Precision) horizontal positioning accuracy factor: 3.8

Altitude: 54.8 meters

Geoid height: 0.0 meters

(2) $GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D This is the GLL (Geographic Position – Latitude/Longitude) message, which contains the following key information:

Latitude: 28 degrees 42.4158 minutes north latitude

Longitude: 115 degrees 49.5439 minutes east longitude

Time: 11:49:55 (UTC time)

Positioning status: A (indicating that positioning is valid)

Navigation mode indication: A (autonomous positioning navigation)

(3) $GPGSA,A,3,10,31,18,5.7,3.8,4.2*37 This is the GSA (GNSS DOP and Active Satellites) message, which contains the following key information:

Positioning mode: autonomous positioning mode

Positioning type: 3D positioning

Use satellite numbers: 10, 31, 18

PDOP (Position Dilution of Precision) position accuracy factor: 5.7

HDOP (Horizontal Dilution of Precision) horizontal positioning accuracy factor: 3.8

VDOP (Vertical Dilution of Precision) vertical positioning accuracy factor: 4.2

(4) $BDGSA,A,3,07,10,5.7,3.8,4.2*2A This is the BDGSA (Beidou GNSS DOP and Active Satellites) message, which is similar to the GPGSA message, but uses data from the Beidou navigation system.

Message serial number: This group of messages is divided into 3 messages in total, this is the first message

Total number of visible satellites: 10 satellites

Information such as satellite number, elevation angle, azimuth angle and signal-to-noise ratio

(5) $BDGSV,1,1,04,03,07,05,29,07,79,246,33,10,52,232,19*62 This is the BDGSV (Beidou GNSS Satellites in View) message, which is similar to the GPGSV message. But it uses data from the Beidou navigation system.

(6) $GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,A*4D This is the RMC (Recommended Minimum Specific GNSS Data) message, which contains the following key information:

Time: 11:49:55 (UTC time)

Positioning status: A (indicating that positioning is valid)

Latitude: 28 degrees 42.4158 minutes north latitude

Longitude: 115 degrees 49.5439 minutes east longitude

Ground speed: 0.00 knots

Ground heading: 44.25 degrees

Date: 06 November 17

(7) $GNVTG,44.25,T,M,0.00,N,0.00,K,A*14 This is the VTG (Course Over Ground and Ground Speed) message, which contains the following key information:

Ground heading: 44.25 degrees (true north reference)

Ground speed: 0.00 knots (knots are the same as knots)

Ground speed: 0.00 km/h

Mode indication: A (autonomous positioning and navigation mode)

(8) $GNZDA,114955.000,06,11,2017,00,00*47 This is the ZDA (Time and Date) message, which contains the following key information:

UTC time: 11:49:55

Date: 06 November 17

Local time zone offset: 00 hours 00 minutes

(9) $GPTXT,01,01,01,ANTENNA OK*35 This is a TXT (Text Transmission) message, which contains the following key information:

Text content: ANTENNA OK (indicates that the antenna is in good condition)

These messages provide information such as the time, location, positioning quality, and number of visible satellites of the GPS device. The fields involved include time (UTC time), latitude, longitude, positioning quality indication, satellite number used, positioning accuracy factor, altitude, speed, etc. According to different application requirements, the required information can be extracted from these data for processing and analysis.

3. C language analysis data code

3.1 Parse each field data

The following is using C language to parse the NMEA 0183 data field and print it to the serial port:

#include <stdio.h>
#include <string.h>

// 函数声明
void parseNMEA(const char* sentence);
void printField(const char* field);

int main() {
    
    
    // NMEA数据
    const char* data[] = {
    
    
        "$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F",
        "$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D",
        "$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37",
        "$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A",
        "$GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B",
        "$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C",
        "$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F",
        "$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62",
        "$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D",
        "$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14",
        "$GNZDA,114955.000,06,11,2017,00,00*47",
        "$GPTXT,01,01,01,ANTENNA OK*35"
    };

    int dataSize = sizeof(data) / sizeof(data[0]);

    // 解析并打印每个数据
    for (int i = 0; i < dataSize; i++) {
    
    
        parseNMEA(data[i]);
    }

    return 0;
}

// 解析NMEA语句
void parseNMEA(const char* sentence) {
    
    
    const char* field;
    int count = 0;

    // 跳过$和逗号
    field = strchr(sentence, ',');
    if (field == NULL) {
    
    
        return;
    }
    field++;

    // 解析每个字段
    while (*field != '*') {
    
    
        printField(field);

        // 查找下一个逗号或结束符
        field = strchr(field, ',');
        if (field == NULL) {
    
    
            break;
        }
        field++;
        
        count++;
    }
}

// 打印字段数据
void printField(const char* field) {
    
    
    char str[50];
    int len = 0;

    // 查找字段的长度
    while (field[len] != ',' && field[len] != '\0' && field[len] != '*') {
    
    
        len++;
    }

    // 复制字段数据到缓冲区
    strncpy(str, field, len);
    str[len] = '\0';

    // 打印字段数据到串口
    printf("%s\n", str);
}

3.2 Parse positioning data

A structure named GPSData is defined, and the parsed positioning data is stored in various variables of the structure:

#include <stdio.h>
#include <string.h>

// 定义结构体
typedef struct {
    
    
    char time[10];
    char latitude[10];
    char longitude[11];
    int fixStatus;
    int satellites;
    float hdop;
    float altitude;
} GPSData;

// 函数声明
void parseNMEA(const char* sentence, GPSData* gpsData);
void printGPSData(const GPSData* gpsData);

int main() {
    
    
    // NMEA数据
    const char* data[] = {
    
    
        "$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F",
        "$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D",
        "$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37",
        "$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A",
        "$GPGSV,3,1,10,10,49,184,42,12,16,039,,14,54,341,,18,22,165,23*7B",
        "$GPGSV,3,2,10,22,11,318,,25,51,055,,26,24,205,,29,13,110,*7C",
        "$GPGSV,3,3,10,31,50,287,36,32,66,018,*7F",
        "$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62",
        "$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D",
        "$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14",
        "$GNZDA,114955.000,06,11,2017,00,00*47",
        "$GPTXT,01,01,01,ANTENNA OK*35"
    };

    int dataSize = sizeof(data) / sizeof(data[0]);

    // 解析并打印每个数据
    for (int i = 0; i < dataSize; i++) {
    
    
        GPSData gpsData;
        parseNMEA(data[i], &gpsData);
        printGPSData(&gpsData);
    }

    return 0;
}

// 解析NMEA语句并存储到结构体中
void parseNMEA(const char* sentence, GPSData* gpsData) {
    
    
    const char* field;
    int count = 0;

    // 跳过$和逗号
    field = strchr(sentence, ',');
    if (field == NULL) {
    
    
        return;
    }
    field++;

    // 解析每个字段
    while (*field != '*') {
    
    
        switch (count) {
    
    
            case 0:
                strncpy(gpsData->time, field, 6);
                gpsData->time[6] = '\0';
                break;
            case 1:
                strncpy(gpsData->latitude, field, 9);
                gpsData->latitude[9] = '\0';
                break;
            case 2:
                strncpy(gpsData->longitude, field, 10);
                gpsData->longitude[10] = '\0';
                break;
            case 6:
                sscanf(field, "%d", &gpsData->fixStatus);
                break;
            case 7:
                sscanf(field, "%d", &gpsData->satellites);
                break;
            case 8:
                sscanf(field, "%f", &gpsData->hdop);
                break;
            case 9:
                sscanf(field, "%f", &gpsData->altitude);
                break;
            default:
                break;
        }

        // 查找下一个逗号或结束符
        field = strchr(field, ',');
        if (field == NULL) {
    
    
            break;
        }
        field++;
        
        count++;
    }
}

// 打印GPS数据到串口
void printGPSData(const GPSData* gpsData) {
    
    
    printf("Time: %s\n", gpsData->time);
    printf("Latitude: %s\n", gpsData->latitude);
    printf("Longitude: %s\n", gpsData->longitude);
    printf("Fix Status: %d\n", gpsData->fixStatus);
    printf("Satellites: %d\n", gpsData->satellites);
    printf("HDOP: %.1f\n", gpsData->hdop);
    printf("Altitude: %.1f meters\n", gpsData->altitude);
    printf("\n");
}

This code will parse the data in NMEA 0183 format and store the parsed results in the corresponding variables of the GPSData structure. Use the printGPSData function to print data to the serial port.

Guess you like

Origin blog.csdn.net/weixin_40933653/article/details/133497454