news 2026/9/2 20:59:35

【0183转808协议系列】(二)如何用linux C语言实现$GPRMC报文解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【0183转808协议系列】(二)如何用linux C语言实现$GPRMC报文解析

NMEA 0183协议对RMC消息的定义如下:

我们从串口读取到的模组输出的LOG,有时候可能是好几行数据,所以我们要逐行解析$GPRMC报文。

bytes_read = read_serial(serial_fd, recv_buffer, sizeof(recv_buffer) - 1); if (bytes_read > 0) { recv_buffer[bytes_read] = '\0'; printf("\n\n通过串口从RTK模组读取到原始定位数据:\n%s", recv_buffer); // 解析GPRMC数据并处理JT808协议转换 line = strtok_r(recv_buffer, "\r\n", &saveptr); while (line != NULL) { memset(&gps_data, 0, sizeof(gps_data)); if (parse_gprmc(line, &gps_data) == 0) { printf("\n解析到有效GPS数据:\n纬度=%f, 经度=%f, " "速度=%f, 航向=%f, 日期=%s, 时间=%s\n", gps_data.latitude, gps_data.longitude, gps_data.speed, gps_data.direction, gps_data.date, gps_data.time); ......此处省略代码若干 line = strtok_r(NULL, "\r\n", &saveptr); } }

此处用了strtok_r去分隔字符串而不是用strtok,可以避免原字符串被改变。用while循环去分隔每一行数据,然后对每一行数据进行解析。

解析函数需要实现如下功能:

输入验证‌
首先检查报文是否以$GPRMC开头,确保是GPRMC报文。
使用strncpy复制输入字符串到缓冲区,并确保以\0结尾。

‌字段解析‌
使用strtok_r按逗号分隔报文字段,saveptr保存分隔状态。
可以通过switch语句逐字段解析:
‌时间(HHMMSS)‌:直接复制到gps->time。
‌状态(A/V)‌:存储到gps->status。
‌纬度/经度‌:
为了与JT808协议要求的经纬度格式一致,所以需要将读取到的将度分秒格式(如3104.39321639)的经纬度转换为小数度(如31.073220271666668)。
可以通过atof转换为浮点数,计算分和秒部分。
‌速度/方向‌:直接转换为浮点数存储。
‌日期(DDMMYY)‌:复制到gps->date。

‌错误处理‌
若字段数超过12或非GPRMC报文,返回-1表示解析失败。

具体代码实现如下:

int parse_gprmc(const char *nmea, GPSData *gps) { char buffer[256]; char *token; char *saveptr; // 用于strtok_r的保存指针 int field_count = 0; double lat_sec, lon_sec; int lat_min, lon_min; strncpy(buffer, nmea, sizeof(buffer) - 1); buffer[sizeof(buffer) - 1] = '0'; // 检查是否为GPRMC报文 if (strncmp(buffer, "$GPRMC", 6) != 0) { return -1; } token = strtok_r(buffer, ",", &saveptr); while (token != NULL && field_count < 12) { switch (field_count) { case 1: // 时间 HHMMSS strncpy(gps->time, token, sizeof(gps->time) - 1); break; case 2: // 状态 A/V gps->status = token[0]; break; case 3: // 纬度 if (strlen(token) > 0) { lat_min = (int)(atof(token) / 100); lat_sec = (atof(token) - lat_min * 100); gps->latitude = lat_min + lat_sec / 60.0; } break; case 4: // 纬度半球 N/S // 可根据需要处理 break; case 5: // 经度 if (strlen(token) > 0) { lon_min = (int)(atof(token) / 100); lon_sec = (atof(token) - lon_min * 100); gps->longitude = lon_min + lon_sec / 60.0; } break; case 6: // 经度半球 E/W // 可根据需要处理 break; case 7: // 速度 if (strlen(token) > 0) { gps->speed = atof(token); } break; case 8: // 方向 if (strlen(token) > 0) { gps->direction = atof(token); } break; case 9: // 日期 DDMMYY strncpy(gps->date, token, sizeof(gps->date) - 1); break; } field_count++; token = strtok_r(NULL, ",", &saveptr); } return (gps->status == 'A') ? 0 : -1; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 12:53:21

35岁大龄程序员破局指南:突破“中年危机”魔咒,开启职业第二春!

“35岁危机”曾是悬在程序员头顶的达摩克利斯之剑&#xff0c;但在技术快速迭代的今天&#xff0c;这条年龄线甚至被提前到了30岁。根据某一线互联网公司内部数据&#xff0c;35岁以上程序员主动离职率比30岁以下高出40% &#xff0c;而再就业周期平均延长3-6个月。 这不仅是年…

作者头像 李华
网站建设 2026/9/1 20:16:17

5.3 LlamaFactory 微调实战:微调 Qwen DeepSeek 模型

LlamaFactory 微调实战:微调 Qwen/DeepSeek 模型 导语:理论的尽头是实践。我们已经理解了 LoRA 的原理,并学会了如何“指挥”GPT-4 为我们生产高质量的微调数据。现在,万事俱备,只欠“开炉炼丹”。本章将是一次纯粹的、从头到尾的动手实战。我们将使用 LlamaFactory,一个…

作者头像 李华
网站建设 2026/9/2 15:30:56

5.8 垂直领域 Agent 的未来:探索模型微调在金融、法律等行业的应用

5.8 垂直领域 Agent 的未来:探索模型微调在金融、法律等行业的应用 导语:在本课程的最后一章,让我们将目光从具体的代码和技术细节中抬起,投向更广阔的星辰大海。我们已经通过“AI 皮肤科医生”项目,亲眼见证了模型微调如何将一个通用模型“点化”为垂直领域的专家。然而,…

作者头像 李华
网站建设 2026/8/30 11:38:50

【干货】具身智能技术路线全解:大模型如何走进物理世界,一文掌握核心技术!

简介 具身智能作为AI连接物理世界的关键途径&#xff0c;主要有分层决策与端到端两种技术架构&#xff0c;以及模仿学习与强化学习两种训练方法。各路线各有优劣&#xff0c;数据获取是具身智能发展的核心。商业化路径包括通用技术、纯软件和垂直领域三大方向。未来具身智能将向…

作者头像 李华
网站建设 2026/9/1 13:17:08

从机器学习理论到动手实战教程!(附学习资料)

很多学习机器学习和深度学习的同学&#xff0c;follow的学习教程往往理论和实践是分开的&#xff0c;这就容易导致学习了相关理论但是不知道如何应用的问题学习机器学习深度学习的过程中&#xff0c;理论的重要性不用过多强调&#xff0c;其次在实战中处理数据&#xff0c;搭建…

作者头像 李华
网站建设 2026/9/1 17:26:13

海南封关,到底“一线”如何放,“二线”又如何管?

“一线”指的是海南自贸港和我国关境外的其他国家和地区之间&#xff0c;“二线”指的是海南自贸港和内地之间。 海南自贸港封关的核心就是“一线”放开&#xff0c;“二线”管住&#xff0c;岛内自由。 “一线”放开放什么呢&#xff1f; 6600多种货物可以免关税进入海南岛…

作者头像 李华