C语言实例_解析GPS源数据

news2024/9/22 11:38:13

一、GPS数据格式介绍

GPS(全球定位系统)数据格式常见的是NMEA 0183格式,NMEA 0183格式是一种用于导航设备间传输数据的标准格式,定义了一套规范,使得不同厂商的设备可以通过串行通信接口(常见的是RS-232)进行数据交换。这个标准最初由美国航海电子协会(National Marine Electronics Association,简称NMEA)在1980年推出,并被广泛应用于全球的导航系统。

NMEA 0183格式的数据通常以ASCII字符流的形式传输,每条数据都以$开始,以回车符(\r)和换行符(\n)结束。数据被分为不同的消息类型,每个消息类型都有特定的字段和含义。

在导航中,最常见的NMEA 0183消息类型包括:

  • GGA(Global Positioning System Fix Data):包含定位相关的信息,如纬度、经度、定位质量指示、使用卫星数量、水平定位精度因子等。
  • GLL(Geographic Position – Latitude/Longitude):提供纬度、经度和时间信息。
  • GSA(GNSS DOP and Active Satellites):包含定位模式、使用卫星编号和位置精度因子等信息。
  • GSV(GNSS Satellites in View):提供可见卫星的信息,包括卫星编号、仰角、方位角和信噪比等。
  • RMC(Recommended Minimum Specific GNSS Data):包含定位状态、纬度、经度、地面速度、地面航向等。
  • VTG(Course Over Ground and Ground Speed):提供地面航向和速度信息。
  • ZDA(Time and Date):包含UTC时间和日期信息。

这些消息类型涵盖了定位、导航和时间相关的数据,可以用于实时定位、航行导航以及时间同步等应用。

NMEA 0183格式的数据通常由GPS接收器、导航仪、自动驾驶系统等设备产生,并通过串口输出。其他设备可以通过读取串口数据,并按照NMEA 0183的规范解析数据。这样,不同设备之间就可以进行数据交换和共享,实现设备之间的互操作性。

随着技术的发展,新一代的GPS设备也开始采用更高级的数据格式,例如NMEA 2000。然而,由于广泛应用和兼容性的要求,NMEA 0183仍然被广泛支持,并被许多设备和导航系统所使用。

image-20230627231319004

下面是支持NMEA 0183格式的GPS模块输出的定位数据:

$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数据是NMEA 0183格式的数据,它包含了不同类型的GPS消息,每个消息都有特定的含义和字段。

(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)消息,包含了以下关键信息:

  • 时间:11时49分55秒(UTC时间)
  • 纬度:28度42.4158分北纬
  • 经度:115度49.5439分东经
  • 定位质量指示:1(表示定位有效)
  • 使用卫星数量:5颗卫星
  • HDOP(Horizontal Dilution of Precision)水平定位精度因子:3.8
  • 海拔高度:54.8米
  • 大地水准面高度:0.0米

(2)$GNGLL,2842.4158,N,11549.5439,E,114955.000,A,A*4D 这是GLL(Geographic Position – Latitude/Longitude)消息,包含了以下关键信息:

  • 纬度:28度42.4158分北纬
  • 经度:115度49.5439分东经
  • 时间:11时49分55秒(UTC时间)
  • 定位状态:A(表示定位有效)
  • 导航模式指示:A(自主定位导航)

(3)$GPGSA,A,3,10,31,18,5.7,3.8,4.2*37 这是GSA(GNSS DOP and Active Satellites)消息,包含了以下关键信息:

  • 定位模式:自主定位模式
  • 定位类型:三维定位
  • 使用卫星编号: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消息类似,但使用的是北斗导航系统的数据。

  • 消息序号:这组消息是一共分为3个消息,这是第1个消息
  • 可见卫星总数:10颗卫星
  • 卫星编号、仰角、方位角和信噪比等信息

(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消息类似,但使用的是北斗导航系统的数据。

(6)$GNRMC,114955.000,A,2842.4158,N,11549.5439,E,0.00,44.25,061117,A*4D 这是RMC(Recommended Minimum Specific GNSS Data)消息,包含了以下关键信息:

  • 时间:11时49分55秒(UTC时间)
  • 定位状态:A(表示定位有效)
  • 纬度:28度42.4158分北纬
  • 经度:115度49.5439分东经
  • 地面速度:0.00节
  • 地面航向: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)消息,包含了以下关键信息:

  • 地面航向:44.25度(真北参考)
  • 地面速度:0.00节(节与海里/小时是相同的)
  • 地面速度:0.00千米/小时
  • 模式指示:A(自主定位导航模式)

(8)$GNZDA,114955.000,06,11,2017,00,00*47 这是ZDA(Time and Date)消息,包含了以下关键信息:

  • UTC时间:11时49分55秒
  • 日期:06日11月17年
  • 本地时区偏移:00小时00分钟

(9)$GPTXT,01,01,01,ANTENNA OK*35 这是TXT(Text Transmission)消息,包含了以下关键信息:

  • 文本内容:ANTENNA OK(表示天线状态良好)

这些消息提供了GPS设备的时间、位置、定位质量、可见卫星数量等信息。其中涉及到的字段包括时间(UTC时间)、纬度、经度、定位质量指示、使用卫星编号、定位精度因子、海拔高度、速度等。根据不同的应用需求,可以从这些数据中提取出需要的信息来进行处理和分析。

三、C语言解析数据代码

3.1 解析每个字段数据

以下是使用C语言解析NMEA 0183数据字段并将其打印到串口:

#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 解析定位数据

定义了一个名为GPSData的结构体,并将解析后的定位数据存储在该结构体的各个变量中:

#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");
}

这段代码会解析NMEA 0183格式的数据,并将解析的结果存储在GPSData结构体的对应变量中。使用printGPSData函数将数据打印到串口。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/901844.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机竞赛 卷积神经网络手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

(202308)科研论文配图 task1 书籍第一章阅读

《科研论文配图绘制指南——基于python》阅读笔记 第一章阅读笔记 《科研论文配图绘制指南——基于python》阅读笔记序言阅读笔记1.1 绘制基础绘制原则 1.2 配色基础1.2.1 色彩格式1.2.2 色轮配色原理1.2.3 颜色主题1.2.4 配色工具 序言 有幸在这次的组队学习活动中&#xff0…

14----表格

本节我们将学习markdown表格的相关知识&#xff1a; 一、表格的基本知识&#xff1a; 1. 打印表格&#xff1a; 表格使用竖线|区分每一列&#xff0c;在表格头和表格体之间使用至少一个减号-来分隔表头和表格内容(一般使用3个-)。表格的行由自然行来区分(自然行就是我们平常…

MySQL数据库——SQL(3)-DQL(基本查询、条件查询、聚合函数、分组查询、排序查询、分页查询、案例练习)

目录 语法 基本查询 1.查询多个字段 2.设置别名 3.去除重复记录 示例 条件查询 1.语法 2.条件 示例 聚合函数 介绍 常见聚合函数 语法 示例 分组查询 语法 示例 排序查询 1.语法 2.排序方式 示例 分页查询 语法 示例 DQL案例练习 执行顺序 DQL总结…

【Linux操作系统】Linux系统编程中的共享存储映射(mmap)

在Linux系统编程中&#xff0c;进程之间的通信是一项重要的任务。共享存储映射&#xff08;mmap&#xff09;是一种高效的进程通信方式&#xff0c;它允许多个进程共享同一个内存区域&#xff0c;从而实现数据的共享和通信。本文将介绍共享存储映射的概念、原理、使用方法和注意…

降级gcc和g++为版本gcc-7和g++-7

错误提示&#xff1a; /usr/local/cuda-10.1/include/crt/host_config.h:129:2: error: #error -- unsupported GNU version! gcc versions later than 8 are not supported! 129 | #error -- unsupported GNU version! gcc versions later than 8 are not supported! …

TiDB 源码编译之 TiFlash 篇

作者&#xff1a; ShawnYan 原文来源&#xff1a; https://tidb.net/blog/5f3fe44d 导言 TiFlash 从去年四月一日开源至今已经过去将近一年半&#xff0c;这段时间里 TiFlash 从 v6.0.0-DMR 升级到了 v7.3.0-DMR &#xff0c;并增加了若干新特性&#xff0c;比如支持 …

aardio的CS架构mysql数据表查询实例

import win.ui; /*DSG{{*/ var winform win.form(text"aardio form";right759;bottom479) winform.add( buttonAdd{cls"button";text"复制";left516;top442;right587;bottom473;z11}; buttonClose{cls"button";text"退出";…

HTML详解连载(8)

HTML详解连载&#xff08;8&#xff09; 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽浮动-产品区域布局场景 解决方法清除浮动方法一&#xff1a;额外标签发方法二&#xff1a;单伪元素法方法三&#xff1a;双伪元素法方法四&#xff1a;overflow浮动-总结…

漫谈红黑树:红黑树的奇妙演化

漫谈红黑树&#xff1a;红黑树的奇妙演化 一、红黑树的提出二、红黑树性质的简单推导三、结论 博主简介 &#x1f4a1;一个热爱分享高性能服务器后台开发知识的博主&#xff0c;目标是通过理论与代码实践的结合&#xff0c;让世界上看似难以掌握的技术变得易于理解与掌握。技能…

Dockerfile快速搭建自己专属的LAMP环境

目录 编写Dockerfile 1.文件内容需求&#xff1a; 2.值得注意的是centos6官方源已下线&#xff0c;所以需要切换centos-vault源&#xff01; 3.Dockerfile内容 4.进入到 lamp 开始构建镜像 推送镜像到私有仓库 1.创建用户并添加到私有仓库&#xff1a;​编辑​编辑 2.推…

CK-A60180、CK-B1542、CK-L3095单向离合器

CK-A1542、CK-A1747、CK-A2052、CK-A2652、CK-A3072、CK-A3580、CK-A4090、CK-A45100、CK-A450110、CK-A60130、CK-A65140、CK-A70150、CK-A75160、CK-A80170、CK-A1250、CK-A1855、CK-A2060、CK-A2563、CK-A2563T、CK-A2870、CK-A3080T、CK-A3585、CK-A35100、CK-A35140、CK-A…

Mybatis对参数的处理

环境配置 项目结构 导入依赖 <dependencies><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><dependency><groupId>mysql</grou…

16、可重入锁+设计模式

可重入锁设计模式 while判断并自旋重试获取锁setnx含自然过期时间Lua脚本官网删除锁命令但不能保证可重如 问题&#xff0c;如何兼顾锁的可重入性问题&#xff1f; 可重入锁 可重入锁又名递归锁 是指在同一个线程在外层方法获取锁的时候&#xff0c;再进入该线程的内层方法…

Vue实战

初始化项目 创建项目 指令&#xff1a; pnpm create vite 实例&#xff1a; C:\Users\Administrator\Desktop\Vue\Vue3_admin_template>pnpm create vite .../Local/pnpm/store/v3/tmp/dlx-6140 | 1 Packages are hard linked from the content-addressable store to…

单体版ruoyi表格绑定按钮

先需要在表格中添加一个按钮&#xff0c;可以快速操作这条数据的某个0/1状态 表格的列 editFlag是检验用户是否有操作的权限 var editFlag [[${permission.hasPermi(pipayshop:itemCommoidtyInfoCategoryTop:edit)}]]; 绑定状态条 /* 用户状态显示 */function statusTools(…

我和 TiDB 的故事 | 远近高低各不同

作者&#xff1a; ShawnYan 原文来源&#xff1a; https://tidb.net/blog/b41a02e6 Hi, TiDB, Again! 书接上回&#xff0c; 《我和 TiDB 的故事 | 横看成岭侧成峰》 &#xff0c;一年时光如白驹过隙&#xff0c;这一年我好似在 TiDB 上投入的时间总量不是很多&#xff0…

baidu一面二叉树路径组数求和

举例&#xff1a;如下图&#xff0c;124125136 386 int sumTree(TreeNode* node,int sum){if(nodenullptr){return 0;}if(node->leftnullptr && node->rightnullptr){sum*10;sumnode->val;return sum;}sum *10;sum node->val;int sum_left sumTree(no…

网络安全---Ring3下动态链接库.so函数劫持

一、动态链接库劫持原理 1.1、原理 Unix操作系统中&#xff0c;程序运行时会按照一定的规则顺序去查找依赖的动态链接库&#xff0c;当查找到指定的so文件时&#xff0c;动态链接器(/lib/ld-linux.so.X)会将程序所依赖的共享对象进行装载和初始化&#xff0c;而为什么可以使用…

NPM 创建和管理组织

目录 1、创建一个组织 2、将用户帐户转换为组织 3、组织中开启双因素身份验证 3.1 关于组织的双因素身份验证 3.2 先决条件 3.3 在您的组织中要求双因素身份验证 3.4 帮助已删除的成员和外部协作者重新加入您的组织 4、重命名组织 5、删除组织 1、创建一个组织 任何n…