電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 15|回復(fù): 0
收起左側(cè)

C語(yǔ)言實(shí)例_解析GPS源數(shù)據(jù)

[復(fù)制鏈接]

285

主題

285

帖子

2558

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
2558
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-11-14 11:51:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
一、GPS數(shù)據(jù)格式介紹GPS(全球定位系統(tǒng))數(shù)據(jù)格式常見(jiàn)的是NMEA 0183格式,NMEA 0183格式是一種用于導(dǎo)航設(shè)備間傳輸數(shù)據(jù)的標(biāo)準(zhǔn)格式,定義了一套規(guī)范,使得不同廠商的設(shè)備可以通過(guò)串行通信接口(常見(jiàn)的是RS-232)進(jìn)行數(shù)據(jù)交換。這個(gè)標(biāo)準(zhǔn)最初由美國(guó)航海電子協(xié)會(huì)(National Marine Electronics Association,簡(jiǎn)稱NMEA)在1980年推出,并被廣泛應(yīng)用于全球的導(dǎo)航系統(tǒng)。
NMEA 0183格式的數(shù)據(jù)通常以ASCII字符流的形式傳輸,每條數(shù)據(jù)都以$開始,以回車符(\r)和換行符(
)結(jié)束。數(shù)據(jù)被分為不同的消息類型,每個(gè)消息類型都有特定的字段和含義。
在導(dǎo)航中,最常見(jiàn)的NMEA 0183消息類型包括:
GGA(Global Positioning System Fix Data):包含定位相關(guān)的信息,如緯度、經(jīng)度、定位質(zhì)量指示、使用衛(wèi)星數(shù)量、水平定位精度因子等。
GLL(Geographic Position – Latitude/Longitude):提供緯度、經(jīng)度和時(shí)間信息。
GSA(GNSS DOP and Active Satellites):包含定位模式、使用衛(wèi)星編號(hào)和位置精度因子等信息。
GSV(GNSS Satellites in View):提供可見(jiàn)衛(wèi)星的信息,包括衛(wèi)星編號(hào)、仰角、方位角和信噪比等。
RMC(Recommended Minimum Specific GNSS Data):包含定位狀態(tài)、緯度、經(jīng)度、地面速度、地面航向等。
VTG(Course Over Ground and Ground Speed):提供地面航向和速度信息。
ZDA(Time and Date):包含UTC時(shí)間和日期信息。
這些消息類型涵蓋了定位、導(dǎo)航和時(shí)間相關(guān)的數(shù)據(jù),可以用于實(shí)時(shí)定位、航行導(dǎo)航以及時(shí)間同步等應(yīng)用。
NMEA 0183格式的數(shù)據(jù)通常由GPS接收器、導(dǎo)航儀、自動(dòng)駕駛系統(tǒng)等設(shè)備產(chǎn)生,并通過(guò)串口輸出。其他設(shè)備可以通過(guò)讀取串口數(shù)據(jù),并按照NMEA 0183的規(guī)范解析數(shù)據(jù)。這樣,不同設(shè)備之間就可以進(jìn)行數(shù)據(jù)交換和共享,實(shí)現(xiàn)設(shè)備之間的互操作性。
隨著技術(shù)的發(fā)展,新一代的GPS設(shè)備也開始采用更高級(jí)的數(shù)據(jù)格式,例如NMEA 2000。然而,由于廣泛應(yīng)用和兼容性的要求,NMEA 0183仍然被廣泛支持,并被許多設(shè)備和導(dǎo)航系統(tǒng)所使用。

下面是支持NMEA 0183格式的GPS模塊輸出的定位數(shù)據(jù):
cpp
$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
二、GPS字段含義這段GPS數(shù)據(jù)是NMEA 0183格式的數(shù)據(jù),它包含了不同類型的GPS消息,每個(gè)消息都有特定的含義和字段。
(1)$GNGGA,114955.000,2842.4158,N,11549.5439,E,1,05,3.8,54.8,M,0.0,M,,*4F 這是GGA(Global Positioning System Fix Data)消息,包含了以下關(guān)鍵信息:
時(shí)間:11時(shí)49分55秒(UTC時(shí)間)
緯度:28度42.4158分北緯
經(jīng)度:115度49.5439分東經(jīng)
定位質(zhì)量指示:1(表示定位有效)
使用衛(wèi)星數(shù)量:5顆衛(wèi)星
HDOP(Horizontal Dilution of Precision)水平定位精度因子:3.8
海拔高度:54.8米
大地水準(zhǔn)面高度:0.0米
(2)$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D 這是GLL(Geographic Position – Latitude/Longitude)消息,包含了以下關(guān)鍵信息:
緯度:28度42.4158分北緯
經(jīng)度:115度49.5439分東經(jīng)
時(shí)間:11時(shí)49分55秒(UTC時(shí)間)
定位狀態(tài):A(表示定位有效)
導(dǎo)航模式指示:A(自主定位導(dǎo)航)
(3)$GPGSA,A,3,10,31,18,,,,,,,,,,5.7,3.8,4.2*37 這是GSA(GNSS DOP and Active Satellites)消息,包含了以下關(guān)鍵信息:
定位模式:自主定位模式
定位類型:三維定位
使用衛(wèi)星編號(hào):10、31、18
PDOP(Position Dilution of Precision)位置精度因子:5.7
HDOP(Horizontal Dilution of Precision)水平定位精度因子:3.8
VDOP(Vertical Dilution of Precision)垂直定位精度因子:4.2
(4)$BDGSA,A,3,07,10,,,,,,,,,,,5.7,3.8,4.2*2A 這是BDGSA(Beidou GNSS DOP and Active Satellites)消息,與GPGSA消息類似,但使用的是北斗導(dǎo)航系統(tǒng)的數(shù)據(jù)。
消息序號(hào):這組消息是一共分為3個(gè)消息,這是第1個(gè)消息
可見(jiàn)衛(wèi)星總數(shù):10顆衛(wèi)星
衛(wèi)星編號(hào)、仰角、方位角和信噪比等信息
(5)$BDGSV,1,1,04,03,,,07,05,,,29,07,79,246,33,10,52,232,19*62 這是BDGSV(Beidou GNSS Satellites in View)消息,與GPGSV消息類似,但使用的是北斗導(dǎo)航系統(tǒng)的數(shù)據(jù)。
(6)$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,,,A*4D 這是RMC(Recommended Minimum Specific GNSS Data)消息,包含了以下關(guān)鍵信息:
時(shí)間:11時(shí)49分55秒(UTC時(shí)間)
定位狀態(tài):A(表示定位有效)
緯度:28度42.4158分北緯
經(jīng)度:115度49.5439分東經(jīng)
地面速度:0.00節(jié)
地面航向:44.25度
日期:06日11月17年
(7)$GNVTG,44.25,T,,M,0.00,N,0.00,K,A*14 這是VTG(Course Over Ground and Ground Speed)消息,包含了以下關(guān)鍵信息:
地面航向:44.25度(真北參考)
地面速度:0.00節(jié)(節(jié)與海里/小時(shí)是相同的)
地面速度:0.00千米/小時(shí)
模式指示:A(自主定位導(dǎo)航模式)
(8)$GNZDA,114955.000,06,11,2017,00,00*47 這是ZDA(Time and Date)消息,包含了以下關(guān)鍵信息:
UTC時(shí)間:11時(shí)49分55秒
日期:06日11月17年
本地時(shí)區(qū)偏移:00小時(shí)00分鐘
(9)$GPTXT,01,01,01,ANTENNA OK*35 這是TXT(Text Transmission)消息,包含了以下關(guān)鍵信息:
文本內(nèi)容:ANTENNA OK(表示天線狀態(tài)良好)
這些消息提供了GPS設(shè)備的時(shí)間、位置、定位質(zhì)量、可見(jiàn)衛(wèi)星數(shù)量等信息。其中涉及到的字段包括時(shí)間(UTC時(shí)間)、緯度、經(jīng)度、定位質(zhì)量指示、使用衛(wèi)星編號(hào)、定位精度因子、海拔高度、速度等。根據(jù)不同的應(yīng)用需求,可以從這些數(shù)據(jù)中提取出需要的信息來(lái)進(jìn)行處理和分析。
三、C語(yǔ)言解析數(shù)據(jù)代碼3.1 解析每個(gè)字段數(shù)據(jù)以下是使用C語(yǔ)言解析NMEA 0183數(shù)據(jù)字段并將其打印到串口:
cpp
#include
#include
// 函數(shù)聲明
void parseNMEA(const char* sentence);
void printField(const char* field);
int main() {
    // NMEA數(shù)據(jù)
    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]);
    // 解析并打印每個(gè)數(shù)據(jù)
    for (int i = 0; i
        parseNMEA(data);
    }
    return 0;
}
// 解析NMEA語(yǔ)句
void parseNMEA(const char* sentence) {
    const char* field;
    int count = 0;
    // 跳過(guò)$和逗號(hào)
    field = strchr(sentence, ',');
    if (field == NULL) {
        return;
    }
    field++;
    // 解析每個(gè)字段
    while (*field != '*') {
        printField(field);
        // 查找下一個(gè)逗號(hào)或結(jié)束符
        field = strchr(field, ',');
        if (field == NULL) {
            break;
        }
        field++;
        
        count++;
    }
}
// 打印字段數(shù)據(jù)
void printField(const char* field) {
    char str[50];
    int len = 0;
    // 查找字段的長(zhǎng)度
    while (field[len] != ',' && field[len] != '\0' && field[len] != '*') {
        len++;
    }
    // 復(fù)制字段數(shù)據(jù)到緩沖區(qū)
    strncpy(str, field, len);
    str[len] = '\0';
    // 打印字段數(shù)據(jù)到串口
    printf("%s
", str);
}
3.2 解析定位數(shù)據(jù)定義了一個(gè)名為GPSData的結(jié)構(gòu)體,并將解析后的定位數(shù)據(jù)存儲(chǔ)在該結(jié)構(gòu)體的各個(gè)變量中:
cpp
#include
#include
// 定義結(jié)構(gòu)體
typedef struct {
    char time[10];
    char latitude[10];
    char longitude[11];
    int fixStatus;
    int satellites;
    float hdop;
    float altitude;
} GPSData;
// 函數(shù)聲明
void parseNMEA(const char* sentence, GPSData* gpsData);
void printGPSData(const GPSData* gpsData);
int main() {
    // NMEA數(shù)據(jù)
    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]);
    // 解析并打印每個(gè)數(shù)據(jù)
    for (int i = 0; i
        GPSData gpsData;
        parseNMEA(data, &gpsData);
        printGPSData(&gpsData);
    }
    return 0;
}
// 解析NMEA語(yǔ)句并存儲(chǔ)到結(jié)構(gòu)體中
void parseNMEA(const char* sentence, GPSData* gpsData) {
    const char* field;
    int count = 0;
    // 跳過(guò)$和逗號(hào)
    field = strchr(sentence, ',');
    if (field == NULL) {
        return;
    }
    field++;
    // 解析每個(gè)字段
    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;
        }
        // 查找下一個(gè)逗號(hào)或結(jié)束符
        field = strchr(field, ',');
        if (field == NULL) {
            break;
        }
        field++;
        
        count++;
    }
}
// 打印GPS數(shù)據(jù)到串口
void printGPSData(const GPSData* gpsData) {
    printf("Time: %s
", gpsData->time);
    printf("Latitude: %s
", gpsData->latitude);
    printf("Longitude: %s
", gpsData->longitude);
    printf("Fix Status: %d
", gpsData->fixStatus);
    printf("Satellites: %d
", gpsData->satellites);
    printf("HDOP: %.1f
", gpsData->hdop);
    printf("Altitude: %.1f meters
", gpsData->altitude);
    printf("
");
}
這段代碼會(huì)解析NMEA 0183格式的數(shù)據(jù),并將解析的結(jié)果存儲(chǔ)在GPSData結(jié)構(gòu)體的對(duì)應(yīng)變量中。使用printGPSData函數(shù)將數(shù)據(jù)打印到串口。

發(fā)表回復(fù)

本版積分規(guī)則


聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表