程序的基本原理:GPS设备的NMEA语句是逐条发送的,每条语句都是以0x0D和0x0A来结束的。程序开放256字节的接收缓冲区,当接收到0x0D字节时开始进行NMEA语句的校验和验证与数据解析。首先查找该语句的每个参数之间的逗号分隔符,将分隔符的位置作记录下来并替换为0x00,再依据不同的语句定义将不同参数的数据指针提取出来。因为事先已经将分隔符替换为0x00,所以数据指针结束时不会溢出到其他参数中去。最后通过字符串的复制或字符串的转换,将各语句的参数提取出来并放置在相应的数据结构单元中去,最终完成解析运算。

实验证明,用STM32在8M的速率下,GPS以4800的波特率,处理完一条语句后,后面的NMEA输出的0x0D还没有接收完成。程序的难点没什么,只是多用一些C语言的系统函数来完成复制和字符串转换,处理字符串时的尽量越少越短越好,可以说基本上是实时处理的。

  1. extern struct _GPS_Real_buf
  2. {
  3. char data[256];                             //定义GPS输入缓冲区
  4. volatile unsigned short rx_pc;    //接收指针
  5. } GPS_Real_buf; //GPS接收数据缓冲区
  6. extern struct _GPS_Information
  7. {
  8. unsigned char Real_Locate;              //实时定位有效位
  9. unsigned char Located;                      //定位有效位
  10. unsigned char Locate_Mode;           //定位模式,2D或3D
  11. char UTC_Time[7];                                //时间
  12. char UTC_Date[7];                               //日期
  13. char Latitude[10];                               //纬度
  14. char NS_Indicator;                               //N=北半球,S=南半球
  15. char Longitude[11];                          //经度
  16. char EW_Indicator;                              //E=东经,W=西经
  17. double Speed;                                       //地面速率
  18. double Course;                                      //地面航向
  19. double PDOP;                                         //位置精度
  20. double HDOP;                                         //水平精度
  21. double VDOP;                                         //垂直精度
  22. double MSL_Altitude;                         //MSL海拔高度
  23. unsigned char Use_EPH_Sum;       //使用的卫星数量
  24. unsigned char User_EPH[12];         //当前搜索到的卫星编号
  25. unsigned short EPH_State[12][4]; //当前使用的12颗卫星的编号、仰角、方位角、信噪比
  26. } GPS_Information; //GPS信息
  27. /********************************************************************************************************
  28. **函数信息 :void USART2_IRQHandler(void)
  29. **功能描述 :UART2中断服务函数
  30. **输入参数 :无
  31. **输出参数 :无
  32. ********************************************************************************************************/
  33. void USART2_IRQHandler( void ) //串口2中断服务程序
  34. {
  35. unsigned char Recv;
  36. if ( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET ) //接收中断
  37. {
  38. Recv = USART_ReceiveData( USART2 );          //接收数据
  39. if ( Recv == '$' )
  40. {
  41. GPS_Real_buf.rx_pc = 0;
  42. }
  43. else
  44. {
  45. if ( GPS_Real_buf.rx_pc < sizeof( GPS_Real_buf.data ) - 1 )
  46. {
  47. GPS_Real_buf.rx_pc++;
  48. }
  49. }
  50. GPS_Real_buf.data[GPS_Real_buf.rx_pc] = Recv;
  51. if ( Recv == '\r' )    //当接收数据为0x0D时开始处理GPS数据
  52. {
  53. if ( Real_Process_Enabled == Valid )
  54. {
  55. if ( Calc_GPS_Sum( GPS_Real_buf.data ) == Valid )
  56. {
  57. Creat_DH_Index( GPS_Real_buf.data );
  58. Real_GPS_Command_Process();
  59. }
  60. }
  61. }
  62. }
  63. if ( USART_GetFlagStatus( USART2, USART_FLAG_ORE ) == SET ) //溢出中断
  64. {
  65. USART_ClearFlag( USART2, USART_FLAG_ORE );   //清溢出位
  66. USART_ReceiveData( USART2 );                                //读DR
  67. }
  68. }
  69. /********************************************************************************************************
  70. **函数信息 :void Creat_DH_Index( char* buffer )
  71. **功能描述 :寻找所有逗号的位置,创建索引
  72. **输入参数 :接收GPS数据的缓冲区
  73. **输出参数 :创建全局变量数组中的逗号索引,原GPS数据中的逗号将会被0x00替代
  74. ********************************************************************************************************/
  75. unsigned char DH_id_sep[32];//全局变量数组,最多处理32个逗号索引
  76. void Creat_DH_Index( char* buffer )
  77. {
  78. unsigned short i, len;
  79. unsigned char idj;
  80. memset( DH_id_sep, 0, sizeof( DH_id_sep ) );
  81. len = strlen( buffer );
  82. for ( i = 0, idj = 0; i < len; i++ )
  83. {
  84. if ( buffer[i] == ',' )
  85. {
  86. DH_id_sep[idj] = i;
  87. idj++;
  88. buffer[i] = 0x00;
  89. }
  90. }
  91. }
  92. /********************************************************************************************************
  93. **函数信息 :char* Real_Process_DH( char* buffer, unsigned char num )
  94. **功能描述 :查找GPS数据第N个参数的偏移
  95. **输入参数 :创建索引后的接收GPS数据缓冲区
  96. **输出参数 :返回第N个","之后的信息,需要*buffer有效并创建索引后才可以执行
  97. ********************************************************************************************************/
  98. char* Real_Process_DH( char* buffer, unsigned char num )
  99. {
  100. if ( num < 1 )
  101. return  &buffer[0];
  102. return  &buffer[ DH_id_sep[num - 1] + 1];
  103. }
  104. /********************************************************************************************************
  105. **函数信息 :void Real_GPS_Command_Process( void )
  106. **功能描述 :处理做好参数索引的数据并填入GPS数据结构中
  107. **输入参数 :
  108. **输出参数 :
  109. ********************************************************************************************************/
  110. void Real_GPS_Command_Process( void )
  111. {
  112. char* temp;
  113. unsigned char i, j, zhen;
  114. if ( strstr( GPS_Real_buf.data, "GPGGA" ) )//$GPGGA,112118.000,3743.5044,N,11540.5393,E,1,06,1.6,15.3,M,-9.1,M,,0000*7E
  115. {
  116. GPS_Information.Use_EPH_Sum = atof( Real_Process_DH( GPS_Real_buf.data, 7 ) ); //第7个参数为卫星使用数量
  117. GPS_Information.MSL_Altitude = atof( Real_Process_DH( GPS_Real_buf.data, 9 ) ); //第9个参数为海拔高度
  118. return;
  119. }
  120. if ( strstr( GPS_Real_buf.data, "GPGSA" ) )  //$GPGSA,A,3,28,17,11,09,08,07,,,,,,,3.4,1.6,3.0*3B
  121. {
  122. temp = Real_Process_DH( GPS_Real_buf.data, 2 ); //第2个参数为定位模式
  123. if ( ( *temp == '2' ) || ( *temp == '3' ) )
  124. GPS_Information.Locate_Mode = *temp;
  125. else
  126. GPS_Information.Locate_Mode = Invalid;
  127. for ( i = 0; i < 12; i++ ) //总共最多为12颗星
  128. {
  129. GPS_Information.User_EPH[i] = atof( Real_Process_DH( GPS_Real_buf.data, i + 3 ) ); //从第3个参数开始为所使用的卫星编号
  130. }
  131. GPS_Information.PDOP = atof( Real_Process_DH( GPS_Real_buf.data, 15 ) ); //第15个参数为位置精度
  132. GPS_Information.HDOP = atof( Real_Process_DH( GPS_Real_buf.data, 16 ) ); //第16个参数为水平精度
  133. GPS_Information.VDOP = atof( Real_Process_DH( GPS_Real_buf.data, 17 ) ); //第17个参数为垂直精度
  134. return;
  135. }
  136. if ( strstr( GPS_Real_buf.data, "GPRMC" ) )//$GPRMC,112118.000,A,3743.5044,N,11540.5393,E,0.25,198.81,130613,,,A*67
  137. {
  138. temp = Real_Process_DH( GPS_Real_buf.data, 1 ); //第1个参数为时间
  139. if ( *temp != 0 )
  140. memcpy( GPS_Information.UTC_Time, temp, 6 );
  141. if ( *( Real_Process_DH( GPS_Real_buf.data, 2 ) ) == 'A' ) //第2个参数
  142. {
  143. GPS_Information.Real_Locate = Valid; //实时数据有效
  144. GPS_Information.Located = Valid;
  145. }
  146. else
  147. {
  148. GPS_Information.Real_Locate = Invalid;  //实时数据无效
  149. }
  150. temp = Real_Process_DH( GPS_Real_buf.data, 3 ); //第3个参数为纬度
  151. if ( ( *temp >= 0x31 ) && ( *temp <= 0x39 ) )
  152. {
  153. memcpy( GPS_Information.Latitude, temp, 9 );
  154. GPS_Information.Latitude[9] = 0;
  155. }
  156. else
  157. {
  158. GPS_Information.Latitude[0] = '0';
  159. GPS_Information.Latitude[1] = 0;
  160. }
  161. GPS_Information.NS_Indicator = *( Real_Process_DH( GPS_Real_buf.data, 4 ) ); //第4个参数为南北
  162. temp = Real_Process_DH( GPS_Real_buf.data, 5 ); //第5个参数为经度
  163. if ( ( *temp >= 0x31 ) && ( *temp <= 0x39 ) )
  164. {
  165. memcpy( GPS_Information.Longitude, temp, 10 );
  166. GPS_Information.Longitude[10] = 0;
  167. }
  168. else
  169. {
  170. GPS_Information.Longitude[0] = '0';
  171. GPS_Information.Longitude[1] = 0;
  172. }
  173. GPS_Information.EW_Indicator = *( Real_Process_DH( GPS_Real_buf.data, 6 ) ); //第6个参数为东西
  174. GPS_Information.Speed = atof( Real_Process_DH( GPS_Real_buf.data, 7 ) ); //第7个参数为速度
  175. GPS_Information.Course = atof( Real_Process_DH( GPS_Real_buf.data, 8 ) ); //第8个参数为航向
  176. temp = Real_Process_DH( GPS_Real_buf.data, 9 ); //第9个参数为日期
  177. if ( *temp != 0 )
  178. {
  179. memcpy( GPS_Information.UTC_Date, temp, 6 );
  180. }
  181. return;
  182. }
  183. if ( strstr( GPS_Real_buf.data, "GPGSV" ) )//$GPGSV,3,1,11,28,73,321,32,17,39,289,43,11,38,053,17,09,37,250,41*78
  184. {
  185. zhen = atof( Real_Process_DH( GPS_Real_buf.data, 2 ) ); //取当前帧号
  186. if ( ( zhen <= 3 ) && ( zhen != 0 ) )
  187. {
  188. for ( i = ( zhen - 1 ) * 4, j = 4; i < zhen * 4; i++ )
  189. {
  190. GPS_Information.EPH_State[i][0] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取星号
  191. GPS_Information.EPH_State[i][1] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取仰角
  192. GPS_Information.EPH_State[i][2] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取方位角
  193. GPS_Information.EPH_State[i][3] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取信噪比
  194. }
  195. }
  196. return;
  197. }
  198. }
  199. /********************************************************************************************************
  200. **函数信息 :unsigned char Calc_GPS_Sum( const char* Buffer )
  201. **功能描述 :计算GPS的校验和
  202. **输入参数 :接收完成的GPS数据
  203. **输出参数 :
  204. ********************************************************************************************************/
  205. #include <ctype.h>
  206. unsigned char gps_sum = 0;
  207. unsigned char Calc_GPS_Sum( const char* Buffer )
  208. {
  209. unsigned char i, j, k, sum;
  210. sum = 0;
  211. for ( i = 1; i < 255; i++ ) //i从1开始是闪过$开始符
  212. {
  213. if ( ( Buffer[i] != '*' ) && ( Buffer[i] != 0x00 ) ) //判断结束符
  214. {
  215. sum ^= Buffer[i];//GPS校验和算法为XOR
  216. }
  217. else
  218. {
  219. break;
  220. }
  221. }
  222. j = Buffer[i + 1];//取结束符后两位字符
  223. k = Buffer[i + 2];
  224. if ( isalpha( j ) ) //判断字符是否为英文字母,为英文字母时返回非零值,否则返回零
  225. {
  226. if ( isupper( j ) ) //判断字符为大写英文字母时,返回非零值,否则返回零
  227. {
  228. j -= 0x37;//强制转换为16进制
  229. }
  230. else
  231. {
  232. j -= 0x57;//强制转换为16进制
  233. }
  234. }
  235. else
  236. {
  237. if ( ( j >= 0x30 ) && ( j <= 0x39 ) )
  238. {
  239. j -= 0x30;//强制转换为16进制
  240. }
  241. }
  242. if ( isalpha( k ) ) //判断字符是否为英文字母,为英文字母时返回非零值,否则返回零
  243. {
  244. if ( isupper( k ) ) //判断字符为大写英文字母时,返回非零值,否则返回零
  245. {
  246. k -= 0x37;//强制转换为16进制
  247. }
  248. else
  249. {
  250. k -= 0x57;//强制转换为16进制
  251. }
  252. }
  253. else
  254. {
  255. if ( ( k >= 0x30 ) && ( k <= 0x39 ) )
  256. {
  257. k -= 0x30;//强制转换为16进制
  258. }
  259. }
  260. j = ( j << 4 ) + k; //强制合并为16进制
  261. gps_sum = j;
  262. if ( sum == j )
  263. {
  264. return Valid; //校验和正常
  265. }
  266. else
  267. {
  268. return Invalid; //校验和错误
  269. }
  270. }

GPS-NMEA解析代码相关推荐

  1. android提取串口返回nmea,实现GPS 串口 NMEA 解析的代码

    经常需求使用 GPS 串口 NMEA 解析的功能,写了一段代码来完成引功能. 分享一下,大家一起学习. 头文件:#ifndef _GPS_MONITER_HH_ #define _GPS_MONITE ...

  2. GPS NMEA数据包解析

    GPS NMEA数据包解析 NMEA-0183是美国国家海洋电子协会为海用电子设备制定的标准格式.它包含了定位时间,纬度,经度,高度,定位所用的卫星数,DOP值,差分状态和校正时段等很多信息 一 通用 ...

  3. minmea——GPS NMEA 0183 协议解析库

    今天给大家推荐一个纯C语言编写,轻量级的GPS NMEA 0183协议解析库:minmea github地址:https://github.com/kosma/minmea 一.特点 1.C99标准编 ...

  4. 远程定位gps linux,GPS(NMEA)数据解析

    一.GPS定位信息 设置好gps模式,启动gps,正常的话在gps通路有NMEA数据上报,如下: $GPGSV,3,1,11,01,62,130,42,07,61,201,43,11,72,075,2 ...

  5. GPS NMEA协议解析之通用语句

    GPS NMEA协议解析(NMEA通用语句) 文章目录 前言 一.NMEA协议简介 二.NMEA数据格式 1.GGA(全球定位系统定位数据) 2.GSA(GNSS 精度因子与有效卫星) 3.GSV(可 ...

  6. GPS项目实战系列1:GPS数据解析1

    前面写了一系列关于Linux的文章,从这一篇开始换个题目,叫做GPS项目实战系列,后面的很多篇内容都会围绕着这个项目展开.这个项目要完成的任务,可以参考之前的文章:https://topsemic.c ...

  7. 【Groovy】Groovy 脚本调用 ( Groovy 配置文件格式 | Groovy 配置文件读取 | 完整配置文件及解析代码示例 )

    文章目录 前言 一.Groovy 配置文件格式 二.Groovy 配置文件读取 二.完整配置文件及解析代码示例 前言 在 Groovy 脚本 , Groovy 类 , Java 类中 , 可以调用 G ...

  8. MATLAB接收机位置解算,GPS-receiver GPS软件接收机代码 完整的捕获 解算定位 (可 8个通道) matlab 240万源代码下载- www.pudn.com...

    文件名称: GPS-receiver下载  收藏√  [ 5  4  3  2  1 ] 开发工具: matlab 文件大小: 148 KB 上传时间: 2015-07-02 下载次数: 0 提 供 ...

  9. 技术解析+代码实战,带你入门华为云政务区块链平台

    摘要:政务区块链平台是行业区块链平台的初步实践,未来在区块链技术的发展下,还会打造面向其他领域的链管平台,构建多方协同的分布式账本,让区块链应用更便捷高效的为产业服务. 本文分享自华为云社区<技 ...

  10. MediaInfo源代码分析 5:JPEG解析代码分析

    ===================================================== MediaInfo源代码分析系列文章列表: MediaInfo源代码分析 1:整体结构 Me ...

最新文章

  1. 大数据精准投放平台_大数据库(可视化精准平台,能够使您的广告更加精准有效)...
  2. C++虚函数Demo - Win32 版本
  3. IDA Pro7.0使用技巧总结使用
  4. 信息学奥赛一本通(1224:最大子矩阵)
  5. [linux]关于deepin截图软件在KDE桌面下无法使用粘贴的解决方法
  6. 2750个通用停用词表整理,免费下载
  7. disable jboss JMXInvokerServlet .
  8. 一个自己主动依据xcode中的objective-c代码生成类关系图的神器
  9. PLSQL 免费下载安装
  10. html调用js里面的函数,html如何调用js函数
  11. app上架小米应用商店流程
  12. 基于TCP的STM32 IAP bootloader初步设计
  13. 69张图回顾2021和看透2022
  14. UE4 关闭屏幕显示信息响应
  15. linux 删除swp文件,linux E325: 注意 发现交换文件 *.swp 解决方法
  16. word文档中标题跳到表格的下方-解决方法
  17. android 移除子view,android-从父视图中移除视图与隐藏视图
  18. ijkplayer播放器架构从原型到升级
  19. 图虫:科技赋能图片版权领域创新发展
  20. Socket error Event: 32 Error: 10053.

热门文章

  1. BiSS-C的基本组网原理介绍
  2. RxJava过滤操作符 filter
  3. DTW学习(dynamic time warping)——思想、代码实现
  4. tshark常用命令
  5. http上传文件流程 使用winlnet
  6. pytorch加载自己的数据集,数据集载入-视频合集
  7. 数据分析方法:非正态数据转化成正态数据
  8. garch dcc用matlab,用matlab工具箱怎么对garch模型做...
  9. python创建目录
  10. Ajax跨域请求(一):什么是CORS