c语言 GPS nmealib学习笔记

摘要:
通过测试,nmealib处理第一种情况没有任何问题,但是连续处理第二种和第三种情况会产生问题,产生问题的主要原因是动态开辟的空间没有被释放。解决该问题需要修改nmealib的源代码,这种修改是有难度的。
0.nmealib简介
    nmealib是一个基于C语言的用于nmea协议的开源库。虽然nmea体积小巧,但是却具备了不少功能。
    分析NMEA语句并把结果保存在合适的C语言结构体中。
    除了解析NMEA语句之外,还可以产生NMEA语句。
    支持多种NMEA语句,包括GPGGA, GPGSA, GPGSV, GPRMC, GPVTG。
    解析算法层次严谨。
    附加地理学相关功能,可支持导航等数据工作。
    更多介绍请参考以下链接
    http://nmea.sourceforge.net/#downloads
1.目录介绍
    nmealib的目录还是非常清晰的,下面简单介绍一下。
    include
mealib文件夹中存在nmealib相关的头文件
    src文件夹存放nmealib相关源文件,该文件夹中的内容和include
mealib文件夹相对应
    samples文件夹存放若干例子,一些简单易懂的例子。
#include <nmea/nmea.h>
#include <string.h>
#include <stdio.h>
intmain()
{
    //被测试的GPS模块输出数据,仅有GPRMC格式
    char gps_str[] = "$GPRMC,013257.00,A,3129.51829,N,12022.10562,E,0.093,,270813,,,A*7A
";
    nmeaINFO info;                  //nmea协议解析结果结构体
    nmeaPARSER parser;              //nmea协议解析载体

    nmea_zero_INFO(&info);          //填入默认的解析结果
    nmea_parser_init(&parser);      //为解析载体分配内存空间
    //调用函数完成GPS信息解析,最终结果保留于info数组中
    if( (nmea_parse(&parser, gps_str, (int)strlen(gps_str), &info)) > 0)
    {
        printf("longitude   %.5f
",info.lon);
        printf("latitude    %.5f
",info.lat);
        printf("speed       %.2f
",info.speed);
    }
    nmea_parser_destroy(&parser);   //释放解析载体的内存空间
    return 0;
}

利用nmealib解析GPS模块的输出结果大致可以分为三步,第一步定义和初始化GPS信息结构体和解析载体结构体,第二步调用nmea_parse函数完成解析工作,第三步释放解析载体所占用的内存空间。如果仔细查看nmea_parser_init部分的代码,便会发现函数中使用了C标准库的malloc函数,该函数会在RAM中的heap空间开辟一个空间,这就需要使用完该载体之后立刻释放,所以nmea_parser_init和nmea_parser_destroy需要成对出现。

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
2) $GPRMC,022649.00,V,,,,,,,020913,,,N*7F
3) $GPRMC,,V,,,,,,,,,,N*53
第一种: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个字节,那么分配内存时势必会产生问题,而工程的编译却不会有任何问题。

4.总结

nmealib的使用可以缩短GPS的开发周期,这里只是简单的举例了nmealib的基本功能,更多的功能可以查看samples文件夹中的例子,并在实践中不断熟悉提高。
示例工程链接:百度网盘
简要说明:IAR ARM 6.5 simulator
更多

免责声明:文章转载自《c语言 GPS nmealib学习笔记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇[转载]字符串-02. 删除字符串中的子串(20)长连接 、短连接、心跳机制与断线重连下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

TIOBE 四月世界编程语言排行榜:C语言重回榜首

TIOBE 2012年4月世界编程语言排行榜已经发布。C语言超越了Java重回榜首;而Objective-C则一路飙升,超越了C#,占据了第4的位置;并且C++也重新回到第3的位置。而Python持续下滑,目前排名第8。 TIOBE2012年4月世界编程语言排行榜的前20名 从开发领域来讲,只要有合适的硬件驱动和API,C或者C++理论上是可以做任何开发的...

C语言的面向对象设计 —— 对 X264/FFMPEG 架构探讨

类似题目的文章已经不新鲜了,这里,我仅仅总结自己的一些代码经验,结合两款在视频开发领域比较常用的开源软件探讨C语言的应用问题。 1.为什么要用C语言 曾几何时,我也不熟悉C,最早接触C的是在大学四年级,当时已经学过pascal,过二级也是pascal。接着走上了Delphi的路,多方便的软件,写写画画,程序就出来了,本科的毕业设计就是这样出来的MIS,在当...

Linux C语言头文件搜索路径

本文介绍在linux中头文件的搜索路径,也就是说你通过include指定的头文件,linux下的gcc编译器它是怎么找到它的呢。在此之前,先了解一个基本概念。     头文件是一种文本文件,使用文本编辑器将代码编写好之后,以扩展名.h保存就行了。头文件中一般放一些重复使用的代码,例如函数声明、变量声明、常数定义、宏的定义等等。当使用#include语句将...

C语言实现进度条

C语言实现进度条 学观察者模式时想实现一个进度条通知实例,花了一些时间,记录下来吧。 #include <stdio.h> #include <iostream> #include <windows.h> void DoProgress(int t, int n) { putchar('['); for...

(转)C语言中格式化日期时间asctime()函数详细讲解

函数原型:char *asctime(const struct tm *tblock); 功能说明:将tm结构类型时间日期转换为ASCII码。 头文件: 参数说明:语法:asctime[必要参数] 必要参数的具体说明如下: tblock:待转换的时间指针,tblock为一tm结构型指针。 返回值:返回由tm结构中的日期和时间转换成的字符串的地址,该字符串的...

xilinx FPGA课程学习总结

    一时冲动,跑步进入了FPGA的大门,尤老师是教练,我之前一直做嵌入式软件,数字电路也是十年前大学课堂学过,早已经还给老师了。FPGA对于我来说完全是小白,所以。老师的课程,对于我来说至关重要!因为见过太多从入门到放弃的案例了! 什么样的教程和视频,可以不至于让小白从入门到放弃呢?我总结了几点:1.由浅入深,循序渐进,不急躁,不跃进,符合人的认知规律...