当前位置: 首页 > news >正文

GPS定位数据解析:从NMEA到实际坐标(5/10)

GPS定位数据解析:从NMEA到实际坐标(5/10)

作者:宋一平
分类:嵌入式 / 传感器 / 物联网
预计阅读:12分钟


一、GPS基础知识

1.1 GPS工作原理

GPS(Global Positioning System,全球定位系统)通过三球交汇定位原理确定位置:

┌─────────────────────────────────────────────────────┐ │ GPS定位原理 │ │ │ │ 卫星1 ◄─────┐ │ │ │ │ │ 卫星2 ◄─────┼─────► 接收机位置(交点) │ │ │ │ │ 卫星3 ◄─────┘ │ │ │ │ 原理:测量到3颗卫星的距离,通过几何计算得出位置 │ │ 实际:需要4颗卫星(第4颗用于时间校准) │ │ │ └─────────────────────────────────────────────────────┘

定位过程

  1. 接收机接收卫星信号
  2. 解算到各卫星的距离(伪距)
  3. 通过几何计算得出经纬度、高度、时间

1.2 NMEA协议介绍

NMEA-0183是美国国家海洋电子协会制定的GPS数据格式标准。

特点

  • 文本格式,易于解析
  • $开头,\r\n结尾
  • 逗号分隔各字段
  • 校验和(可选)

常见语句类型

语句全称内容
$GNRMCRecommended Minimum推荐最小定位信息(时间+位置)
$GNGGAGlobal Positioning Fix Data定位数据(高度+卫星数)
$GNGSADOP and Active Satellites卫星精度因子
$GPGSVSatellites in View可见卫星信息

本项目使用$GNRMC:包含时间和位置信息,足以满足需求。

1.3 $GNRMC语句结构

$GNRMC,092846.400,A,3029.7317,N,10404.1784,E,000.0,183.8,190428,,,A*73\r\n
字段内容说明
$GNRMC语句标识推荐最小定位信息
092846.400UTC时间09:28:46.400(北京时间需+8小时)
A定位状态A=有效,V=无效
3029.7317纬度30°29.7317’
N纬度半球N=北纬,S=南纬
10404.1784经度104°04.1784’
E经度半球E=东经,W=西经
000.0地速节(1节=1.852km/h)
183.8方位角
190428UTC日期2019年4月28日
A模式A=自动,D=差分

二、NMEA数据解析

2.1 经纬度格式转换

NMEA中的经纬度是度分格式,需要转换为十进制度

原始数据:3029.7317,N 含义:30度29.7317分 转换公式: 十进制度 = 度 + 分/60 计算: 30 + 29.7317/60 = 30 + 0.49553 = 30.49553°

代码实现

// 将度分格式转换为十进制度doubledmm_to_decimal(doubledmm){intdegrees=(int)(dmm/100);// 提取度doubleminutes=dmm-degrees*100;// 提取分returndegrees+minutes/60.0;// 转换为十进制度}// 示例doublelat=dmm_to_decimal(3029.7317);// 结果:30.49553

2.2 时间转换

UTC时间需要转换为北京时间(UTC+8):

// UTC时间转北京时间voidutc_to_beijing(u8*hour){*hour=(*hour+8)%24;// 加8小时,超过24取模}// 示例:UTC 09:28:46 → 北京时间 17:28:46

2.3 解析函数实现

核心解析函数,按逗号分隔提取各字段:

/** * @brief 从字符串中提取指定字段 * @param pstr 源字符串 * @param buf 输出缓冲区 * @param buflen 缓冲区大小 * @param s 起始逗号位置(从0开始) * @param e 结束逗号位置 * @return 字段长度,失败返回-1 */intcomma_split(unsignedchar*pstr,char*buf,intbuflen,ints,inte){inti=0,k=0;intcommaCount=0;if(e<=s)return-1;// 找到起始逗号while(pstr[i]!='\0'){if(pstr[i]==',')commaCount++;if(commaCount==s){k=++i;// 记录起始位置break;}i++;}// 找到结束逗号,提取字段while(pstr[i]!='\0'){if(pstr[i]==',')commaCount++;if(commaCount==e){if(i-k+1>buflen)return-1;memcpy(buf,pstr+k,i-k);buf[i-k]='\0';returni-k;}i++;}return-1;}

三、代码实现

3.1 数据结构定义

/** * @brief GNRMC解析结果结构体 */structGNRMC_Info{// 时间信息unsignedintyear;// 年unsignedcharmonth;// 月unsignedcharday;// 日unsignedcharhour;// 时(已转换为北京时间)unsignedcharMinute;// 分unsignedcharsecond;// 秒// 位置信息unsignedintlongitude;// 经度(整数部分,乘以10000)unsignedintlatitude;// 纬度(整数部分,乘以10000)charlongitude_suffix;// 经度半球 E/Wcharlatitude_suffix;// 纬度半球 N/S// 状态unsignedcharposition_valid;// 定位是否有效};// 全局变量structGNRMC_InfoGNRMC;// 解析结果

3.2 完整解析函数

/** * @brief 解析GNRMC语句 * @param pstr NMEA字符串 * @param pGNRMCInfo 输出结构体 * @return 0:成功, <0:失败 */intGNRMC_Parse(unsignedchar*pstr,structGNRMC_Info*pGNRMCInfo){intlen=0;intcommaCount=0;doubletemp=0;charbuf[32]={0};// 1. 统计逗号数量,验证格式while(pstr[len]!='\0'){if(pstr[len]==',')commaCount++;len++;}if(commaCount!=12)return-1;// GNRMC有12个逗号// 2. 验证起始字符:$GNRMCif(strncmp((char*)pstr,"$GNRMC",6)!=0)return-1;// 3. 验证结束字符:\r\nif(pstr[len-2]!='\r'||pstr[len-1]!='\n')return-1;// 4. 解析UTC时间(字段1)len=comma_split(pstr,buf,sizeof(buf),1,2);if(len<0)return-1;// 格式:hhmmss.ssspGNRMCInfo->hour=((buf[0]-'0')*10+(buf[1]-'0')+8)%24;// 转北京时间pGNRMCInfo->Minute=(buf[2]-'0')*10+(buf[3]-'0');pGNRMCInfo->second=(buf[4]-'0')*10+(buf[5]-'0');// 5. 解析定位状态(字段2)len=comma_split(pstr,buf,sizeof(buf),2,3);if(len!=1)return-1;pGNRMCInfo->position_valid=(buf[0]=='A')?1:0;// 6. 解析纬度(字段3)len=comma_split(pstr,buf,sizeof(buf),3,4);if(len<0)return-1;temp=atof(buf);pGNRMCInfo->latitude=(unsignedint)(temp*10000);// 7. 解析纬度半球(字段4)len=comma_split(pstr,buf,sizeof(buf),4,5);if(len!=1)return-1;pGNRMCInfo->latitude_suffix=buf[0];// 8. 解析经度(字段5)len=comma_split(pstr,buf,sizeof(buf),5,6);if(len<0)return-1;temp=atof(buf);pGNRMCInfo->longitude=(unsignedint)(temp*10000);// 9. 解析经度半球(字段6)len=comma_split(pstr,buf,sizeof(buf),6,7);if(len!=1)return-1;pGNRMCInfo->longitude_suffix=buf[0];// 10. 解析UTC日期(字段9)len=comma_split(pstr,buf,sizeof(buf),9,10);if(len<0)return-1;// 格式:ddmmyypGNRMCInfo->day=(buf[0]-'0')*10+(buf[1]-'0');pGNRMCInfo->month=(buf[2]-'0')*10+(buf[3]-'0');pGNRMCInfo->year=(buf[4]-'0')*10+(buf[5]-'0')+2000;return0;}

3.3 GPS数据处理任务

u8 gps_recebuf[200];intgps_recelen;/** * @brief GPS数据处理函数 */voidgps_process(void){// 仅在非加注状态时处理GPSif(EventSeek(&var.Event_1,eSYS_SA|ePRICE_OPT,OR)==0){// 切换串口到GPS模式_4052A_OUT=0;// 4052模拟开关控制vTaskDelay(5);// 清空串口缓冲while(UARTRead(U_4,gps_recebuf,&gps_recelen)==0){vTaskDelay(5);}// 等待GPS数据while(UARTRead(U_4,gps_recebuf,&gps_recelen)==0){vTaskDelay(5);}// 解析GPS数据al_gps(gps_recebuf,gps_recelen);// 清空缓冲区memset(gps_recebuf,0,200);// 切换串口回其他模式_4052A_OUT=1;}}/** * @brief GPS数据回调函数 */voidal_gps(u8*buf,u8 len){char*prt;// 查找\r\n结尾prt=strstr((char*)buf,"\r\n");if(prt!=0){*(prt+2)=0x00;// 截断字符串// 解析GNRMCGNRMC_Parse(buf,&GNRMC);if(GNRMC.position_valid>0){// 定位有效,打印信息printf("时间:%d-%d-%d %d:%d:%d\n",GNRMC.year,GNRMC.month,GNRMC.day,GNRMC.hour,GNRMC.Minute,GNRMC.second);printf("经纬度:%u.%c|%u.%c\n",GNRMC.longitude,GNRMC.longitude_suffix,GNRMC.latitude,GNRMC.latitude_suffix);}}}

3.4 使用示例

// 测试数据char*test_gps="$GNRMC,092846.400,A,3029.7317,N,10404.1784,E,000.0,183.8,190428,,,A*73\r\n";intmain(void){// 解析GPS数据GNRMC_Parse((unsignedchar*)test_gps,&GNRMC);// 输出结果if(GNRMC.position_valid){printf("定位有效\n");printf("日期: %d-%02d-%02d\n",GNRMC.year,GNRMC.month,GNRMC.day);printf("时间: %02d:%02d:%02d\n",GNRMC.hour,GNRMC.Minute,GNRMC.second);printf("经度: %u%c\n",GNRMC.longitude,GNRMC.longitude_suffix);printf("纬度: %u%c\n",GNRMC.latitude,GNRMC.latitude_suffix);}return0;}/* 输出: 定位有效 日期: 2019-04-28 时间: 17:28:46 经度: 104041784E 纬度: 30297317N */

四、实际应用

4.1 本项目GPS使用方式

玻璃水加注机中GPS用于设备位置上报

┌─────────────────────────────────────────────────────┐ │ GPS数据流向 │ │ │ │ GPS模块 ──(串口)──► STM32 ──(GPRS)──► 云服务器 │ │ │ │ │ │ │ │ │ │ │ │ NMEA数据 解析处理 位置上报 │ │ │ └─────────────────────────────────────────────────────┘

4.2 上传数据格式

// 生成上报字符串voidrecord_make(void){u32 gpsx_xs=0;u32 gpsy_xs=0;// 经纬度转换gpsx_xs=(GNRMC.longitude%1000000)/6;// 小数部分gpsy_xs=(GNRMC.latitude%1000000)/6;// 生成上报字符串sprintf((char*)var.record,"id=%s|total=%d|money=%d|price=%d|GPSX=%u.%5u|GPSY=%u.%5u|",db_var.id,var.db_tpu/10,(var.db_tpu*var.price)/1000,var.price,GNRMC.longitude/1000000,gpsx_xs,GNRMC.latitude/1000000,gpsy_xs);// 示例输出:// id=00000001|total=20|money=200|price=10|GPSX=104.04178|GPSY=30.29731|}

4.3 硬件连接

本项目使用ATGM336HGPS模块:

┌─────────────────────────────────────────────────────┐ │ GPS模块连接 │ │ │ │ ATGM336H STM32F103 │ │ ┌────────┐ ┌────────┐ │ │ │ VCC │◄─────────►│ 3.3V │ │ │ │ GND │◄─────────►│ GND │ │ │ │ TXD │──────────►│ PC11 │ (UART4_RX) │ │ │ RXD │◄──────────│ PC10 │ (UART4_TX) │ │ │ PPS │ │ │ (可选,时间同步) │ │ └────────┘ └────────┘ │ │ │ │ 注意:GPS模块需要室外天线,室内信号弱 │ │ │ └─────────────────────────────────────────────────────┘

五、精度优化

5.1 多次采样取平均

#defineGPS_SAMPLE_COUNT5u32get_avg_longitude(void){u32 sum=0;u8 valid_count=0;for(u8 i=0;i<GPS_SAMPLE_COUNT;i++){gps_process();// 采集GPS数据if(GNRMC.position_valid){sum+=GNRMC.longitude;valid_count++;}vTaskDelay(1000);// 间隔1秒}if(valid_count>0)returnsum/valid_count;elsereturn0;}

5.2 数据校验

/** * @brief 校验NMEA数据的校验和 * @param pstr NMEA字符串 * @return 0:校验通过, <0:校验失败 */intverify_checksum(unsignedchar*pstr){unsignedcharchecksum=0;unsignedcharreceived_checksum=0;charbuf[3];char*p;// 找到*号p=strchr((char*)pstr,'*');if(p==NULL)return-1;// 计算$到*之间的异或值for(inti=1;i<(p-(char*)pstr);i++){checksum^=pstr[i];}// 读取接收到的校验和buf[0]=*(p+1);buf[1]=*(p+2);buf[2]='\0';received_checksum=(unsignedchar)strtol(buf,NULL,16);// 比较if(checksum==received_checksum)return0;elsereturn-1;}

六、常见问题

Q1:定位慢怎么办?

原因分析

  • 冷启动:模块断电后重新上电,需要重新搜星
  • 室内环境:信号被遮挡
  • 天线问题:天线位置不当

解决方案

// 1. 使用热启动// 断电前保存星历数据到EEPROM,上电后恢复// 2. 增加定位超时时间#defineGPS_TIMEOUT_MS60000// 60秒超时// 3. 使用AGPS辅助定位// 通过GPRS下载辅助数据,加速定位

Q2:信号弱怎么处理?

// 1. 检查信号强度(通过$GNGGA语句)// 2. 增加重试次数// 3. 使用外置天线// 信号质量判断intcheck_gps_quality(void){// 卫星数量 > 4 才能定位// HDOP < 2.0 精度较好if(GNRMC.position_valid==0)return-1;// 无定位return0;}

Q3:室内能定位吗?

不能。GPS信号无法穿透建筑。

替代方案

  • WiFi定位(室内有WiFi)
  • 蓝牙信标定位
  • 使用固定坐标(设备安装后手动配置)
// 手动配置GPS坐标if(db_var.gps_mode==1)// 手动模式{// 使用预设坐标sprintf((char*)var.record,"GPSX=%s|GPSY=%s|",db_var.gpsx,db_var.gpsy);}

Q4:定位数据跳变?

原因:GPS定位误差导致

解决:添加滤波算法

// 简单的限幅滤波#defineGPS_MAX_CHANGE100// 最大变化量u32filter_longitude(u32 new_value){staticu32 last_value=0;staticu8 first=1;if(first){last_value=new_value;first=0;returnnew_value;}// 变化量过大,可能是跳变if(abs(new_value-last_value)>GPS_MAX_CHANGE){returnlast_value;// 保持上次值}last_value=new_value;returnnew_value;}

七、总结

7.1 GPS解析要点

要点说明
NMEA格式文本协议,逗号分隔字段
时间转换UTC+8 = 北京时间
经纬度转换度分格式 → 十进制度
有效性判断position_valid = ‘A’
校验和可选,用于数据完整性校验

7.2 本项目GPS应用

  • 模块:ATGM336H
  • 接口:UART4,9600波特率
  • 用途:设备位置上报
  • 频率:非加注状态时采集

7.3 优化建议

  1. 多次采样取平均,提高精度
  2. 添加数据校验,防止异常数据
  3. 室外天线,保证信号质量
  4. 支持手动配置坐标,解决室内定位问题

八、源码获取

本文完整源码已收录至「STM32物联网项目资料包」

资料包包含

  • ✅ GPS解析完整代码(GNRMC_Parse)
  • ✅ 玻璃水加注机完整工程
  • ✅ 外设驱动代码模板
  • ✅ 调试技巧文档
  • ✅ 常见问题FAQ

获取方式

  1. 点赞 + 收藏本文
  2. 私信我,备注「资料」免费领取

作者:宋一平 | 嵌入式/物联网技术分享
转载请注明出处

http://www.jsqmd.com/news/508685/

相关文章:

  • 2025_NIPS_SATURN: SAT-based Reinforcement Learning to Unleash Language Model Reasoning
  • Android用户必看:如何识别并防范CRaxsRat v7.4这类远程控制木马
  • 亲测有效:2026年教育机构代理招生平台分享 - 企业推荐官【官方】
  • 解锁3大高效技能:专业级网页资源捕获完全指南
  • Pi0视觉语言动作模型快速上手:从安装到运行完整教程
  • System V IPC底层原理详解
  • S7通信随笔
  • 一键调用GLM-4.7-Flash API:Ollama部署后的进阶使用教程
  • 从智能卡到物联网:一文读懂GPC-SCP03安全通道协议在JavaCard™密钥管理中的实战应用
  • Qwen3.5-9B强化学习泛化能力落地:百万级任务适配部署步骤详解
  • yz-女生-角色扮演-造相Z-Turbo生成效果优化:提示词工程指南
  • 告别繁琐安装!m3u8live.cn 在线M3U8播放器,粘贴即播超省心
  • 辽阳市鼎盛模具厂. - 企业推荐官【官方】
  • Qwen3-32B-Chat RTX4090D部署案例:科研论文润色助手私有化部署
  • 基于SDPose-Wholebody的Python爬虫数据可视化分析
  • CTLA-4抗体如何重塑肿瘤免疫治疗格局?
  • Qt文件操作全解析:QFile vs QDataStream vs QTextStream如何选择?
  • 文墨共鸣应用案例:某重点中学语文教研组‘作文互评AI助手’落地过程全记录
  • Windows下用CDO处理CMIP6气象数据的完整避坑指南(附批量裁剪脚本)
  • Z-Image-Turbo-rinaiqiao-huiyewunv部署案例:校园动漫社本地AI绘图工作站搭建实录
  • 【行测】常识知识-近代史1(1840-启)
  • 江西土特产哪家强?亲测这家靠谱 - 企业推荐官【官方】
  • 思通AI视频监控系统开源版深度解析:5分钟部署,20个免费模型,开启智能监控新纪元
  • Qwen3.5-9B开源大模型效果展示:百万RLHF强化学习泛化能力案例集
  • Qwen3-Reranker-0.6B零基础部署:5分钟搞定文本重排序服务
  • 【从零开始实现STM32步进电机驱动】(二)搭建硬件环境
  • 2026年太原GEO优化公司推荐Top5:AI搜索获客时代的本地服务商选型指南 - 小白条111
  • 2026年 全氟聚醚润滑脂厂家推荐排行榜,半导体设备/新能源汽车/精密仪器专用,高温长效耐腐蚀润滑脂品牌深度解析 - 品牌企业推荐师(官方)
  • 背发光字的
  • 移动端录音APP集成FRCRN SDK效果演示:前后录音质感飞跃