U-BLOX GPS 模块及GPRMC指令解析

article/2025/10/16 8:05:58

        受朋友所托,调试一款GPS模块,该模块是UBLOX的NEO-6M GPS模组。想到用这款GPS的人较多,自己日后也有可能在用到这个模块,就写下这份笔记。

一、介绍

        基本信息如下:

1、 模块采用U-BLOX NEO-6M模组,体积小巧,性能优异。

2、 模块增加放大电路,有利于无缘陶瓷天线快速搜星。

3、 模块可通过串口进行各种参数设置,并可保存在EEPROM,使用方便。

4、 模块自带SMA接口,可以连接各种有源天线,适应能力强。

5、 模块兼容3.3V/5V电平,方便连接各种单片机系统。

6、 模块自带可充电后备电池,可以掉电保持星历数据。

        看到这里,就可以知道,这个模块是高度集成的,有点类似于西门子华为等公司的GPRS模块,基本上就是一个小的系统,用户只需要用AT命令通过串口通信就可以完成所有工作。那么这款模块的使用,其实就是字符串的解析工作了。

二、通信协议

        GPS模块采用NMEA 0183协议,NMEA 0183是美国国家海洋电子协会(National Marine Electronics Association)为海用电子设备制定的标准格式。目前业已成了GPS导航设备统一的RTCM(Radio Technical Commission for Maritime services)标准协议。NMEA-0183协议采用ASCII码来传递GPS定位信息,我们称之为帧。

        帧格式形如:

$aaccc,ddd,ddd,„,ddd*hh(CR)(LF)

1、“$”:帧命令起始位

2、aaccc:地址域,前两位为识别符(aa),后三位为语句名(ccc)

3、ddd„ddd:数据

4、“*”:校验和前缀(也可以作为语句数据结束的标志)

5、hh:校验和,$与*之间所有字符ASCII码的校验和(各字节做异或运算,得到

校验和后,再转换16进制格式的ASCII字符)

6、(CR)(LF):帧结束,回车和换行符

        在一般的项目中,最常用的指令是第4个,即$GPRMC ,推荐定位信息,长度70字节。$GPRMC(推荐定位信息,Recommended Minimum Specific GPS/Transit Data),$GPRMC语句的基本格式如下: 

$GPRMC,(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)*hh(CR)(LF)

(1) UTC时间,hhmmss(时分秒)

(2) 定位状态,A=有效定位,V=无效定位

(3) 纬度ddmm.mmmmm(度分)

(4) 纬度半球N(北半球)或S(南半球)

(5) 经度dddmm.mmmmm(度分)

(6) 经度半球E(东经)或W(西经)

(7) 地面速率(000.0~999.9节)

(8) 地面航向(000.0~359.9度,以真北方为参考基准)

(9) UTC日期,ddmmyy(日月年)

(10)磁偏角(000.0~180.0度,前导位数不足则补0)

(11) 磁偏角方向,E(东)或W(西)

(12) 模式指示(A=自主定位,D=差分,E=估算,N=数据无效)

 举例如下:

$GPRMC,023543.00,A,2308.28715,N,11322.09875,E,0.195,,240213,,,A*78

三、PC端显示数据 

        GPS模块有一个PC配置软件,叫做u-Center,可以对模块进行参数设置,然后保存到EEPROM,其实也可以通过单片机串口通信进行设置,但是PC端设置更加人性化,可以立刻看到结果。

        打开GPS模块之后,接上u-Center软件,可以看到如下数据。 

   $GPGSV,,,,,,,,,,,,,,,,,,,*7D$GPRMC,132043.00,V,,,,,,,,,,N*7F$GPVTG,,,,,,,,,N*$GPGSA,A,,,,,,,,,,,,,,99.99,99.99,99.99*$GPGSV,,,,,,,,,,,,,,,,,,,*7B$GPGSV,,,,,,,,,,,,,,,,,,,*7D$GPRMC,132044.00,V,,,,,,,,,,N*$GPVTG,,,,,,,,,N*$GPGSA,A,,,,,,,,,,,,,,99.99,99.99,99.99*$GPGSV,,,,,,,,,,,,,,,,,,,*7B$GPGSV,,,,,,,,,,,,,,,,,,,*7A$GPRMC,132045.00,V,,,,,,,,,,N*$GPVTG,,,,,,,,,N*$GPGSA,A,,,,,,,,,,,,,,99.99,99.99,99.99*$GPGSV,,,,,,,,,,,,,,,,,,,*7B$GPGSV,,,,,,,,,,,,,,,,,,,*7D$GPRMC,132046.00,V,,,,,,,,,,N*7A$GPVTG,,,,,,,,,N*$GPGSV,,,,,,,,,,,,,,,,,,,*7B$GPGSV,,,,,,,,,,,,,,,,,,,*$GPRMC,132049.00,V,,,,,,,,,,N*$GPRMC,133300.00,V,,,,,,,,,,N*7A$GPRMC,133301.00,V,,,,,,,,,,N*7B$GPRMC,133302.00,V,,,,,,,,,,N*$GPRMC,133303.00,V,,,,,,,,,,N*$GPRMC,133304.00,V,,,,,,,,,,N*7E$GPRMC,133305.00,V,,,,,,,,,,N*7F$GPRMC,133306.00,A,3949.63075,N,11616.48616,E,0.513,,,,,A*7A$GPRMC,133307.00,A,3949.63025,N,11616.48614,E,1.053,,,,,A*7C$GPRMC,133308.00,A,3949.63002,N,11616.48641,E,1.101,,,,,A*

四、PC端软件配置

        GPS有7种指令数据输出,如果我们只需要当前经纬度的话,可以屏蔽其他的数据。如果不屏蔽的话,MCU处理的时候,会不停的收到不需要的指令,降低MCU效率。

        使用软件配置,[Config]-->[Configuration], 可以选择显示哪些项目,这里只保留GPRMC指令信息输出,然后保存。界面显示如下:

 

五、数据解析

        相对于MCU的处理速度,GPS定位数据更新几乎可以认为是缓慢变化的信号,每秒都会输出推荐位置信息,但是即使丢掉几个也不会影响定位准确性。因此可以使用中断循环buffer来接收GPS输出的串口数据,然后在需要的地方读取buffer,对数据实现一次检索,找到一个有用的GPS定位数据。

/*******************************************************************************
1.中断负责把GPS串口数据保存到GPS_Uart_Rcv_Buf,在合适的地方调用此函数开始解析。
2.调用本函数会自动关闭接收,然后处理,期间的GPS数据可以忽略。
3.在合适的地方打开接收。
*******************************************************************************/
uint8_t get_gps_useful_data(uint8_t *weidu, uint8_t *jingdu)
{uint8_t *p_frame_start = NULL;uint8_t *p_useful_frame_start = NULL;uint8_t *p_useful_frame_end = NULL;int16_t frame_len = ;int16_t rcv_buf_data_len = ;int16_t index = ;int16_t frame_start_point = ;int16_t remain_data_len = ;uint8_t rtn =;gps_rcv_enable(FALSE);rcv_buf_data_len = GPS_Rev_Buf_Size;p_frame_start = &GPS_Uart_Rcv_Buf[];/* data example:$GPVTG,,,,,,,,,N*30$GPRMC,132234.00,V,,,,,,,120116,,,N*7D$GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79*/for(index = ; index < rcv_buf_data_len; ){p_frame_start=strstr(GPS_Uart_Rcv_Buf + index, "$GPRMC,"); //1. find start, "$GPRMC,"//$GPRMC,132234.00,V,,,,,,,120116,,,N*7D $GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79if(p_frame_start){index = p_frame_start-GPS_Uart_Rcv_Buf;if(index>){memset(GPS_Uart_Rcv_Buf,  , index);}index = index + ;p_useful_frame_start = strstr(GPS_Uart_Rcv_Buf + index, ",A,");//2 find useful data, ",A,"frame_start_point = p_useful_frame_start - p_frame_start;if((frame_start_point > )||(frame_start_point <= ))//not find useful data{continue;}frame_start_point = p_useful_frame_start-GPS_Uart_Rcv_Buf;p_useful_frame_end = strstr(GPS_Uart_Rcv_Buf + frame_start_point, ",A*");//3 find useful data end, ",A*"frame_len = p_useful_frame_end - p_frame_start + ;if((frame_len > GPS_Frame_Buf_Size)||(frame_len <= )) // not found frame end{continue;}//$GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79frame_start_point = p_frame_start - GPS_Uart_Rcv_Buf + ;memset(GPS_Frame_Buf, , GPS_Frame_Buf_Size);memcpy(GPS_Frame_Buf, GPS_Uart_Rcv_Buf + frame_start_point , frame_len);
//                 if(check_frame_xor(GPS_Frame_Buf) != TRUE)
//                 {
//                     continue;
//                 }//the frame is correctrtn = read_gps_data(GPS_Frame_Buf, remain_data_len, weidu, jingdu);if( == rtn){break; //found weidu,jingdu data}else{continue;}}else{break;}}g_gps_data_cnt = ;memset(GPS_Uart_Rcv_Buf, , GPS_Rev_Buf_Size);return rtn;
}

        上面处理的基本思想是:找到"$GPRMC,"帧头,然后找到代表定位信息有效的字符",A,",最后找到帧尾",A*"。

        因为实际收到的数据有不完整的,或者无效的定位信息,也有串口接收循环buffer造成的覆盖数据,因此上面还校验了数据长度,以及一个标志字符串到另一个字符串直接的长度。

        实际使用中,发现没有加上校验也可以很有效的工作,但是为了保证数据安全,最后的异或校验还有应该有的。

/*******************************************************************************
* Function Name  :
* Description    : 对GPRMC数据包进行解析,找到经纬度数据
* Input          :
* Output         :
* Return         :
*******************************************************************************/
uint8_t read_gps_data(uint8_t *gps_buf, uint8_t frame_len, uint8_t *weidu, uint8_t *jindu){uint8_t *weidu_s = NULL;uint8_t *weidu_o = NULL;uint8_t *jingdu_o = NULL;uint8_t rtn =;//GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79weidu_s  = strstr(GPS_Frame_Buf, ",A,");weidu_o  = strstr(GPS_Frame_Buf, ",N,");jingdu_o = strstr(GPS_Frame_Buf, ",E,");if((weidu_s == NULL) || (weidu_o == NULL) ||(jingdu_o == NULL) ){rtn = FALSE;}else{memset(weidu_buf,,sizeof(weidu_buf));memset(jindu_buf,,sizeof(jindu_buf));memcpy(weidu_buf, weidu_s+, (weidu_o-weidu_s-));memcpy(jindu_buf, weidu_o+, (jingdu_o-weidu_o-));printf("\r\n---------------------------------------");printf("\r\nGet GPS Frame:\r\n%s\r\n", GPS_Frame_Buf);printf("\r\n---------------------------------------");rtn = TRUE;}return rtn;
}

 六、总结

        本文总结了GPS模块的基本使用方法,可以得到经度和纬度信息。对于此类的模块产品,主要工作有两大部分:

1:模块的熟悉,包括配置和指令的使用,一般可以一边读文档一边跑下demo体验效果;

2:字符串的解析。

        同样的经验可以应用于很多串口模块。

        例如GPRS模块,蓝牙模块,zigbee模块,TCP模块,CAN模块,485模块。

        这几种产品我都使用过,其基本思路是一样的,调试时候可以先用串口助手模拟MCU来发数据,其实大部分模块都有自己的PC端工具,可以很快的看到效果。

        使用模块可以极大地提升项目效率,但是灵活性和成本上会有所牺牲。另外,由于模块的封闭性,一般都要写很多的异常保护处理来保证产品的正常工作。

U-BLOX GPS 模块及GPRMC指令解析 (bbsmax.com)


http://chatgpt.dhexx.cn/article/7l7jj0ma.shtml

相关文章

ROS节点解析GPS数据:GPRMC/GPFDP/HEADINGA

数据解析&#xff0c;肯定是要知道数据格式的&#xff1a; 数据格式参考&#xff1a;&#xff08;前人已经总结的比较齐全了&#xff09; https://blog.csdn.net/u010384390/article/details/78432016?ops_request_misc%257B%2522request%255Fid%2522%253A%2522163031225416…

python各种模块,迭代器,生成器

从逻辑上组织python代码&#xff08;变量&#xff0c;函数&#xff0c;类&#xff0c;逻辑&#xff1a;实现一个功能&#xff09; 本质就是.py结尾的python文件(文件名&#xff1a;test.py,对应的模块名就是test) 包&#xff1a;用来从逻辑上组织模块的,本质就是一个目录&#…

VFS - 虚拟文件系统的加载和导出

VFS - 代码生成器预览功能实现VFS - 虚拟文件系统基本操作方法的封装VFS - 虚拟文件系统的加载和导出 这是 VFS 的最后一篇&#xff0c;前面两篇中的基本方法已经实现了一个简单的虚拟文件系统&#xff0c;可以创建目录和文件&#xff0c;可以读写文件的内容。在这最后一篇中&a…

如何优雅的使用javascript递归画一棵结构树

递归和尾递归 简单的说&#xff0c;递归就是函数自己调用自己&#xff0c;它作为一种算法在程序设计语言中广泛应用。其核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。一般来说&#xff0c;递归需要有边界条件、递归前进阶段和递归返回阶段…

python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图

python数据结构和算法 参考 本文github 计算机科学是解决问题的研究。计算机科学使用抽象作为表示过程和数据的工具。抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性。Python是一种强大但易于使用的面向对象语言。列表、元组和字符串都是用Python有序集合…

黑马毕向东Java课程笔记(day20-1——20-17)IO流:File类及相关方法、递归、递归的相关练习、Properties、PrintWriter类与PrintStream类、合并流与切割流

1、File类概述   File是文件和目录路径名的抽象表示形式。 用来将文件或者文件夹封装成对象&#xff0c;方便对文件与文件夹的属性信息进行操作。   前面说到的“流”&#xff0c;它只能操作数据&#xff0c;想要操作由数据封装成的文件的信息&#xff0c;必须使用File对象…

算法: 如何优雅的使用javascript递归画一棵结构树

递归和尾递归 简单的说&#xff0c;递归就是函数自己调用自己&#xff0c;它做为一种算法在程序设计语言中广泛应用。其核心思想是把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。一般来说&#xff0c;递归需要有边界条件、递归前进阶段和递归返回阶段…

day04函数名 闭包 迭代器 生成器(各种推导式和生成器表达式) 内置函数 装饰器 递归...

一.今日内容概 1. 函数本质就是一个内存地址. 用起来和变量一模一样 2. 闭包 内层函数对外层变量的使用 1. 保护变量 2. 让一个变量常驻内存 3. 迭代器 可迭代对象: __iter__ 迭代器: __iter__ __next__ from collecti…

linux 迭代列出文件,讲解在Linux命令行下使用ls命令列出文件的技巧

Linux ls 命令可以说是在 Linux 中常见到的命令之一&#xff0c;因为使用它可以掌握系统中文件所在目录中的内容&#xff0c;从而能够查看与修改文件&#xff0c;如果你正在使用 Linux ls 命令&#xff0c;不妨看一下以下技巧&#xff0c;它能帮助你更快速的完成任务。 ls 命令…

学习递归的另一种方法

每个学期&#xff0c;我都会通过一项调查&#xff0c;以获取有关我的教学的一些反馈。 上学期终于有人给我写一篇新文章的想法。 特别是&#xff0c;他们想了解有关递归的更多信息&#xff0c;所以我认为我会综合一些技巧。 递归概述 对于那些可能是第一次学习递归的人&#x…

用非递归方法实现递归算法时_学习递归的另一种方法

用非递归方法实现递归算法时 每个学期&#xff0c;我都会通过一项调查&#xff0c;以获取有关我的教学的一些反馈。 上学期终于有人给我写一篇新文章的想法。 特别是&#xff0c;他们想了解有关递归的更多信息&#xff0c;所以我认为我会综合一些技巧。 递归概述 对于那些可能…

bat 文件夹移动

echo off echo hello world ::得到当天 set pathLog%date:~0,4%%date:~5,2%%date:~8,2% :: eg:能得到 秒:set pathLog%date:~0,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2% :: set pathLog%pathLog: 0% ::创建文件夹 md "d:\log\log%pathLog% ec…

【Python零基础入门篇 · 19】:os模块、可迭代对象和迭代器对象

目录 一、os模块 1、os模块中的命令&#xff1a; 2、常用命令的代码演示 os.getcwd() os.chdir(path) os.listdir(path) os.mkdir(path) os.makedirs(path) os.rename(旧名,新名) 3、举例&#xff1a;查找文件夹下所有满足要求的文件 二、可迭代对象和迭代器对象 1、…

day18:File(构造方法、创建、删除文件或者文件夹、 判断性、重命名与剪切、得到性、过滤性)、递归(遍历文件夹文件)

一 回顾 1.HashMap集合 特点: A.数据结构也是Hash表结构 B.多线程中是不安全 C.默认的数组的初始化容量是16 2.HashMap与HashSet的比较 相同点:都是hash表结构来存储 不同点: A.HashSet的底层就是使用HashMap来实现 B.HashSet的数据结构针对与是元素 HashMap的…

Python 文件和文件夹 01

Python文件和文件夹 01 ① 修改当前目录&#xff0c;首次利用 pandas 读取 excel 表 os.chdir import os import pandas as pd os.chdir(C:/aa/bb/cc) os.chdir(rC:\aa\bb\cc)数据 pd.read_excel("temp.xlsx") 等同于当前路径下的 temp.xlsx 文件。print(数据)② 字…

删除win10无限嵌套文件夹

解决由于失误操作导致WIN10系统产生无限循环的文件夹问题 昨天本想自己写一个拷贝文件的小程序&#xff0c;结果出现了点小问题&#xff0c;整出了一个无限循环的文件夹&#xff0c;直接删除出出现错误代码提示&#xff0c;显示无法删除&#xff0c;然后我就去网上找解决方案&…

计算机专硕一般研二在干嘛,专硕一般研二在干嘛,专硕两年怎么安排

一般学习两年。 硕士学位的学制取决于您申请的学校和专业。 不同的学校可能不同&#xff0c;同一所学校的硕士学位也可能不同。 许多学校还设有两年半的学制&#xff0c;甚至三年制的学制。本文一起来看一下吧~ 一.什么人适合读专硕 1、英语相对一般的人 学硕主要考英语一试卷&…

研二导师画大饼,不给时间实习,咋办

一个小学弟最近咨询我 我是本硕都在一所双非一本就读&#xff0c;软件工程&#xff0c;目前研二&#xff0c;23 届。我想在暑期进行一下今年的实习&#xff0c;想着可能对后面秋招和来年春招有帮助&#xff0c;但是实验室管的严导师不放时间(其实我当时是为了毕业条件和平时研…

2022年终总结与2023新年展望

前言 时间过得太快了&#xff0c;虽然写博客已经很多年了&#xff0c;但是年终总结一直由于种种原因没有写过&#xff0c;2022年确实是魔幻的一年&#xff0c;不知不觉自己也已经研二了&#xff0c;因为疫情的原因突然放开&#xff0c;提前放假回家&#xff0c;借此机会写一下…

研二(上学期)计划安排

今天是9.17号了&#xff0c;时间过得很快&#xff0c;学习的脚步永远停不下来。 时间的安排就不说了&#xff0c;真的是计划赶不上变化&#xff0c;一句话&#xff0c;除了外聘上课和研助&#xff0c;其他的时间必须到达实验室&#xff0c;&#xff08;一个星期一次总结&#…