搜索
bottom↓
回复: 42

GPS nmealib学习笔记

  [复制链接]

出0入0汤圆

发表于 2013-10-17 16:58:58 | 显示全部楼层 |阅读模式
0.nmealib简介
    nmealib是一个基于C语言的用于nmea协议的开源库。虽然nmea体积小巧,但是却具备了不少功能。
    分析NMEA语句并把结果保存在合适的C语言结构体中。
    除了解析NMEA语句之外,还可以产生NMEA语句。
    支持多种NMEA语句,包括GPGGA, GPGSA, GPGSV, GPRMC, GPVTG。
    解析算法层次严谨。
    附加地理学相关功能,可支持导航等数据工作。
    更多介绍请参考以下链接
    http://nmea.sourceforge.net/#downloads
1.目录介绍
    nmealib的目录还是非常清晰的,下面简单介绍一下。
    include\nmealib文件夹中存在nmealib相关的头文件
    src文件夹存放nmealib相关源文件,该文件夹中的内容和include\nmealib文件夹相对应
    samples文件夹存放若干例子,一些简单易懂的例子。
   
2.示例代码
  1. #include <nmea/nmea.h>
  2. #include <string.h>
  3. #include <stdio.h>

  4. int main()
  5. {
  6.     // 被测试的GPS模块输出数据,仅有GPRMC格式
  7.     char gps_str[] = "$GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n";

  8.     nmeaINFO info;                  // nmea协议解析结果结构体
  9.     nmeaPARSER parser;              // nmea协议解析载体

  10.     nmea_zero_INFO(&info);          // 填入默认的解析结果
  11.     nmea_parser_init(&parser);      // 为解析载体分配内存空间

  12.     // 调用函数完成GPS信息解析,最终结果保留于info数组中
  13.     if( (nmea_parse(&parser, gps_str, (int)strlen(gps_str), &info)) > 0 )
  14.     {
  15.         printf("longitude   %.5f\r\n",info.lon);
  16.         printf("latitude    %.5f\r\n",info.lat);
  17.         printf("speed       %.2f\r\n",info.speed);
  18.     }

  19.     nmea_parser_destroy(&parser);   // 释放解析载体的内存空间

  20.     return 0;
  21. }
复制代码

图1 程序输出结果
    利用nmealib解析GPS模块的输出结果大致可以分为三步,第一步定义和初始化GPS信息结构体和解析载体结构体,第二步调用nmea_parse函数完成解析工作,第三步释放解析载体所占用的内存空间。如果仔细查看nmea_parser_init部分的代码,便会发现函数中使用了C标准库的malloc函数,该函数会在RAM中的heap空间开辟一个空间,这就需要使用完该载体之后立刻释放,所以nmea_parser_init和nmea_parser_destroy需要成对出现。
  1. typedef struct _nmeaINFO
  2. {
  3.     int     smask;      /**< Mask specifying types of packages from which data have been obtained */

  4.     nmeaTIME utc;       /**< UTC of position */

  5.     int     sig;        /**< GPS quality indicator (0 = Invalid; 1 = Fix; 2 = Differential, 3 = Sensitive) */
  6.     int     fix;        /**< Operating mode, used for navigation (1 = Fix not available; 2 = 2D; 3 = 3D) */

  7.     double  PDOP;       /**< Position Dilution Of Precision */
  8.     double  HDOP;       /**< Horizontal Dilution Of Precision */
  9.     double  VDOP;       /**< Vertical Dilution Of Precision */

  10.     double  lat;        /**< Latitude in NDEG - +/-[degree][min].[sec/60] */
  11.     double  lon;        /**< Longitude in NDEG - +/-[degree][min].[sec/60] */
  12.     double  elv;        /**< Antenna altitude above/below mean sea level (geoid) in meters */
  13.     double  speed;      /**< Speed over the ground in kilometers/hour */
  14.     double  direction;  /**< Track angle in degrees True */
  15.     double  declination; /**< Magnetic variation degrees (Easterly var. subtracts from true course) */

  16.     nmeaSATINFO satinfo; /**< Satellites information */

  17. } nmeaINFO;
复制代码
nmeaINFO是一个很关键的结构体,该结构体中保存了nmea语句解析的结果。例如lat代表纬度,lon代表精度,speed代表速度。需要注意的是lat和lon的数值格式和百度地图的格式是有区别的,而速度的单位为KM/H,相对于“节”这个单位,公里每小时要好理解的多。

    GPS模块可以输出的内容很多,但是最基本的信息可通过GPRMC获得。GPRMC的具体格式如下内容所示:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh
<1> UTC时间,hhmmss.sss(时分秒.毫秒)格式
<2> 定位状态,A=有效定位,V=无效定位
<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)
<4> 纬度半球N(北半球)或S(南半球)
<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)
<6> 经度半球E(东经)或W(西经)
<7> 地面速率(000.0~999.9节,前面的0也将被传输)
<8> 地面航向(000.0~359.9度,以正北为参考基准,前面的0也将被传输)
<9> UTC日期,ddmmyy(日月年)格式
<10> 磁偏角(000.0~180.0度,前面的0也将被传输)
<11> 磁偏角方向,E(东)或W(西)
<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)
在不同的情况下测试GPS模块,可以获得以下三种不同形式的输出内容:
1)    $GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A\r\n
2)    $GPRMC,022649.00,V,,,,,,,020913,,,N*7F\r\n
3)    $GPRMC,,V,,,,,,,,,,N*53\r\n
第一种:GPS定位成功,输出正确的GPS位置信息和对地速度信息。
第二种:GPS定位异常,只有UTC时间信息,其中V代表定位错误。
第三种:GPS定位异常,甚至没有UTC时间信息,其中V代表定位错误。
通过测试,nmealib处理第一种情况没有任何问题,但是连续处理第二种和第三种情况会产生问题,产生问题的主要原因是动态开辟的空间没有被释放。解决该问题需要修改nmealib的源代码,这种修改是有难度的。
    如果不想修改nmealib源代码,可以在串口接收GPS输出内容时直接过滤带有V的字符串,这种方法简单有效,同样可以获得准确的GPS坐标信息。

3.若干注意点
3.1 重置解析载体缓冲区
    由于nmealib虽然使用C语言,但是相关测试环境均基于PC环境,所以在嵌入式环境下需要对相关参数(宏定义)进行修改。例如context.h文件中,定义了待处理的nmea缓冲区的大小,相关宏定义如下
#define NMEA_DEF_PARSEBUFF  (1024)
#define NMEA_MIN_PARSEBUFF  (256)
   示例代码的分析中提到,解析载体parser通过动态内存分配的方法开辟空间,该空间位于RAM空间中的heap部分,如果heap部分设置的太小,将会导致MCU进入不可预知的状态或者直接掉入断言中。
在编译器设置中,option->linker,cstack和heap的大小设置如下图所示,此时heap的大小仅有512个字节,而解析载体却需要1024个字节,那么分配内存时势必会产生问题,而工程的编译却不会有任何问题。

图2 不合适的HEAP大小设置
  1.     if(0 == (parser->buffer = malloc(buff_size)))
  2.         nmea_error("Insufficient memory!");        //  此时会发生内存分配错误
  3.     else
  4.     {
  5.         parser->buff_size = buff_size;
  6.         resv = 1;
  7.     }
复制代码
在这种情况下可以适当减少缓冲区的大小,例如修改如下:
#define NMEA_DEF_PARSEBUFF  (256)
#define NMEA_MIN_PARSEBUFF  (128)
同时可以把HEAP空间大小的调整一下。

图3 合适的HEAP大小设置
当然缓冲区的大小也是视情况而定,若GPS模块仅输出GPRMC语句,那么256字节的缓冲区已经足够了。但是如果GPS模块输出GPGGA, GPGSA, GPGSV, GPRMC, GPVTG等多种数据,那么256字节的缓冲区也有可能不够使用。
3.2 注意nmeaINFO结构体大小
    nmeaINFO结构体左右360字节,若该结构体类型的变量势必会占用较多的CSTACK(全局变量的情况除外),在嵌入式编程中像nmeaINFO类型的变量也可算的上是中型“人物”了。所以在调试的过程中可以打开IDE的stack查看功能(进入debug模式,view->stack),观察当前函数的CSTACK使用情况,尤其要注意CSTACK越界的情况。

图4 查看CSTACK空间占用情况
    从上图可以看出,CSTACK的大小为2048字节(2K),此时被占用752字节,占用率为36%,完全在可以接受的范围内。
4.总结
    nmealib的使用可以缩短GPS的开发周期,这里只是简单的举例了nmealib的基本功能,更多的功能可以查看samples文件夹中的例子,并在实践中不断熟悉提高。
    示例工程链接:百度网盘
    http://pan.baidu.com/share/link? ... 2&uk=3707837393
    简要说明:IAR ARM 6.5 simulator
    最后感谢我的同事utopiaprince,我从他那里学到很多东西,也帮助我解决了很多“疑难杂症”。

本帖子中包含更多资源

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

x

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

如果想吃一顿饺子,就得从冰箱里取出肉,剁馅儿,倒面粉、揉面、醒面,擀成皮儿,下锅……
一整个繁琐流程,就是为了出锅时那一嘴滚烫流油的热饺子。

如果这个过程,禁不住饿,零食下肚了,饺子出锅时也就不香了……《非诚勿扰3》

出110入0汤圆

发表于 2013-10-17 17:04:47 | 显示全部楼层
又见楼主来送福利的,很快就用这个

出0入0汤圆

 楼主| 发表于 2013-10-17 17:07:12 | 显示全部楼层
Flyback 发表于 2013-10-17 17:04
又见楼主来送福利的,很快就用这个

这个的确非常好用,比其他的代码稳定的多了!

出0入0汤圆

发表于 2013-10-17 18:43:37 | 显示全部楼层
以前自己写过一段,只解析了最基本的一些信息。
这个库都提供了那些功能啊?比如计算距离,日落日出的有没有?

出0入0汤圆

 楼主| 发表于 2013-10-17 19:02:06 | 显示全部楼层
AIHHLI 发表于 2013-10-17 18:43
以前自己写过一段,只解析了最基本的一些信息。
这个库都提供了那些功能啊?比如计算距离,日落日出的有没 ...

计算距离是有的,但是日出日落好像没有找到过。

出0入0汤圆

发表于 2013-10-17 20:19:54 | 显示全部楼层
xukai871105 发表于 2013-10-17 19:02
计算距离是有的,但是日出日落好像没有找到过。

哦,那再请问一下是否知道计算距离是使用什么算法?还有精度怎么样?

出0入0汤圆

 楼主| 发表于 2013-10-17 21:53:36 | 显示全部楼层
AIHHLI 发表于 2013-10-17 20:19
哦,那再请问一下是否知道计算距离是使用什么算法?还有精度怎么样?

有计算直线距离的算法,也有考虑地球曲面的算法
至于精度吗,我不知道你什么意思了。

出0入0汤圆

发表于 2013-10-17 22:29:20 | 显示全部楼层
xukai871105 发表于 2013-10-17 21:53
有计算直线距离的算法,也有考虑地球曲面的算法
至于精度吗,我不知道你什么意思了。 ...

-_-!
我的意思是误差....不好意思。

出200入0汤圆

发表于 2013-10-18 10:57:10 来自手机 | 显示全部楼层
好东东,收藏

出0入17汤圆

发表于 2014-1-1 22:10:30 | 显示全部楼层
好东东,收藏

出0入0汤圆

 楼主| 发表于 2014-1-1 22:26:09 | 显示全部楼层
这个帖子顶的人倒是不多啊!

出0入0汤圆

发表于 2014-1-2 22:47:16 | 显示全部楼层
http://nmea.sourceforge.net/#downloads
打不开的

出0入0汤圆

 楼主| 发表于 2014-1-3 08:23:09 | 显示全部楼层
可以打开的,我又尝试了一下!

出0入0汤圆

发表于 2014-1-17 12:37:16 | 显示全部楼层
之前也被处理GPS数据问题困扰过     试试楼主的方法  

出0入0汤圆

发表于 2014-1-17 12:45:37 | 显示全部楼层
这个库不错

出0入0汤圆

 楼主| 发表于 2014-1-17 16:49:00 | 显示全部楼层
4058665 发表于 2014-1-17 12:37
之前也被处理GPS数据问题困扰过     试试楼主的方法

这个简单易用,稳定可靠!

出0入0汤圆

发表于 2014-1-17 17:12:35 | 显示全部楼层
收藏学习!~

出0入0汤圆

发表于 2014-1-17 17:26:44 | 显示全部楼层
要是搞个linux的GPS导航就爽了,现在导航用的都是CE的多

出0入0汤圆

 楼主| 发表于 2014-1-17 23:07:24 | 显示全部楼层
xi_liang 发表于 2014-1-17 17:26
要是搞个linux的GPS导航就爽了,现在导航用的都是CE的多

这个应该弄起来也不难,就用这个库,用树莓派也是可以的!

出0入0汤圆

发表于 2014-1-17 23:48:02 | 显示全部楼层
这个是很不错呀,之前自己写了一个,感觉不全面,这下可有得参考了,谢谢LZ分享

出0入0汤圆

发表于 2014-1-19 23:42:17 | 显示全部楼层
不错,收藏了。有空自己也做一个。

出0入0汤圆

发表于 2014-1-20 09:19:59 | 显示全部楼层
好东西,先留着,以后用

出0入8汤圆

发表于 2014-1-20 09:31:29 | 显示全部楼层
好东西  值得收藏

出0入0汤圆

发表于 2014-1-20 11:15:34 | 显示全部楼层
GPS nmealib学习笔记 好东西

出0入0汤圆

发表于 2014-6-30 15:28:17 | 显示全部楼层
nmealib内存泄漏在paser.c中
            case GPRMC:
                if(0 == (node->pack = malloc(sizeof(nmeaGPRMC))))
                    goto mem_fail;
                node->packType = GPRMC;
                if(!nmea_parse_GPRMC(
                    (const char *)parser->buffer + nparsed,
                    sen_sz, (nmeaGPRMC *)node->pack))
                {
                    free(node->pack);
                    free(node);
                    node = 0;
                }
                break;


上面那个free(node->pack) 是我加上去的,相应几种nmea语法都要加

出0入0汤圆

发表于 2014-6-30 15:29:34 | 显示全部楼层
nmealib源文件,没任何修改

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-7-1 08:20:51 | 显示全部楼层
boycn 发表于 2014-6-30 15:28
nmealib内存泄漏在paser.c中
            case GPRMC:
                if(0 == (node->pack = malloc(size ...

有的时候GPS再定位失败的时候也会发出NMEA语句,但是不会解析发导致堆溢出。
这个我知道,但是没有写在帖子中,后来就渐渐就忘了。

多谢提醒,亲爱的坛友!

出0入0汤圆

发表于 2014-7-21 15:47:40 | 显示全部楼层
大部分数据都是双精度浮点,单片机一般不这么折腾。

出0入0汤圆

发表于 2014-8-2 15:10:39 | 显示全部楼层
示例工程链接:百度网盘
    http://pan.baidu.com/share/link? ... 2&uk=3707837393

楼主,你这个工程已经删除,能发一份给我不。谢谢。

出0入0汤圆

发表于 2014-8-2 15:17:39 | 显示全部楼层
标记 这个好

出0入0汤圆

 楼主| 发表于 2014-8-3 21:53:29 | 显示全部楼层
Shaw.Embedi 发表于 2014-8-2 15:10
示例工程链接:百度网盘
    http://pan.baidu.com/share/link? ... 2&uk=3707837393


一个IAR MSP的工程,你要根据实际情况进行修改。

本帖子中包含更多资源

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

x

出0入0汤圆

 楼主| 发表于 2014-8-3 21:55:12 | 显示全部楼层
Shaw.Embedi 发表于 2014-8-2 15:10
示例工程链接:百度网盘
    http://pan.baidu.com/share/link? ... 2&uk=3707837393

对源码有少量的修改,请确认modify by xukai部分

出0入0汤圆

发表于 2014-8-4 11:33:43 | 显示全部楼层
xukai871105 发表于 2014-8-3 21:55
对源码有少量的修改,请确认modify by xukai部分

刚接触学习GPS模块,这个对我帮助很大。谢谢。

出0入0汤圆

发表于 2014-9-3 22:07:34 | 显示全部楼层
楼主您好,我用MDK,一直报
..\Output\STM32-GPS.axf: Error: L6218E: Undefined symbol time (referred from time.o).

这个错误,不知怎么弄,麻烦楼主提点一下,谢谢!

出0入0汤圆

发表于 2014-9-3 22:16:02 | 显示全部楼层
谢谢分享!调试GPS的利器啊!

出0入0汤圆

发表于 2014-9-3 22:19:14 | 显示全部楼层
先收藏,以后肯定用得着

出0入0汤圆

 楼主| 发表于 2014-9-4 08:28:50 | 显示全部楼层
shenrongze 发表于 2014-9-3 22:07
楼主您好,我用MDK,一直报
..\Output\STM32-GPS.axf: Error: L6218E: Undefined symbol time (referred fr ...

抱歉,我很少使用Keil,所以无法直接回答你这个问题。
不过直觉告诉我,这个问题是不是一个 时间问题,好像是解析日期时间的函数,我记得我当时注释了该部分。

出0入0汤圆

发表于 2014-9-4 09:39:08 | 显示全部楼层
xukai871105 发表于 2014-9-4 08:28
抱歉,我很少使用Keil,所以无法直接回答你这个问题。
不过直觉告诉我,这个问题是不是一个 时间问题,好 ...

用了你示例工程里面的源码,果然没有这个报错了。


再细读了,谢谢~~  

出5入4汤圆

发表于 2014-9-13 22:31:51 | 显示全部楼层
MARK,用lib方便不少,代码规范很多

出0入0汤圆

发表于 2015-3-7 20:45:17 | 显示全部楼层
赞啊。。。。。

出0入0汤圆

发表于 2015-4-1 10:10:11 | 显示全部楼层
好东西,谢谢分享,

出0入0汤圆

发表于 2015-10-18 22:15:55 | 显示全部楼层
谢谢楼主的资料,正好需要,多谢了

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-3-28 23:48

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

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