lwgps

lwgps 是一款专为嵌入式系统设计的轻量级 GPS NMEA 协议解析库,它能够高效处理常见的 NMEA 语句(如 GPGGA、GPRMC 等),并将数据转换为易于使用的结构体,大大简化了嵌入式开发中 GPS 数据处理的工作。

1、体积与效率

代码量极小(核心函数<1k行),资源占用低,适合资源受限的MCU。

功能专注,不支持复杂的NMEA 2000等高级协议。

2、跨平台性

基于C11标准,几乎不依赖特定平台,可轻松移植到Linux、FreeRTOS及裸机系统。

3、浮点精度

支持编译时选择单精度(float)或双精度(double),方便在功耗和精度间权衡。

在无硬件FPU的低端MCU上使用double可能影响性能。

4、开源许可

采用非常宽松的MIT许可证,可无障碍用于商业闭源项目

github:lwgps

lwgps编码使用及测试

#include <stdio.h>
#include <string.h>
#include "uart.h"
#include "lwgps/lwgps.h"

#define GNSS_DEV   "/dev/ttygnss3"

struct gnss_system {
    char *tag;
    char *name;
};

lwgps_t hgps;

static const struct gnss_system gs_gnss_sys[] = {
    {.tag = "$GN", .name = "GPS"},
    {.tag = "$BD", .name = "北斗"},
    {.tag = "$GL", .name = "格洛纳斯"},
    {.tag = "$GA", .name = "伽利略"},
    {.tag = "$CC", .name = "计算机系统"},
    {.tag = "$CF", .name = "自定义信息"},
    {NULL, NULL},
};

char *find_gnss_sys_soure(char *gnss_data)
{
    char *p = NULL;
    for (int i = 0; i < sizeof(gs_gnss_sys)/sizeof(gs_gnss_sys[0]); i++) {
        p = strstr(gnss_data, gs_gnss_sys[i].tag);
        if (p != NULL) {
            return gs_gnss_sys[i].name;
        }
    }
}

int main(int argc, char **argv)
{
    int cnt = 0;
    char *gnss_system;

    int fd = UART_Open(GNSS_DEV);
    if (fd < 0) 
    {
        printf("open %s failed\n", GNSS_DEV);
        return -1;
    }

    UART_Init(fd, 9600, 0, 8, 1, 'N');

    char gps_rx_data[1024];
    int recvlen;

    lwgps_init(&hgps);

    while (1)
    {
        recvlen = UART_Recv_timeout_pro(fd, gps_rx_data, sizeof(gps_rx_data), 1000, 50);
        if (recvlen > 0) {
            printf("%s\n", gps_rx_data);
        }

        lwgps_process(&hgps, gps_rx_data, strlen(gps_rx_data));

        gnss_system = find_gnss_sys_soure(gps_rx_data);
        /* Print messages */
        printf("信号源(signal source):     %s\r\n", gnss_system);
        printf("数据有效性(data validity):  %d-%s\r\n", hgps.is_valid, hgps.is_valid ? "有效" : "无效");
        printf("纬度(latitude):            %f degrees\r\n", hgps.latitude);
        printf("经度(longitude):           %f degrees\r\n", hgps.longitude);
        printf("海拔(altitude):            %f meters\r\n", hgps.altitude);
        printf("使用星数(sats in use):     %d\r\n", hgps.sats_in_use);
        printf("时间(time):               20%d-%d-%d %02d:%02d:%02d\r\n", 
                    hgps.year, hgps.month, hgps.date,
                    hgps.hours+8, hgps.minutes, hgps.seconds);

        bzero(gps_rx_data, sizeof(gps_rx_data));

        if (cnt++ >= 5) {
            break;
        }
    }

    UART_Close(fd);
      /* Process all input data */

    return 0;
}

测试:

[RSU7032: ~]# ./readgnss 
$GNRMC,064455.00,A,2310.15635,N,11323.96829,E,0.043,,210126,,,D,V*1C

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            0.000000 degrees
经度(longitude):           0.000000 degrees
海拔(altitude):            0.000000 meters
使用星数(sats in use):     0
时间(time):               2026-1-21 08:00:00
$GNGGA,064455.00,2310.15635,N,11323.96829,E,2,11,0.95,53.5,M,-5.3,M,,0000*69

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169273 degrees
经度(longitude):           113.399472 degrees
海拔(altitude):            53.500000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:44:55
$GNRMC,064456.00,A,2310.15636,N,11323.96831,E,0.041,,210126,,,D,V*17

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169273 degrees
[RSU7032: ~]# 
[RSU7032: ~]# ./readgnss 
$GNRMC,064513.00,A,2310.15681,N,11323.96886,E,0.035,,210126,,,D,V*14

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            0.000000 degrees
经度(longitude):           0.000000 degrees
海拔(altitude):            0.000000 meters
使用星数(sats in use):     0
时间(time):               2026-1-21 08:00:00
$GNGGA,064513.00,2310.15681,N,11323.96886,E,2,11,0.96,55.8,M,-5.3,M,,0000*68

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169280 degrees
经度(longitude):           113.399481 degrees
海拔(altitude):            55.800000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:45:13
$GNRMC,064514.00,A,2310.15685,N,11323.96895,E,0.023,,210126,,,D,V*12

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169280 degrees
经度(longitude):           113.399481 degrees
海拔(altitude):            55.800000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:45:13
$GNGGA,064514.00,2310.15685,N,11323.96895,E,2,11,0.99,55.8,M,-5.3,M,,0000*66

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169281 degrees
经度(longitude):           113.399483 degrees
海拔(altitude):            55.800000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:45:14
$GNRMC,064515.00,A,2310.15688,N,11323.96899,E,0.025,,210126,,,D,V*14

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169281 degrees
经度(longitude):           113.399483 degrees
海拔(altitude):            55.800000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:45:14
$GNGGA,064515.00,2310.15688,N,11323.96899,E,2,11,0.96,55.9,M,-5.3,M,,0000*68

信号源(signal source):     GPS
数据有效性(data validity):  1-有效
纬度(latitude):            23.169281 degrees
经度(longitude):           113.399483 degrees
海拔(altitude):            55.900000 meters
使用星数(sats in use):     11
时间(time):               2026-1-21 14:45:15
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐