首页 > 其他分享 >U-BLOX GPS 模块及GPRMC指令解析

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

时间:2022-11-10 08:33:40浏览次数:70  
标签:GPRMC frame 120116 uint8 BLOX 模块 GPS

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

1. 介绍

基本信息如下:

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

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

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

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

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

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

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

 

2. 通信协议

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 

3. PC端显示数据

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

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

 1   $GPGSV,2,2,08,21,15,076,,23,52,270,,26,50,050,,27,52,179,*7D 2   $GPRMC,132043.00,V,,,,,,,120116,,,N*7F 3   $GPVTG,,,,,,,,,N*30 4   $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30 5   $GPGSV,2,1,08,03,00,230,,07,02,301,,08,24,198,,16,72,000,*7B 6   $GPGSV,2,2,08,21,15,076,,23,52,270,,26,50,050,,27,52,179,*7D 7   $GPRMC,132044.00,V,,,,,,,120116,,,N*78 8   $GPVTG,,,,,,,,,N*30 9   $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*3010   $GPGSV,2,1,08,03,00,230,,07,02,301,,08,24,198,,16,72,000,*7B11   $GPGSV,2,2,08,21,15,076,,23,52,270,25,26,50,050,,27,52,179,*7A12   $GPRMC,132045.00,V,,,,,,,120116,,,N*7913   $GPVTG,,,,,,,,,N*3014   $GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*3015   $GPGSV,2,1,08,03,00,230,,07,02,301,,08,24,198,,16,72,000,*7B16   $GPGSV,2,2,08,21,15,076,,23,52,270,,26,50,050,,27,52,179,*7D17   $GPRMC,132046.00,V,,,,,,,120116,,,N*7A18   $GPVTG,,,,,,,,,N*3019   $GPGSV,2,1,08,03,00,230,,07,02,301,,08,24,198,,16,72,000,*7B20   $GPGSV,2,2,08,21,15,076,07,23,52,270,20,26,50,050,,27,52,179,*7821   $GPRMC,132049.00,V,,,,,,,120116,,,N*7522   $GPRMC,133300.00,V,,,,,,,120116,,,N*7A23   $GPRMC,133301.00,V,,,,,,,120116,,,N*7B24   $GPRMC,133302.00,V,,,,,,,120116,,,N*7825   $GPRMC,133303.00,V,,,,,,,120116,,,N*7926   $GPRMC,133304.00,V,,,,,,,120116,,,N*7E27   $GPRMC,133305.00,V,,,,,,,120116,,,N*7F28   $GPRMC,133306.00,A,3949.63075,N,11616.48616,E,0.513,,120116,,,A*7A29   $GPRMC,133307.00,A,3949.63025,N,11616.48614,E,1.053,,120116,,,A*7C30   $GPRMC,133308.00,A,3949.63002,N,11616.48641,E,1.101,,120116,,,A*7031   …………

 

4. PC端软件配置

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

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

 

5. 数据解析

      相对于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 = 0;     int16_t rcv_buf_data_len = 0;     int16_t index = 0;     int16_t frame_start_point = 0;     int16_t remain_data_len = 0;     uint8_t rtn =0;         gps_rcv_enable(FALSE);      rcv_buf_data_len = GPS_Rev_Buf_Size;     p_frame_start = &GPS_Uart_Rcv_Buf[0];            /* 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 = 0; 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*79         if(p_frame_start)          {              index = p_frame_start-GPS_Uart_Rcv_Buf;              if(index>0)                {                    memset(GPS_Uart_Rcv_Buf, 0 , index);                }              index = index + 7;              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 > 20)||(frame_start_point <= 0))//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 + 1;                 if((frame_len > GPS_Frame_Buf_Size)||(frame_len <= 50)) // not found frame end                {                    continue;                }                                //$GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79                frame_start_point = p_frame_start - GPS_Uart_Rcv_Buf + 1;                memset(GPS_Frame_Buf, 0, 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 correct                rtn = read_gps_data(GPS_Frame_Buf, remain_data_len, weidu, jingdu);                if(1 == rtn)                {                    break; //found weidu,jingdu data                }                else                {                     continue;                }            }            else            {               break;            }         }        g_gps_data_cnt = 0;        memset(GPS_Uart_Rcv_Buf, 0, 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 =0;     //GPRMC,133735.00,A,3949.63893,N,11616.48419,E,0.296,,120116,,,A*79     weidu_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,0,sizeof(weidu_buf));          memset(jindu_buf,0,sizeof(jindu_buf));          memcpy(weidu_buf, weidu_s+3, (weidu_o-weidu_s-3));          memcpy(jindu_buf, weidu_o+3, (jingdu_o-weidu_o-3));          printf("\r\n---------------------------------------");          printf("\r\nGet GPS Frame:\r\n%s\r\n", GPS_Frame_Buf);          printf("\r\n---------------------------------------");          rtn = TRUE;     }    return rtn;}

6. 总结

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

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

      2:字符串的解析。

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

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

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

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

 


---------------------
作者:啊哈彭
来源:CNBLOGS
原文:https://www.cnblogs.com/pingwen/p/5225461.html
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

标签:GPRMC,frame,120116,uint8,BLOX,模块,GPS
From: https://www.cnblogs.com/sdufe/p/16875845.html

相关文章

  • 基于IMU和GPS数据融合的自车定位 (卡尔曼)
    如果想深入了解IMU和GPS融合原理,可以看看这篇文章: 重读经典《Quaternionkinematicsfortheerror-stateKalmanfilter》,这也是Coursera课程关于这一项目的参考文献。......
  • GPS位置模拟-安卓
    测试定位功能时都需要位置模拟,一般有如下3种方式:a)手机上安装第三方模拟软件:需要Root;b)PC模拟其中运行app并模拟位置:不能在真机上运行,手机兼容性不能测试到;b)在app......
  • GPS时间获取 - 流水江湖 - 博客园
    https://github.com/leech001/gps任务很简单就是将从串口获取的GPS数据包提取你需要的gps数据信息,过滤掉不用的数据即可. GPS数据类型及格式GPS数据信息类型有下面几......
  • GPS信息和字段含义
    @目录前言字段分析$GPGGA(GPS定位信息)$GPGLL(大地坐标信息)$GPGSA(当前卫星信息)$GPGSV(可见卫星信息)$GPRMC(推荐定位信息)$GPVTG(地面速度信息)GPS的误差前言不同信息条目,不同字段......
  • Android实现GPS定位,不用SDK
    权限<uses-permissionandroid:name="android.permission.ACCESS_FINE_LOCATION"/><uses-permissionandroid:name="android.permission.ACCESS_COARSE_LOCATI......
  • GPS载波同步MATLAB仿真
     %载波跟踪算法仿真clcclearclf%输入信号参数定义fd=2.45e+3;f_ref=4.092e+6;fi=(4.092e+6)+fd;fs=16.368e+6;Ts=1/fs;N=16368;Repeat_Num=0.5000e+4;Freq_Step=500;......
  • [转]嵌入式系统上实现GPS全球定位功能
           GPS(GlobalPositioningSystem)即全球定位系统,是由美国建立的一个卫星导航定位系统,利用该系统,用户可以在全球范围内实现全天候、连续、实时的三维导航定......
  • cgps gpsmon
    cgpsgpsmon来源 https://www.openwrt.pro/post-514.html Openwrt设备安装GPS模块、安装驱动、安装GPSD读取GPS信息,使用gpsmon或cgps软件展示获取信息因项目需求,现需......
  • gps坐标系转高德坐标系
    详细说明:坐标转换importrequests#116.497759,39.979316#116.497759,39.979331#116.497759,39.979346defgd_map():para={'key':'8a2191b448b4de6aefe7f......
  • 数据实战2-出租车GPS数据
    继续上周的数据实战-本周主要围绕出租车GPS展开一、从出租车GPS数据中提取乘客出行OD1.数据清洗:是对数据进行检查和校验的过程,包括检查数据一致性,处理无效值和缺失值等......