[原创] 《GPSR+GPS开发板》之二GPS解码

zhaojun_xf   2013-8-12 06:37 楼主
对于GPS,想必大家都比较熟悉了。对于GPS的解码大家应该都知道,其解码难度并不大,原理非常简单。不管怎样,下面我们还是详细的介绍一下这个过程及相关知识。

       GPS是英文Global Positioning System(全球定位系统)的简称。GPS起始于1958年美国军方的一个项目,1964年投入使用。20世纪70年代,美国陆海空三军联合研制了新一代卫星定位系统GPS 。主要目的是为陆海空三大领域提供实时、全天候和全球性的导航服务,并用于情报收集、核爆监测和应急通讯等一些军事目的,经过20余年的研究实验,耗资300亿美元,到1994年,全球覆盖率高达98%的24颗GPS卫星星座己布设完成。在机械领域GPS则有另外一种含义:产品几何技术规范(Geometrical Product Specifications)-简称GPS。另外一种解释为G/s(GB per s)。

定位原理
       GPS定位的基本原理是根据高速运动的卫星瞬间位置作为已知的起算数据,采用空间距离后方交会的方法,确定待测点的位置。如图所示,假设t时刻在地面待测点上安置GPS接收机,可以测定GPS信号到达接收机的时间△t,再加上接收机所接收到的卫星星历等其它数据可以确定以下四个方程式。

1.png



定位精度
28颗卫星(其中4颗备用)早已升空,分布在6条交点互隔60度的轨道面上,距离地面约20000千米。已经实现单机导航精度约为10米,综合定位的话,精度可达厘米级和毫米级。但民用领域开放的精度约为10米。
我的博客

回复评论 (26)

我们所说的GPS协议一般指:NMEA-0183协议

       NMEA协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的RTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。

    NMEA协议有0180、0182和0183这3种,0183可以认为是前两种的升级,也是目前使用最为广泛的一种NMEA-0183协议是GPS接收机应当遵守的标准协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。也有少数厂商或软件不支持NMEA-0183,购买和使用的时候需要注意识别。
NAEA 0183 GPS协议该协议为NAEA 0183 2.0版,此协议是为了在不同的GPS导航设备中建立统一的RTCM标准。NAEA 0183语句以ASCII格式输出,传输速率可自定义。

       NMEA通讯协议所规定的通讯语句都已是以ASCII码为基础的,NMEA-0183协议语句的数据格式如下:“$”为语句起始标志;“,”为域分隔符;“ *”为校验和识别符,其后面的两位数为校验和,代表了“$”和“*”之间所有字符的按位异或值(不包括这两个字符);“/”为终止符,所有的语句必须以回车换行来结束,也就是ASCII 字符的“回车”(十六进制的0D)和“换行”(十六进制的0A)

在读取输出语句时数据之间最好用“,”区分,不要按位读取,以保证应用程序的兼容性。

对于不同的GPS模块来说,实际输出的语句是有一定的区别的,但不管怎么说,常见的几个语句一般都还是有的。


[ 本帖最后由 zhaojun_xf 于 2013-8-12 06:41 编辑 ]
我的博客
点赞  2013-8-12 06:39
1、GGA

$GPGGA、<1>、<2>、<3>、<4>、<5>、< 6>、<7>、<8>、<9>、M, <11>、<12>*hh
<0>$GPGG,语句ID,表明该语句为GlobalPositioning System Fix Data(GGA)GPS定位信息
<1>UTC时间,hh mm ss格式(定位它的卫星提供)
<2>纬度dd mm mmmm 格式(前导位数不足则补0)
<3>纬度方向 (北纬)或S(南纬)
<4>经度ddd mm mmmm 格式(前导位数不足则补0)
<5>经度方向E(东经)或W(西经)
<6>GPS状态指示:0—未定位, 1—无差分定位信息, 2—带差分定位信息 ,3-无效GPS,6-正在估算
<7>正在使用的卫星数量(00- 12)(前导位数不足则补0)
<8>HDOP水平精度因子(0.5- 99.9)
<9>海平面高度(-9999.9- 99999.9)
<10>地球椭球面相对大地水准面的高度
<11>差分GPS信息,即差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空)
<12>差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)

2、GSA

$GPGSA、<1>、<2>、<3>、<3>、<3>、<3>、< 3>、<3>、<3>、<3>、<3>、<3>、<3>、< 3>、<4>、<5>、<6>、*hh
<0>$GPGSA,语句ID,表明该语句为GPSDOP and Active Satellites(GSA)当前卫星信息
<1>定位模式M—手动,A—自动
<2>当前状态 1—无定位信息,2—2D   3—3D
<3>PRN号01~32(伪随机噪声码),当前信道(共12个信道)正在使用的卫星PRN码编号(00)(前导位数不足则补0)
<4>PDOP综合位置精度因子(0.5- 99.9)
<5>HDOP水平精度因子(0.5- 99.9)
<6>VDOP垂直精度因子(0.5- 99.9)

3、GSV

$GPGSV、<1>、<2>、<3>、<4>、<5>、<6>、< 7><4>、<5>、<6>、<7>*hh
<0>$GPGSV,语句ID,表明该语句为GPSSatellites in View(GSV)可见卫星信息
<1>GSV语句的总数目(1 -3)
<2>当前GSV语句数目(1 -3)
<3>显示卫星的总数目00~12(前导位数不足则补0)
<4>卫星的PRN号星号(01- 32)(前导位数不足则补0)
<5>卫星仰角(00- 90)度(前导位数不足则补0)
<6>卫星旋角(00- 359)度(前导位数不足则补0)
<7>信噪比(00-99)dbHz
*语句共两条,每条最多包括4颗星的处所。每个星有4个数据,即<4>—星号 <5>—仰角<6>—方位<7>—信噪比

4、RMC

$GPRMC、<1>、<2>、<3>、<4>、<5>、< 6>、<7>、<8>、<9>、<10>、<11>、*hh
<0>$GPRMC,语句ID,表明该语句为RecommendedMinimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
<1>定位时UTC时间hhmmss.sss格式
<2>状态A=定位V=导航
<3>经度ddmm.mmm 格式(前导位数不足则补0)
<4>经度方向N(北纬)或S(南纬)
<5>纬度dddmm.mmmm (前导位数不足则补0)
<6>纬度方向E(东经)或W(西经)
<7>速率,节,Knots
<8>方位角(二维方向指向,相当于二维罗盘)
<9>当前UTC日期ddmmyy 格式
<10>磁偏角,(000- 180)度(前导位数不足则补0)
<11>磁偏角方向,E=东经  W=西经

5、VTG

$GPVTG、<1>、T、<2>、M、<3>、N、<4>K*hh
<0>$GPVTG,语句ID,表明该语句为TrackMade Good and Ground Speed(VTG)地面速度信息
<1>真实方向(000 - 359),(前导位数不足则补0)
T-正北参照系
<2>相对方向
M-磁北参照系
<3>步长
N-节,Knots
<4>速率
K-公里/时,km/h

6、GPGLL

例:$GPGLL,<1>,S,<3>,E,<5>,<6>*<7>
<0>:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息
<1>:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
<2>:纬度N(北纬)或S(南纬)
<3>:经度dddmm.mmmm,度分格式(前导位数不足则补0)
<4>:经度E(东经)或W(西经)
<5>:UTC时间,hhmmss.sss格式
<6>:状态,A=定位,V=未定位
<7>:校验值
我的博客
点赞  2013-8-12 06:42
很多情况下,我们并不需要把这些语句都完全解码出来。一般来说,我们只需要解码出我们需要的信息即可。为此,绝大多数情况下,我们只需要解码 GPRMC 语句,有时我们为了进一步获取完善的定位信息,还会解码 GPGGA 语句。

下面我们将介绍解码这两种语句的具体方法及程序代码。
我的博客
点赞  2013-8-12 06:47
硬件原理图:

1.png



    首先我们看看本系统的硬件原理图,从图不难看出,GPS部分由一个电源芯片、两GPS模块和一个串口座组成。实际的应中并不需要这么复杂。这样做是为了能够满足各种封装和各种接口的GPS。图上的两个模块分别代表着两种常见的尺寸的模块。而串口是用于通过座子连接的GPS模块。实际应用中只要选择其中一种即可。

    电源芯片一般采用5v转3.3v的DC-DC即可,不过需要注意模块的工作电流,一般工作电流在40mA左右,启动电流会大一些,当然不同模块,可能存在差异。所以,在选择电源芯片的时候一定要注意其输出电流不能低于应用,而且应该保留一定的空余空间。

     GPS天线检查部分没有放在上图中,不同的模块对天线检查电路的要求是不一样的。有点是根据外部硬件电路直接检查,有的是以GPS语句的形式输出天线状态。不管是哪一种,我们可以根据GPS模块资料找到参考。

      GPS模块只是一个GPS信号接收与处理的系统,一般情况下,并不需要对模块发送数据。我们只需要每秒把GPS接收的数据解码出来即可。
我的博客
点赞  2013-8-12 07:03
对于GPS解码,实际上非常简单。但我们这里还是要相信说明一下我们的解码方法。我们代码的事实性,同时最大程度的利用CPU,提高CPU的工作效率。我们把GPS的数据接收与数据解码分开处理。

    GPS的接收是通过串口中断进行的,接收到的数据我们直接放入串口缓冲器中,而不用在中断中对数据进行数据解码。

    GPS的数据处理是通过时间间隔性扫描缓冲区,如果缓冲区中有数据,就对该数据进行取帧处理,这个间隔一般可以采用1s一次,因为GPS数据的接收频率就是1s一次。

     如果理解了这个过程,其他就非常简单了。我们可以把接收与处理完全当着两个任务来处理。他们之间的通过接收和处理变量联系。
我的博客
点赞  2013-8-12 07:11
GPS数据接收:

     在透传贴中我们说到,可以同串口命令更改模块的传送模式。在透传模式下,我们直接把GPS模块接收到的数据发送到主串口,而不用对模块数据进行任何处理。在非透传模式下,我们通过串口中断把数据放入缓冲区中。在应用中我们只需要把下面这个函数放入串口中断服务函数中即可。
  1. /****************************************************************************************************
  2. * FunctionName   : UART3_IRQHandler()                                                           
  3. * Description    : UART3 Interrupt
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void UART3_IRQHandler(void)
  8. {
  9.     u8 tmpDat;

  10.     switch (UARTItGetMode(UART3))
  11.     {
  12.         case UIT_MOD_RCV:                                       // 接收中断
  13.         {
  14.             UARTItRcvBuf(UART3, &tmpDat, 1);             // 读一字节
  15.             AppRcvUGps(tmpDat, &AppPar.WrkMod);       // 数据接收
  16.             break;
  17.         }

  18.         case UIT_MOD_OUT: break;                         // 超时中断
  19.         case UIT_MOD_SND: break;                          // 发送中断
  20.         default: break;
  21.     }                 
  22. }
中断接收函数,把数据放入接收缓冲区。
  1. /****************************************************************************************************
  2. * FunctionName   : AppRcvUGps()                                                           
  3. * Description    : GPS接收数据处理
  4. * EntryParameter : dat - 接收数据,pWrkMod - 工作模式(0-正常,1-GSM透传,2-GPS透传)
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void AppRcvUGps(u8 dat, APP_WRK_MOD *pWrkMod)
  8. {
  9.     switch (*pWrkMod)
  10.     {
  11.         case APP_WRK_TGP: UARTSendByte(UART0, dat);   break;   // GPS透传
  12.         default         : DTFWriteByte(dat, &GpsBuf); break;
  13.     }
  14. }
数据放入缓冲中的是调用 DTFWriteByte()函数,由于串口的处理方法都是一样的,我们把所有对串口的处理单独独立出来。
  1. /****************************************************************************************************
  2. * FunctionName   : DTFWriteByte()
  3. * Description    : 数据接收(接收中断调用)
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void DTFWriteByte(u8 dat, DTF_RCV *pRcv)
  8. {
  9.     pRcv->RwBuf[pRcv->WtCnt] = dat;              // 数据存入
  10.    
  11.     if (++(pRcv->WtCnt) >= pRcv->BufLen)       // 缓冲判断
  12.     {
  13.         pRcv->WtCnt = 0;
  14.     }
  15. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 05:48 编辑 ]
我的博客
点赞  2013-8-12 07:19
在使用GPS之前需要先初始化GPS模块,例如变量的初始化、管脚定义、模块电源控制、复位模块并启动模块等。
  1. /****************************************************************************************************
  2. * FunctionName   : GpsInit()
  3. * Description    : 初始化
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void GpsInit(void)
  8. {
  9.     Gps_SetGpio();
  10.     DTFInit(&GpsBuf);
  11.     GpsPar.StaMrk = GPS_STT_PCS;
  12.     Gps_StartMdl();                                                                              // 启动GPS模块
  13. }
函数Gps_StartMdl()是用于启动模块的,调用此函数开始启动模块,其过程:关闭电源->打开电源->模块复位->取消复位。在这个过程中,我们是同定时器自动实现步骤连接的。在关闭电源是时候我们开始100ms定时,在定时时间到后,会改变GpsPar.StaMrk的值进入下一步。。。
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_StartMdl()
  3. * Description    : 启动模块
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void Gps_StartMdl(void)
  8. {
  9.     switch (GpsPar.StaMrk)
  10.     {
  11.         case GPS_STT_NUL: break;

  12.         case GPS_STT_PCS:                                                   // 电源关闭
  13.        {
  14.            GpsPar.StaMrk = GPS_STT_NUL;
  15.            Gps_PowSwitch(GPS_POW_CLS);
  16.            Gps_ClearBuf(&GpsBuf);
  17.            Gps_ClearPack(&GpsPck);
  18.            Gps_ClearFrmBuf(&Gps_Frm);
  19.            SFTStartFul(GpsSft, GPS_SFT_DLY, 100, Gps_StartMdl, &GpsPar.StaMrk, GPS_STT_POP);
  20.            break;
  21.        }                               

  22.        case GPS_STT_POP:                                                                                             // 电源打开
  23.       {          
  24.           GpsPar.StaMrk = GPS_STT_NUL;
  25.           Gps_PowSwitch(GPS_POW_OPN);
  26.           SFTStartFul(GpsSft, GPS_SFT_DLY, 200, Gps_StartMdl, &GpsPar.StaMrk, GPS_STT_RES);
  27.           break;
  28.      }               

  29.      case GPS_STT_RES:                                                                                                 // 模块复位
  30.      {
  31.          GpsPar.StaMrk = GPS_STT_NUL;
  32.          Gps_SetReset(1);
  33.          SFTStartFul(GpsSft, GPS_SFT_DLY, 100, Gps_StartMdl, &GpsPar.StaMrk, GPS_STT_CRS);
  34.          break;
  35.     }

  36.     case GPS_STT_CRS:                                                                                                 // 取消复位
  37.     {
  38.         GpsPar.StaMrk = GPS_STT_NUL;
  39.         Gps_SetReset(0);
  40.         SFTStartVal(GpsSft, GPS_SFT_DLY, 300, &GpsPar.StaMrk, GPS_STT_CMP);
  41.         break;
  42.     }

  43.     default: break;
  44.     }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 05:59 编辑 ]
我的博客
点赞  2013-8-12 07:19
对于定时器,本身涉及到的内容也比较多,如果读过我的新书《ARM嵌入式应用程序架构设计实例精讲---基于LPC1700》,那么定时的应用应该比较了解了,我们在它的基础上对定时进行了进一步扩展,添加了各种函数。。。

      如果对时间片轮询的实现方法比较了解,那么定时器的应用就非常简单了。如果不了解,读者可以去查看本人发的时间的相关帖子。这里不在说明。
  1. /****************************************************************************************************
  2. * FunctionName   : SFTService()
  3. * Description    : 软定时器中断服务函数(定时器中断用)
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ***************************************************************************************************/
  7. void SFTService(SFT_STU *pStu, u8 num)
  8. {
  9.     u8 i;

  10.     for (i=0; i
  11.     {
  12.         if (pStu[i].TimStu == SFT_OPN)                                   // 定时器是否打开
  13.         {
  14.             if ((pStu[i].CntVal > 0) && (--pStu[i].CntVal == 0))       // 定时判断
  15.             {
  16.                 pStu[i].TimStu  = SFT_CLS;                                // 关闭定时器
  17.                 pStu[i].OvrMrk  = SFT_CMP;
  18.                 pStu[i].CntVal  = pStu[i].IniVal;               // 定时值
  19.                 // 多种赋值,根据需求使用
  20.                 if (pStu[i].Result > 0)
  21.                 {
  22.                       *pStu[i].CmpVal = pStu[i].Result;
  23.                  }

  24.                   pStu[i].ExeFun();                                                 // 函数运行
  25.             }
  26.         }
  27.     }
  28. }

  29. /****************************************************************************************************
  30. * FunctionName   : SFTStart()
  31. * Description    : 定时器启动
  32. * EntryParameter : None
  33. * ReturnValue    : None
  34. ***************************************************************************************************/
  35. void SFTStart(SFT_STU *pStu, u8 num, u32 val)
  36. {
  37.     pStu[num].CntVal = val;            
  38.     pStu[num].OvrMrk = SFT_STT;
  39.     pStu[num].Result = 0x00;
  40.     pStu[num].TimStu = SFT_OPN;               // 打开定时器
  41. }

  42. /****************************************************************************************************
  43. * FunctionName   : SFTStop()
  44. * Description    : 定时器停止
  45. * EntryParameter : None
  46. * ReturnValue    : None
  47. ****************************************************************************************************/
  48. void SFTStop(SFT_STU *pStu, u8 num)
  49. {
  50.     pStu[num].CntVal = 0;
  51.     pStu[num].TimStu = SFT_CLS;             // 关闭定时器
  52.     pStu[num].OvrMrk = SFT_STT;
  53. }

  54. /****************************************************************************************************
  55. * FunctionName   : SFT_EmpFun()
  56. * Description    : 空函数
  57. * EntryParameter : None
  58. * ReturnValue    : None
  59. ****************************************************************************************************/
  60. void SFT_EmpFun(void)
  61. {
  62.     ;
  63. }

  64. /****************************************************************************************************
  65. * FunctionName   : SFTStartFun()
  66. * Description    : 定时器启动扩展函数
  67. * EntryParameter : None
  68. * ReturnValue    : None
  69. ****************************************************************************************************/
  70. void SFTStartFun(SFT_STU *pStu, u8 num, u32 val, void(*pFun)(void))
  71. {
  72.     pStu[num].CntVal = val;            
  73.     pStu[num].OvrMrk = SFT_STT;
  74.     pStu[num].Result = 0x00;
  75.     pStu[num].ExeFun = pFun;                                                                                                
  76.     pStu[num].TimStu = SFT_OPN;                                             
  77. }

  78. /****************************************************************************************************
  79. * FunctionName   : SFTStartMrk()
  80. * Description    : 定时器启动扩展函数
  81. * EntryParameter : None
  82. * ReturnValue    : None
  83. ****************************************************************************************************/
  84. void SFTStartMrk(SFT_STU *pStu, u8 num, u32 val, u8 *pOvr)
  85. {
  86.     pStu[num].CntVal = val;            
  87.     pStu[num].OvrMrk = SFT_STT;
  88.     pStu[num].Result = 0x01;
  89.     pStu[num].CmpVal = pOvr;
  90.     pStu[num].ExeFun = SFT_EmpFun;
  91.     pStu[num].TimStu = SFT_OPN;                                             
  92. }

  93. /****************************************************************************************************
  94. * FunctionName   : SFTStartVal()
  95. * Description    : 定时器启动扩展函数
  96. * EntryParameter : None
  97. * ReturnValue    : None
  98. ****************************************************************************************************/
  99. void SFTStartVal(SFT_STU *pStu, u8 num, u32 val, u8 *pOvr, u8 rsl)
  100. {
  101.     pStu[num].CntVal = val;            
  102.     pStu[num].OvrMrk = SFT_STT;
  103.     pStu[num].Result = rsl;
  104.     pStu[num].CmpVal = pOvr;
  105.     pStu[num].ExeFun = SFT_EmpFun;
  106.     pStu[num].TimStu = SFT_OPN;                                             
  107. }

  108. /****************************************************************************************************
  109. * FunctionName   : SFTStartFul()
  110. * Description    : 定时器启动扩展函数
  111. * EntryParameter : None
  112. * ReturnValue    : None
  113. ****************************************************************************************************/
  114. void SFTStartFul(SFT_STU *pStu, u8 num, u32 val, void(*pFun)(void), u8 *pOvr, u8 rsl)
  115. {
  116.     pStu[num].CntVal = val;            
  117.     pStu[num].OvrMrk = SFT_STT;
  118.     pStu[num].Result = rsl;
  119.     pStu[num].CmpVal = pOvr;
  120.     pStu[num].ExeFun = pFun;
  121.     pStu[num].TimStu = SFT_OPN;                                             
  122. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:07 编辑 ]
我的博客
点赞  2013-8-12 07:19
模块启动完成后,我们就可以把接收的数据进行解码了。由于GPS每秒发送进400字节(不同模块发数据不同),为了不漏数据,我们把接收缓冲开辟到800字节,保证随时能够接收2帧数据。

  1. /****************************************************************************************************
  2. * FunctionName   : GpsParse()
  3. * Description    : GPS 数据解码
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void GpsParse(void)
  8. {
  9.     if (GpsPar.StaMrk >= GPS_STT_CMP)
  10.         {           
  11.                 if (Gps_AntennaStatus() == GPS_ANT_ABN)
  12.                 {
  13.                     GpsPck.Sta = 'V';
  14.                         Gps_ClearPack(&GpsPck);
  15.                 }
  16.                 else
  17.                 {
  18.                     while (GpsBuf.RdCnt != GpsBuf.WtCnt)
  19.                         {
  20.                                 if (Gps_GetDatFrm(&GpsBuf, &Gps_Frm))                       // 获取帧
  21.                                 {
  22.                                         GPS_FRMPro(&GpsPck, &Gps_Frm);                // 帧处理
  23.                                         Gps_ClearFrmBuf(&Gps_Frm);
  24.                                 }
  25.                         }
  26.                 }
  27.         }
  28. }
GpsPar.StaMrk >= GPS_STT_CMP表示模块启动完成。完成后可以对天线进行判断,天线正常的时候,我们就可以开始解码了,如果天线不正常,就没有必要解码了,没有天线GPS的不可能定位的。


[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:38 编辑 ]
我的博客
点赞  2013-8-12 07:19
只要缓冲区中有数据,我们就循环处理,直到完成数据处理,才退出GPS解码任务。为此我们首先需要获取一帧数据,其函数如下:
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_GetDatFrm()
  3. * Description    : GPS获取数据帧
  4. * EntryParameter : None
  5. * ReturnValue    : 获取一针返回1,否则返回0
  6. ****************************************************************************************************/
  7. u8 Gps_GetDatFrm(DTF_RCV *pRcv, GPS_FRM *pFrm)
  8. {
  9.     u8 reval = 0, tmp;
  10.         u16 i, len;
  11.         static u8 rMark = 0;

  12.         len = DTFGetLen(pRcv);                // 获取未读数据长度

  13.         if (len != 0)                               // 有未处理的数据
  14.         {
  15.             for (i=0; i
  16.                 {
  17.                     tmp = DTFReadByte(pRcv);      // 读取一字节数据
  18.                         if (tmp == 0x24)    // GPS头判断(帖子中无法显示这个符号)
  19.                         {
  20.                                 rMark = 1;
  21.                                 pFrm->Len = 0;
  22.                         }

  23.                         if (rMark == 1)
  24.                         {
  25.                             pFrm->Buf[pFrm->Len++] = tmp;        // 缓存
  26.                                 if (tmp == 0x0A)                                     // 结束
  27.                                 {
  28.                                     rMark = 0;
  29.                                     reval = 1;
  30.                                         break;
  31.                                 }
  32.                                 else
  33.                                 {
  34.                                         if (pFrm->Len > GPS_FRM_SIZE)    // 越界判断,还没有收到0x0D,0x0A结束标志
  35.                                         {
  36.                                             Gps_ClearFrmBuf(pFrm);
  37.                                                 break;
  38.                                         }
  39.                                 }
  40.                         }               
  41.                 }
  42.         }

  43.         return reval;   
  44. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:43 编辑 ]
我的博客
点赞  2013-8-12 07:19
在这个函数中,首先判断是否接收到头,如果是开始读取数据,最后判断是否接收到尾,如果是完成一帧数据读取。GPS接收到的数据均为可以显示的ASC码字符,在数据中,绝对不会是重复出现帧头和帧尾数据的。

    获取一帧数据后,我们需要把这帧数据进行比较,是什么语句就与采用相应函数进行解码:[        DISCUZ_CODE_12        ]在这个函数中,首先判断是否接收到头,如果是开始读取数据,最后判断是否接收到尾,如果是完成一帧数据读取。GPS接收到的数据均为可以显示的ASC码字符,在数据中,绝对不会是重复出现帧头和帧尾数据的。

    获取一帧数据后,我们需要把这帧数据进行比较,是什么语句就与采用相应函数进行解码:

对于比较数组的定义,在本人新书上的菜单部分或本人发的菜单实现贴中已经描述过,定义如下:
  1. GPS_TBL Gps_Tbl[] =
  2. {
  3.         "$GPRMC", Gps_GPRMCParse,//
  4.         "$GPGGA", Gps_GPGGAParse, //
  5.         "$GPGLL", Gps_GPGLLParse, //
  6.         "$GPGSA", Gps_GPGSAParse//
  7.         "$GPGSV", Gps_GPGSVParse,//
  8.         "$GPVTG", Gps_GPVTGParse, //
  9. };

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:43 编辑 ]
我的博客
点赞  2013-8-12 07:19
GPS语句解码的方法很简单,只需要计算逗号,并把两逗号之间的相应数据读取出来即可。
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_GPRMCParse()
  3. * Description    : $GPRMC,085223.136,A,3957.6286,N,11619.2078,E,0.06,36.81,180908,,,A*57
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void Gps_GPRMCParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  8. {
  9.         /*
  10.         字段1:UTC时间,hhmmss.sss格式
  11.         字段2:状态,A=定位,V=未定位
  12.         字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
  13.         字段4:纬度N(北纬)或S(南纬)
  14.         字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
  15.         字段6:经度E(东经)或W(西经)
  16.         字段7:速度,节,Knots
  17.         字段8:方位角,度
  18.         字段9:UTC日期,DDMMYY格式
  19.         字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
  20.         字段11:磁偏角方向,E=东W=西
  21.         字段16:校验值
  22.         */

  23.         u8 *pComma, *pHead;       
  24.         u8 cmmCnt = 0;                                                                                                                        // 逗号计数
  25.    
  26.     pHead = &pFrm->Buf[7];

  27.     while (cmmCnt < 9)                                                                                                                // 此语句有9个逗号
  28.     {
  29.         pComma = (u8 *)(strchr((const char *)pHead, ','));                                        // 寻找","符号位置
  30.         
  31.         if ((pComma != (u8 *)NULL) && (pHead != pComma))
  32.         {
  33.             *pComma++ = 0;                                                                                                                // 清除逗号
  34.             
  35.             switch (cmmCnt)
  36.             {
  37.                 case 0:        Gps_GetTime(&pPck->Tim.Hur, pHead);        break;            // H,M,S                                                                                                                // H,M,S
  38.                                 case 1: pPck->Sta = *pHead;                        break;       // 定位标志
  39.                                 case 2:        Gps_GetLatitude(pPck->Lat, pHead);         break;            // 纬度02232.255
  40.                                 case 3:        pPck->NSLat = *pHead;                      break;       // N,S
  41.                                 case 4:        Gps_GetLongitude(pPck->Lon, pHead);        break;                // 经度11400.296
  42.                                 case 5:        pPck->EWLon = *pHead;                      break;                // E,W
  43.                                 case 6:        Gps_GetSpeed(&pPck->Spd, pHead);           break;       // 速度
  44.                             case 7:        Gps_GetDirection(&pPck->Dir, pHead);       break;                // 方向
  45.                                 case 8:        Gps_GetDat(&pPck->Dat.Yea, pHead);         break;                 // Y,M,D                                       
  46.                                 default: break;
  47.                         }
  48.                 }
  49.                 else
  50.                 {
  51.                         pComma++;
  52.                 }
  53.                
  54.                 pHead = pComma;
  55.                 cmmCnt++;
  56.         }

  57.         Gps_AdjustTime(&pPck->Dat.Yea);                                                                  // UTC-BJT 时间转换       
  58. }
不过需要注意解码数据的存储格式,在不同的应用中,我们对解码数据的存储格式是有区别的。在嵌入式中比较常用的是采用BCD码,因为BCD码比较方便传输。同时为了在不同语句中方便解码调用,我们把实现相同解码部分都提出来编写成相应的函数了。在各个逗号之间直接调用函数接口。

特别需要注意的是时间,通过GPS获取的时间是UTC时间,如果要转换为北京时间必须要进行一系列的转换,而不是简单的加8小时完事,虽然UTC和北京时间只差8个小时,但由于这8个小时的差异可能会导致日期、甚至年的差异。
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_AdjustTime()
  3. * Description    : 实现8小时时差调整
  4. * EntryParameter : time - 年,月,日,时(BCD)
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void Gps_AdjustTime(u8 *time)
  8. {       
  9.         u8 tmp[4];
  10.         const u16 dmonth[]  = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  11.         const u16 ddmonth[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  12.        
  13.         memcpy(tmp, time, 4);                                                                                           // 取4字节
  14.         tmp[0] = ((tmp[0] >> 4) * 10) + (tmp[0] & 0x0F);                                   // BCD转十进制
  15.         tmp[1] = ((tmp[1] >> 4) * 10) + (tmp[1] & 0x0F);
  16.         tmp[2] = ((tmp[2] >> 4) * 10) + (tmp[2] & 0x0F);
  17.         tmp[3] = ((tmp[3] >> 4) * 10) + (tmp[3] & 0x0F);
  18.        
  19.         tmp[3] += 8;                                                                                                  
  20.         if (tmp[3] > 23)                                                                                               // 时间加8
  21.         {
  22.                 tmp[3] -= 24;                                                                                                   // 大于24小时,天加一
  23.                 tmp[2]++;
  24.                 if (tmp[0] % 4 != 0)                                                                                   // 闰年
  25.                 {
  26.                         if (tmp[2] > dmonth[tmp[1]])
  27.                         {
  28.                                 tmp[2] = 1;
  29.                                 tmp[1]++;
  30.                                 if (tmp[1] > 12)
  31.                                 {
  32.                                         tmp[1] = 1;
  33.                                         tmp[0]++;
  34.                                 }
  35.                         }
  36.                 }
  37.                 else
  38.                 {
  39.                         if (tmp[2] > ddmonth[tmp[1]])                                                           // 不闰年
  40.                         {
  41.                                 tmp[2] = 1;
  42.                                 tmp[1] ++;
  43.                                 if (tmp[1] > 12)
  44.                                 {
  45.                                         tmp[1] = 1;
  46.                                         tmp[0]++;
  47.                                 }
  48.                         }
  49.                 }
  50.         }

  51.         tmp[0] = ((tmp[0]/10)<<4) + (tmp[0]%10);                                                   // 十进制转BCD
  52.         tmp[1] = ((tmp[1]/10)<<4) + (tmp[1]%10);
  53.         tmp[2] = ((tmp[2]/10)<<4) + (tmp[2]%10);
  54.         tmp[3] = ((tmp[3]/10)<<4) + (tmp[3]%10);
  55.         memcpy(time, tmp, 4);                                                                                           // 拷贝
  56. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:50 编辑 ]
我的博客
点赞  2013-8-12 07:19
GPS的解码函数比较多,我们这里只应用了一部分:
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_GetTime()
  3. * Description    : 获取时间
  4. * EntryParameter : pTim - 转换为BCD码,pStr - 需要转换的字符串
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void Gps_GetTime(u8 *pTim, u8 *pStr)
  8. {
  9.     *(pTim+0) = ((*(pStr+0)-'0')<<4) + (*(pStr+1)-'0');                         // HH
  10.     *(pTim+1) = ((*(pStr+2)-'0')<<4) + (*(pStr+3)-'0');                         // MM
  11.     *(pTim+2) = ((*(pStr+4)-'0')<<4) + (*(pStr+5)-'0');                         // SS
  12. }

  13. /****************************************************************************************************
  14. * FunctionName   : Gps_GetDat()
  15. * Description    : 获取日期
  16. * EntryParameter : pTim - 转换为BCD码,pStr - 需要转换的字符串
  17. * ReturnValue    : None
  18. ****************************************************************************************************/
  19. void Gps_GetDat(u8 *pTim, u8 *pStr)
  20. {
  21.     *(pTim+2) = ((*(pStr+0)-'0')<<4) + (*(pStr+1)-'0');                         // YY
  22.     *(pTim+1) = ((*(pStr+2)-'0')<<4) + (*(pStr+3)-'0');                         // MM
  23.     *(pTim+0) = ((*(pStr+4)-'0')<<4) + (*(pStr+5)-'0');                         // DD
  24. }

  25. /****************************************************************************************************
  26. * FunctionName   : Gps_GetSpeed()
  27. * Description    : 获取速度
  28. * EntryParameter : pSp - 转换整形速度,pStr - 需要转换的字符串
  29. * ReturnValue    : None
  30. ****************************************************************************************************/
  31. void Gps_GetSpeed(u8 *pSp, u8 *pStr)
  32. {
  33.     if (*pStr == ',')
  34.     {
  35.         return ;
  36.     }
  37.         
  38.     *pSp = (u8)((atof((const char *)pStr)*10*5.15+0.5) / 100*3.6);

  39.     if (*pSp < 3)                                                                  // 解决静态速度漂移,不超过3km/h就置为0
  40.     {
  41.         *pSp = 0;
  42.     }
  43. }

  44. /****************************************************************************************************
  45. * FunctionName   : Gps_GetLatitude()
  46. * Description    : 获取纬度(xxx°xx.xxx)
  47. * EntryParameter : pLat - 4字节BCD码,pStr - 需要转换的字符串
  48. * ReturnValue    : None
  49. ****************************************************************************************************/
  50. void Gps_GetLatitude(u8 *pLat, u8 *pStr)
  51. {
  52.     *(pLat+0) = ((0 << 4)             + (*(pStr+0)-'0'));
  53.     *(pLat+1) = (((*(pStr+1)-'0')<<4) + (*(pStr+2)-'0'));
  54.     *(pLat+2) = (((*(pStr+3)-'0')<<4) + (*(pStr+5)-'0'));
  55.     *(pLat+3) = (((*(pStr+6)-'0')<<4) + (*(pStr+7)-'0'));
  56. }

  57. /****************************************************************************************************
  58. * FunctionName   : Gps_GetLongitude()
  59. * Description    : 获取经度(xxx°xx.xxx)
  60. * EntryParameter : pLng - 4字节BCD码,pStr - 需要转换的字符串
  61. * ReturnValue    : None
  62. ****************************************************************************************************/
  63. void Gps_GetLongitude(u8 *pLng, u8 *pStr)
  64. {   
  65.     *(pLng+0) = (((*(pStr+0)-'0')<<4) + (*(pStr+1)-'0'));
  66.     *(pLng+1) = (((*(pStr+2)-'0')<<4) + (*(pStr+3)-'0'));
  67.     *(pLng+2) = (((*(pStr+4)-'0')<<4) + (*(pStr+6)-'0'));
  68.     *(pLng+3) = (((*(pStr+7)-'0')<<4) + (*(pStr+8)-'0'));   
  69. }

  70. /****************************************************************************************************
  71. * FunctionName   : Gps_GetDirection()
  72. * Description    : 获取方向
  73. * EntryParameter : pDir - 1字节(单位2dec),pStr - 需要转换的字符串
  74. * ReturnValue    : None
  75. ****************************************************************************************************/
  76. void Gps_GetDirection(u8 *pDir, u8 *pStr)
  77. {   
  78.     if (*pStr == ',')
  79.     {
  80.         return ;
  81.     }
  82.    
  83.     *pDir = 0;
  84.     while (*pStr != '\0')
  85.     {
  86.         if (*pStr != '.')
  87.         {
  88.             *pDir += (*pStr - '0');
  89.             *pDir*= 10;
  90.         }
  91.         else
  92.         {
  93.             *pDir += (*(pStr + 1) - '0');
  94.             break;
  95.         }
  96.         pStr++;
  97.     }
  98.    
  99.     *pDir /= 2;                                                                        // 单位2dec  
  100. }  

  101. /****************************************************************************************************
  102. * FunctionName   : Gps_SateNum()
  103. * Description    : 卫星数
  104. * EntryParameter : pSat - 卫星数(00~12),pStr - 需要转换的字符串
  105. * ReturnValue    : None
  106. ****************************************************************************************************/
  107. void Gps_SateNum(u8 *pSat, u8 *pStr)
  108. {
  109.     *pSat = (*(pStr+1) != '\0') ? (*(pStr+0)-'0') * 10 + (*(pStr+1)-'0') : (*(pStr+0)-'0');     
  110. }

  111. /****************************************************************************************************
  112. * FunctionName   : Gps_LevelFactor()
  113. * Description    : 水平因子
  114. * EntryParameter : pFac - 水平因子(0.5 - 99.9),pStr - 需要转换的字符串
  115. * ReturnValue    : None
  116. ****************************************************************************************************/
  117. void Gps_LevelFactor(u8 *pFac, u8 *pStr)
  118. {
  119.     u8 i;

  120.     for (i=0; i<2; i++)
  121.         {
  122.             if (*(pStr+i) == '.')                                                                    // 查询小数点位置
  123.                 {
  124.                     break;
  125.                 }
  126.         }

  127.         switch (i)

  128.         {
  129.             case 1:
  130.                 {
  131.                     *(pFac+0) = 0x00;
  132.                         *(pFac+1) = ((*(pStr+0) - '0') << 4) + *(pStr+2) - '0';
  133.                         break;  
  134.                 }

  135.             case 2:
  136.                 {
  137.                     *(pFac+0) = *(pStr+0) - '0';
  138.                         *(pFac+1) = ((*(pStr+1) - '0') << 4) + *(pStr+3) - '0';
  139.                         break;  
  140.                 }

  141.                 default: break;
  142.         }
  143. }

  144. /****************************************************************************************************
  145. * FunctionName   : Gps_Elevation()
  146. * Description    : 海拔
  147. * EntryParameter : Gps_Elevation - 海拔(-9999.9 - 99999.9),pStr - 需要转换的字符串
  148. * ReturnValue    : None
  149. ****************************************************************************************************/
  150. void Gps_Elevation(u8 *pEle, u8 *pStr)
  151. {
  152.     u8 i;

  153.         for (i=0; i<6; i++)
  154.         {
  155.             if (*(pStr+i) == '.')                                                                    // 查询小数点位置
  156.                 {
  157.                     break;
  158.                 }
  159.         }
  160.        
  161.         if (*pStr == '-')                                                                                     // 符号位(负数时,最高位为'F')
  162.         {
  163.             *(pEle+0) = 0xF0;
  164.         }
  165.        
  166.         switch (i)
  167.         {
  168.             case 1:
  169.                 {
  170.                     *(pEle+0) =        0x00;
  171.                     *(pEle+1) = 0x00;
  172.                     *(pEle+2) = ((*(pStr+0) - '0') << 4) + (*(pStr+2) - '0');
  173.                     break;
  174.                 }
  175.        
  176.                 case 2:
  177.                 {
  178.                     *(pEle+0) =        0x00;
  179.                     *(pEle+1) = (*(pStr+0) - '0');
  180.                     *(pEle+2) = ((*(pStr+1) - '0') << 4) + (*(pStr+3) - '0');
  181.                     break;
  182.                 }
  183.        
  184.                 case 3:
  185.                 {
  186.                     *(pEle+0) =        0x00;
  187.                     *(pEle+1) = ((*(pStr+0) - '0') << 4) + (*(pStr+1) - '0');
  188.                     *(pEle+2) = ((*(pStr+2) - '0') << 4) + (*(pStr+4) - '0');
  189.                     break;
  190.                 }
  191.        
  192.                 case 4:
  193.                 {
  194.                     *(pEle+0) = (*(pStr+0) - '0');
  195.                     *(pEle+1) = ((*(pStr+1) - '0') << 4) + (*(pStr+2) - '0');
  196.                     *(pEle+2) = ((*(pStr+3) - '0') << 4) + (*(pStr+5) - '0');
  197.                     break;
  198.                 }
  199.        
  200.                 case 5:
  201.                 {
  202.                     *(pEle+0) = ((*(pStr+0) - '0') << 4) + (*(pStr+1) - '0');
  203.                     *(pEle+1) = ((*(pStr+2) - '0') << 4) + (*(pStr+3) - '0');
  204.                     *(pEle+2) = ((*(pStr+4) - '0') << 4) + (*(pStr+6) - '0');
  205.                     break;
  206.                 }

  207.                 default: break;
  208.         }
  209. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:52 编辑 ]
我的博客
点赞  2013-8-12 07:19
为了方便使用GPS解码数据,我们把GPS的解码数据都放入一个数据包中,其定义:
  1. typedef struct
  2. {
  3.         u8 Yea;     // 年
  4.         u8 Mon;    // 月
  5.         u8 Day;    // 日

  6. } GPS_DAT;      // 日期

  7. //-----------------------------------------------------------------------------------------------------
  8. typedef struct
  9. {                                                                                                                          
  10.         u8 Hur;    // 时
  11.         u8 Min;    // 分
  12.         u8 Sec;   // 秒

  13. } GPS_TIM;     // 时间

  14. //-----------------------------------------------------------------------------------------------------
  15. typedef struct
  16. {
  17.         GPS_DAT Dat;      // 日期
  18.         GPS_TIM Tim;      // 时间

  19.         u8  Lon[4];           // 经度xxx°xx.xxx
  20.         u8  Lat[4];           // 纬度xxx°xx.xxx
  21.         u8  Spd;              // 速度0.519
  22.         u8  Dir;                // 方向2dec
  23.         u8  Hgt[2];         // 高度
  24.         u8  Mlg[4];          // 里程(0.1km,BCD)

  25.         u8  Sta;                // 定位状态,A=有效定位,V=无效定位
  26.         u8  EWLon;           // E或W(东经或西经)
  27.         u8  NSLat;             // N或S(北纬或南纬)
  28.         u8  SateNum;         // 卫星数(00~12)
  29.         u8  LvlAcc[2];        // 水平精确度(0.5~99.9)
  30.         u8  Ele[3];              // 海拔高度(-9999.9 - 99999.9最高位大于9为负数)

  31. } GPS_PCK;

[ 本帖最后由 zhaojun_xf 于 2013-8-13 06:58 编辑 ]
我的博客
点赞  2013-8-12 07:20
这里只列出了一条语句的解码函数,其他语句的解码其实都是差不多的,不过很少使用。
  1. /****************************************************************************************************
  2. * FunctionName   : Gps_GPGGAParse()
  3. * Description    : $GPGGA,085223.136,3957.6286,N,11619.2078,E,1,03,4.0,6.5,M,-6.5,M,0.0,0000*63
  4. * EntryParameter : None
  5. * ReturnValue    : None
  6. ****************************************************************************************************/
  7. void Gps_GPGGAParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  8. {
  9.     /*
  10.         字段1:UTC 时间,hhmmss.sss,时分秒格式
  11.         字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
  12.         字段3:纬度N(北纬)或S(南纬)
  13.         字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0)
  14.         字段5:经度E(东经)或W(西经)
  15.         字段6:GPS状态,0=未定位,1=非差分定位,2=差分定位,3=无效PPS,6=正在估算
  16.         字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0)
  17.         字段8:HDOP水平精度因子(0.5 - 99.9)
  18.         字段9:海拔高度(-9999.9 - 99999.9)
  19.         字段10:地球椭球面相对大地水准面的高度
  20.         字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空)
  21.         字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)
  22.         字段13:校验值
  23.     */
  24.        
  25.         u8 cmmCnt = 0;                                                                                                                        // 逗号计数
  26.     u8 *pComma, *pHead;

  27.     pHead = &pFrm->Buf[7];

  28.     while (cmmCnt < 9)                                                                                                                // 此语句有9个逗号
  29.     {
  30.         pComma = (u8 *)(strchr((const char *)pHead, ','));                                        // 寻找","符号位置
  31.         
  32.         if ((pComma != (u8 *)NULL) && (pHead != pComma))
  33.         {
  34.             *pComma++ = 0;
  35.             
  36.             switch (cmmCnt)
  37.             {
  38.                 case 0:        break;                                                                                                    // 纬度ddmm.mmmm,度分格式(前导位数不足则补0)  
  39.                                 case 1:        break;                                                                                                    // 纬度N(北纬)或S(南纬)
  40.                                 case 2: break;                                                  // 纬度N(北纬)或S(南纬)
  41.                                 case 3:        break;                                                                                // 经度dddmm.mmmm,度分格式(前导位数不足则补0)
  42.                                 case 4:        break;                                                  // 经度E(东经)或W(西经)
  43.                                 case 5:        break;                                                                                                        // GPS状态,0=未定位,1=非差分定位,2=差分定位,3=无效PPS,6=正在估算
  44.                                 case 6:        Gps_SateNum(&pPck->SateNum, pHead);    break;                        // 正在使用的卫星数量(00 - 12)(前导位数不足则补0)
  45.                                 case 7:        Gps_LevelFactor(pPck->LvlAcc, pHead);  break;                        // HDOP水平精度因子(0.5 - 99.9)
  46.                                 case 8:        Gps_Elevation(pPck->Ele, pHead);       break;                    // 海拔高度(-9999.9 - 99999.9)                                       
  47.                                 default: break;
  48.                         }
  49.                 }
  50.                 else
  51.                 {
  52.                         pComma++;
  53.                 }
  54.                
  55.                 pHead = pComma;
  56.                 cmmCnt++;
  57.         }
  58. }

  59. /***************************************************************************************************
  60. * FunctionName   : Gps_GPGLLParse()
  61. * Description    : $GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D
  62. * EntryParameter : None
  63. * ReturnValue    : None
  64. ****************************************************************************************************/
  65. void Gps_GPGLLParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  66. {
  67.     /*
  68.         字段1:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
  69.         字段2:纬度N(北纬)或S(南纬)
  70.         字段3:经度dddmm.mmmm,度分格式(前导位数不足则补0)
  71.         字段4:经度E(东经)或W(西经)
  72.         字段5:UTC时间,hhmmss.sss格式
  73.         字段6:状态,A=定位,V=未定位
  74.         字段7:校验值
  75.     */

  76.         return ;
  77. }

  78. /****************************************************************************************************
  79. * FunctionName   : Gps_GPGSAParse()
  80. * Description    : $GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A
  81. * EntryParameter : None
  82. * ReturnValue    : None
  83. ****************************************************************************************************/
  84. void Gps_GPGSAParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  85. {
  86.         /*
  87.         字段 1:定位模式,A=自动手动2D/3D,M=手动2D/3D
  88.         字段 2:定位类型,1=未定位,2=2D定位,3=3D定位
  89.         字段 3:PRN码(伪随机噪声码),第 1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  90.         字段 4:PRN码(伪随机噪声码),第 2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  91.         字段 5:PRN码(伪随机噪声码),第 3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  92.         字段 6:PRN码(伪随机噪声码),第 4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  93.         字段 7:PRN码(伪随机噪声码),第 5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  94.         字段 8:PRN码(伪随机噪声码),第 6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  95.         字段 9:PRN码(伪随机噪声码),第 7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  96.         字段10:PRN码(伪随机噪声码),第 8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  97.         字段11:PRN码(伪随机噪声码),第 9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  98.         字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  99.         字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  100.         字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)
  101.         字段15:PDOP综合位置精度因子(0.5 - 99.9)
  102.         字段16:HDOP水平精度因子(0.5 - 99.9)
  103.         字段17:VDOP垂直精度因子(0.5 - 99.9)
  104.         字段18:校验值
  105.         */

  106.         return ;
  107. }

  108. /****************************************************************************************************
  109. * FunctionName   : Gps_GPGSVParse()
  110. * Description    : $GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70
  111. * EntryParameter : None
  112. * ReturnValue    : None
  113. ****************************************************************************************************/
  114. void Gps_GPGSVParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  115. {
  116.         /*
  117.         字段 1:本次GSV语句的总数目(1 - 3)
  118.         字段 2:本条GSV语句是本次GSV语句的第几条(1 - 3)
  119.         字段 3:当前可见卫星总数(00 - 12)(前导位数不足则补0)
  120.         字段 4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
  121.         字段 5:卫星仰角(00 - 90)度(前导位数不足则补0)
  122.         字段 6:卫星方位角(00 - 359)度(前导位数不足则补0)
  123.         字段 7:信噪比(00-99)dbHz
  124.         字段 8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
  125.         字段 9:卫星仰角(00 - 90)度(前导位数不足则补0)
  126.         字段10:卫星方位角(00 - 359)度(前导位数不足则补0)
  127.         字段11:信噪比(00-99)dbHz
  128.         字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)
  129.         字段13:卫星仰角(00 - 90)度(前导位数不足则补0)
  130.         字段14:卫星方位角(00 - 359)度(前导位数不足则补0)
  131.         字段15:信噪比(00-99)dbHz
  132.         字段16:校验值     
  133.         */

  134.         return ;
  135. }

  136. /****************************************************************************************************
  137. * FunctionName   : Gps_GPVTGParse()
  138. * Description    : $GPVTG,89.68,T,,M,0.00,N,0.0,K*5F
  139. * EntryParameter : None
  140. * ReturnValue    : None
  141. ****************************************************************************************************/
  142. void Gps_GPVTGParse(GPS_PCK *pPck, GPS_FRM *pFrm)
  143. {
  144.         /*
  145.         字段1:运动角度,000 - 359,(前导位数不足则补0)
  146.         字段2:T=真北参照系
  147.         字段3:运动角度,000 - 359,(前导位数不足则补0)
  148.         字段4:M=磁北参照系
  149.         字段5:水平运动速度(0.00)(前导位数不足则补0)
  150.         字段6:N=节,Knots
  151.         字段7:水平运动速度(0.00)(前导位数不足则补0)
  152.         字段8:K=公里/时,km/h
  153.         字段9:校验值
  154.         */

  155.         return ;
  156. }

[ 本帖最后由 zhaojun_xf 于 2013-8-13 07:00 编辑 ]
我的博客
点赞  2013-8-12 07:20
学习~~
http://weibo.com/u/1391449055
点赞  2013-8-12 10:09
点赞  2013-8-12 11:08
点赞  2013-8-12 12:45
很好,代码很工整,我觉得楼主的书一定很不错,给那些工程师很好的参考。
GPS 这个部分知识解析出来,但是你们在裸机上怎么用呢?因为这个需要地图的啊
如果再用裸机开发地图,或者ucos 之类的开发,那估计真的不容易哦。比用wince和android还难,因为wince的app 和驱动开发可以分开开发了。
如果对linux,Android,wince 等嵌入式底层有兴趣的,请加这个QQ群吧,群号:27100460
点赞  2013-8-13 11:35
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复