搜索
bottom↓
回复: 46

GPS语句解析代码的一些研究[原创]

  [复制链接]

出0入0汤圆

发表于 2013-4-27 18:57:46 | 显示全部楼层 |阅读模式
本帖最后由 冥冥 于 2013-4-28 13:58 编辑

来阿莫不算久,学习下载的东西不算少,是时候该做出一些贡献了。


我写过两版GSP解析代码,第一版写的时候没经验啊...是基于串口,也就是要把函数放在串口中断内,对每一个读入字符进行识别,当然用着没有任何问题,各种字段获取可以实现。但是这种方法有很多问题:


  • 效率不高,因为每次串口中断都要进行一定处理;
  • 可移植性差,因为针对每个不同芯片的串口中断都要重写输入部分;
  • 程序不够结构化,完全采用了函数式的思维,没有面向对象,不方便以后修改。


因此项目结束后,痛定思痛决定写个通用GPS命令识别的,鉴于行业限制我只写了RMC和GGA的但是其他语句可以很容易的添加进来。新的GPS语句解析代码耦合性低。大概分了几个功能:


  • 从一个字符串中截取出所需的完整的GPS语句,在此过程中是进行校验的,未截取成功会返回0;
  • 对完整的GPS字符串进行自定义的掐头去尾,使用与某些场合例如:不想要$不想要后面的校验;
  • 从完整的GPS字符串中提取所需的参数。

以上是对外提供的接口函数。我定义了一些结构体用来存放类似于时间、日期、经纬度这样的信息。所谓这段代码的用户只需要定义一个buffer,然后把串口的数据依次存在里面。定义一个用来接收完整语句的String,然后定义一个所需数据的变量,通过执行函数1和3就可以获取所需的数据了,这样就将代码解析跟硬件分离开来了。淡然代码还有很多可以改进的地方,例如可以用scanf获取数据,我是笨人用的是数据格式转化的方法。废话不说了,上代码。


首次发帖希望大家不要吐槽,我想代码的自注释性还算可以,如果对代码感兴趣,你阅读的时候一定能看懂,如果只是想用就不要有太多疑问,本人很懒。。。。


论坛插入代码格式搞不定,直接上附件第一次发帖不知道有没有裤子


GPS解析代码

决定上张图,这是例程的运行结果,实际上程序可以实现循环Buffer的扫描,不知有人看出来没


看大家反应不激烈 下血本 程序设计文档放出 如果反响良好再开一贴送上一个自己写的实用小工具



GPS
功能:GPS部分负责GPS数据分析,处理,应具有验证是否为指定语句类型的功能,截取指定长度指令的功能,返回某数据的功能。




接口函数
1.unsigned char GPSCmdSnapshot(
const char* const InputBuffer,
const unsigned char BufferMaxLen,
const unsigned char CmdType,
char* const ReturnStr
)
函数:判断输入字符串是否含有完整的指定语句后将语句截出到GPS全局变量中。
输入:待处理字符串首地址,用于将字符串作为参数使用。字符串最大长度,用于防止下标越界。命令类型,用于判别待解析的命令类型。GPS命令字符串首地址,用于存储完整语句。
输出:是非标志。




2.unsigned char GPSCmdCut(
                                                const char* const CmdInput,
const unsigned char Start,
const unsigned char Discard,
char* const ReturnStr
)
函数:从完整语句中截取一部分字符串。
输入:GPS字符串首地址,用于将字符串作为参数使用。截取起始位数,用于表明从第几位截取。去掉的末尾数,用于表明有最后多少位不用返回。接收返回的字符串首地址,用于存储截取的字符串。
输出:是非标志。




3.unsigned char GPSCapParametersStr (
const char* const CmdInput,
const unsigned char ParametersSite,
char* const ReturnStr
)
函数:当前语句的某参数以字符串形式导出。
输入:GPS字符串首地址,用于将字符串作为参数使用。截取参数序号,用于表明截取第几个参数,用逗号标定。接收返回的字符串首地址,用于存储截取的字符串。
输出:是非标志。




4.unsigned char GPSCapParameters (
const char* const CmdInput,
const unsigned char CmdType,
const unsigned char ParametersSite,
void* const ReturnData
)
函数:解析字符串形式数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析类型,待解析的语句类型。解析类型,待解析的参数类型。解析完成的数据的指针,用于存放解析完成的数据。
输出:是非标志。




非接口函数
1. unsigned char GPSTimeProcess (
const char* const CmdInput,
TimePoint const ReturnData
)
函数:解析时间数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,需要返回多字节多类型数据数据。
输出:是非标志。




2. unsigned char GPSCoordinateProcess (
const char* const CmdInput,
CoordinatePoint const ReturnData
)
函数:解析经纬度数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,需要可返回多字节多类型数据。
输出:是非标志。




3. unsigned char GPSCharProcess (
const char* const CmdInput,
char* const ReturnData
)
函数:解析字符型数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,返回单字节数据。
输出:是非标志。




4. unsigned char GPSUncharProcess (
const char* const CmdInput,
unsigned char* const ReturnData
)
函数:解析整型数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,返回单字节数据。
输出:是非标志。




5.unsigned char GPSFloatProcess(
const char* const CmdInput,
float* const ReturnData
)
函数:解析浮点数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,返回浮点数据。
输出:是非标志。




6. unsigned char GPSDateProcess (
const char* const CmdInput,
DatePoint const ReturnData
)
函数:解析日期数据。
输入:GPS参数字符串首地址,用于将字符串作为参数使用。解析完成数据,用指针返回参数,需要返回多字节数据。
输出:是非标志。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

 楼主| 发表于 2013-5-3 20:44:16 | 显示全部楼层
monkey_hzh 发表于 2013-4-30 19:27
求LZ的实用小工具哦~~

北斗和GPS性能评价的实用工具[原创]
http://www.amobbs.com/thread-5532240-1-1.html
如约而至

出0入0汤圆

发表于 2013-4-27 19:51:20 | 显示全部楼层
支持一个。

出0入0汤圆

发表于 2013-4-27 20:03:22 | 显示全部楼层
支持一下哦

出0入0汤圆

发表于 2013-4-27 20:16:18 | 显示全部楼层
支持一下

出0入0汤圆

发表于 2013-4-27 22:35:28 | 显示全部楼层
上次查过一次资料,好像用二维数组方式解析是比较简单快捷的。就是需要多点RAM。

出0入0汤圆

发表于 2013-4-27 22:46:16 | 显示全部楼层
支持一下哦

出0入0汤圆

发表于 2013-4-27 23:22:55 来自手机 | 显示全部楼层
支持一个!!!!!

出0入0汤圆

发表于 2013-4-27 23:35:23 | 显示全部楼层
单片机没有DMA,一个个字符的解也没有什么区别了

出0入0汤圆

 楼主| 发表于 2013-4-28 11:07:46 | 显示全部楼层
Vincent2012 发表于 2013-4-27 22:35
上次查过一次资料,好像用二维数组方式解析是比较简单快捷的。就是需要多点RAM。 ...

使用二维数组是否也需要一行一行读呢?我的代码是针对每一行的,在串口收到换行符后调用函数可提高串口buffer的利用率

出0入0汤圆

 楼主| 发表于 2013-4-28 11:10:42 | 显示全部楼层
oufuqiang 发表于 2013-4-27 23:35
单片机没有DMA,一个个字符的解也没有什么区别了

我原文说的很清楚哦 一个一个字字符的解 会占用串口中断大量时间 可能降低串口可靠性 另外主要还是 程序可移植性 可维护性的问题

出0入0汤圆

发表于 2013-4-28 16:27:08 | 显示全部楼层
mark 一下

出0入0汤圆

发表于 2013-4-28 22:25:09 | 显示全部楼层
支持一下。

出0入0汤圆

发表于 2013-4-29 00:34:41 | 显示全部楼层
冥冥 发表于 2013-4-28 11:07
使用二维数组是否也需要一行一行读呢?我的代码是针对每一行的,在串口收到换行符后调用函数可提高串口bu ...

就是每收到一个字符就保存到二维数组,收到逗号就下一行。收到0x0d ,0x0a就触发解析。

出0入0汤圆

发表于 2013-4-29 02:39:32 | 显示全部楼层
支持一下,自己也写过简单的解析函数,能提取数据

出0入0汤圆

 楼主| 发表于 2013-4-29 20:14:59 | 显示全部楼层
Vincent2012 发表于 2013-4-29 00:34
就是每收到一个字符就保存到二维数组,收到逗号就下一行。收到0x0d ,0x0a就触发解析。
...

大侠说的这个方法优点是方便指定字符串定位,缺点除了您说的浪费了存储空间,还不方便对数据进行校验,并且这样做比较难以将数据获取和数据处理分开降低了模块的可移植性

出0入0汤圆

 楼主| 发表于 2013-4-29 20:20:16 | 显示全部楼层
djj334396514 发表于 2013-4-29 00:50
必须支持,之前自己写过一个,到后来基本看不懂了

我写的第一版GPS代码自己也阅读无力,后来只取了几段能用放在了第二版解析里面

出0入0汤圆

发表于 2013-4-30 19:27:06 | 显示全部楼层
支持一下,确实结构清晰,非常容易读懂与应用,感谢LZ

出0入0汤圆

发表于 2013-4-30 19:27:37 | 显示全部楼层
求LZ的实用小工具哦~~

出0入0汤圆

发表于 2013-5-13 12:36:08 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-5-13 14:38:32 | 显示全部楼层
支持一下

出0入0汤圆

发表于 2013-6-7 21:07:13 | 显示全部楼层
支持一下啦

出0入0汤圆

发表于 2013-6-25 10:50:00 | 显示全部楼层
我收藏啦!

出0入17汤圆

发表于 2013-7-2 09:33:45 | 显示全部楼层
GPS语句解析代码的一些研究,mark!

出0入0汤圆

发表于 2013-7-2 09:37:13 | 显示全部楼层
第一版写的时候没经验啊...是基于串口,
-----------------------

第一版帖子在哪??

出0入0汤圆

发表于 2013-7-14 07:30:08 | 显示全部楼层
學習

出0入0汤圆

 楼主| 发表于 2013-7-17 14:47:26 | 显示全部楼层
wkman 发表于 2013-7-2 09:37
第一版写的时候没经验啊...是基于串口,
-----------------------

没有帖子 写的太烂 所以没好意思贴

出0入0汤圆

发表于 2013-7-17 15:38:23 来自手机 | 显示全部楼层
比较好的做法是中断或者dma中发送数据到环型或者乒乓缓冲,主程序内等系统空闲时调用解析函数来解析。

出0入0汤圆

发表于 2013-7-17 18:26:40 | 显示全部楼层
顶起。谢谢分享

出0入0汤圆

发表于 2013-9-30 05:12:38 | 显示全部楼层
多谢楼主呀

出0入0汤圆

发表于 2013-9-30 11:10:22 | 显示全部楼层
谢谢楼主啦

出0入10汤圆

发表于 2013-11-1 10:44:17 | 显示全部楼层
没看到楼主串口接收部分的程序啊,问下LZ串口接收用环形队列了吗?

出0入0汤圆

 楼主| 发表于 2013-11-21 12:54:23 | 显示全部楼层
lklhzu 发表于 2013-11-1 10:44
没看到楼主串口接收部分的程序啊,问下LZ串口接收用环形队列了吗?

是使用的环形队列  串口很简单 在加上不同单片机串口中断不同 就没加 函数本身是不区分是否环形队列的 它会对字符串进行全扫描

出0入0汤圆

发表于 2013-11-21 13:31:19 | 显示全部楼层
楼主辛苦~

出0入0汤圆

发表于 2013-11-25 07:51:57 | 显示全部楼层
本帖最后由 sch3462 于 2013-11-25 08:04 编辑

实在是好!功夫了得,抄了你头像表示膜拜。附带学会了如何用VC++来验证函数功能。


例:
  1. //****************************************************************************************************
  2. //函数功能:验证星期计算函数 WeekCalculate.h是否好用
  3. //输入:依提示输入,
  4. //          
  5. //输出:算出给定年月日是星期几
  6. //说明: (amoBBS 阿莫电子论坛)
  7.            
  8. //作者:
  9. //****************************************************************************************************

  10. #include "WeekCalculate.h"
  11. #include <stdio.h>

  12. int main(void)
  13. {       
  14.         unsigned int  year=2013,mooth=11,day=26,week;
  15.        
  16.        
  17.         printf("Input year mooth day:%d %d %d\n",year,mooth,day);
  18.         week= GetWeek(year,mooth,day);
  19.         printf("WeekCalculate result is  :%d\n",week);
  20.         //getch();
  21.         return 0;
  22. }
复制代码


  1. #ifndef                 _WeekCalculate_H
  2. #define                  _WeekCalculate_H

  3. /*----------------------------------------------------------------------------------------
  4.   0000年~9999年星期算法(菜农自创)
  5. -----------------------------------------------------------------------------------------*/
  6. unsigned int GetWeek(unsigned int y, unsigned int m, unsigned int d)
  7. {
  8.         unsigned int w, c;
  9.         if (m <= 2)
  10.         {
  11.                 m |= 4;//1月2月同5月六月表
  12.                 y--;
  13.         }
  14.         c = y / 100;
  15.         c &= 0x03;//百年%4
  16.         y %= 100;
  17.         w = ((c | (c << 2)) + (y + (y >> 2)) + (13 * m + 8)/ 5 + d) % 7;//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7
  18.         return w;//返回星期
  19. }

  20. /*----------------------------------------------------------------------------------------
  21.   附赠0000年~9999年月最大天数算法(菜农自创)
  22. -----------------------------------------------------------------------------------------
  23. int GetDom(unsigned int y, unsigned int m)
  24. {
  25.         int dn;
  26.         dn = GetDow(y, m + 1, 1) - GetDow(y, m, 1);//m+1=13表示明年的1月
  27.         if (dn < 0) dn += 7;
  28.         return dn + 28;//返回当月的最大天数
  29. }
  30. ****************/
  31. #endif
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-11-27 00:13:15 | 显示全部楼层
本帖最后由 sch3462 于 2013-11-27 00:17 编辑

请看这是什么问题?在$之前任意加字符都可以。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2013-12-17 15:49:42 | 显示全部楼层
支持一下!

出0入0汤圆

发表于 2014-1-17 09:57:14 | 显示全部楼层
mark!支持

出0入0汤圆

发表于 2014-1-17 09:59:57 | 显示全部楼层
这东西有点高深了!

出0入0汤圆

 楼主| 发表于 2014-7-31 09:43:25 | 显示全部楼层
sch3462 发表于 2013-11-27 00:13
请看这是什么问题?在$之前任意加字符都可以。

GPS语句是有校验和的,就是*后面的内容,当语句内容改变的时候,需要重新计算校验和。所以你修改完后需要将新计算的校验和放到*后面,然后就能正常解析了。

出5入4汤圆

发表于 2014-9-13 23:17:25 | 显示全部楼层
mark,可以参考下

出0入0汤圆

发表于 2015-10-22 12:33:43 | 显示全部楼层
学习,谢谢!!!

出0入0汤圆

发表于 2015-11-19 14:19:25 | 显示全部楼层
学习了,

出85入85汤圆

发表于 2016-6-3 18:25:06 | 显示全部楼层
必须mark,太赞了

出0入0汤圆

发表于 2016-9-19 21:52:05 | 显示全部楼层
很不错的分享,谢谢楼主,mark!

出0入0汤圆

发表于 2016-9-19 22:18:17 | 显示全部楼层
谁能干预蓝牙GPS的信号修改坐标值?玩游戏有用

出0入0汤圆

发表于 2017-9-2 09:49:48 | 显示全部楼层

必须支持
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-3-29 00:58

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表