GPS-NMEA解析代码

程序的基本原理:GPS设备的NMEA语句是逐条发送的,每条语句都是以0x0D和0x0A来结束的。程序开放256字节的接收缓冲区,当接收到0x0D字节时开始进行NMEA语句的校验和验证与数据解析。首先查找该语句的每个参数之间的逗号分隔符,将分隔符的位置作记录下来并替换为0x00,再依据不同的语句定义将不同参数的数据指针提取出来。因为事先已经将分隔符替换为0x00,所以数据指针结束时不会溢出到其他参数中去。最后通过字符串的复制或字符串的转换,将各语句的参数提取出来并放置在相应的数据结构单元中去,最终完成解析运算。

    实验证明,用STM32在8M的速率下,GPS以4800的波特率,处理完一条语句后,后面的NMEA输出的0x0D还没有接收完成。程序的难点没什么,只是多用一些C语言的系统函数来完成复制和字符串转换,处理字符串时的尽量越少越短越好,可以说基本上是实时处理的。



  1. extern struct _GPS_Real_buf  
  2. {  
  3.     char data[256];                             //定义GPS输入缓冲区  
  4.     volatile unsigned short rx_pc;    //接收指针  
  5. } GPS_Real_buf; //GPS接收数据缓冲区  
  6.   
  7.   
  8. extern struct _GPS_Information  
  9. {  
  10.     unsigned char Real_Locate;              //实时定位有效位  
  11.     unsigned char Located;                      //定位有效位  
  12.     unsigned char Locate_Mode;           //定位模式,2D或3D  
  13.     char UTC_Time[7];                                //时间  
  14.     char UTC_Date[7];                               //日期  
  15.     char Latitude[10];                               //纬度  
  16.     char NS_Indicator;                               //N=北半球,S=南半球  
  17.     char Longitude[11];                          //经度  
  18.     char EW_Indicator;                              //E=东经,W=西经  
  19.     double Speed;                                       //地面速率  
  20.     double Course;                                      //地面航向  
  21.     double PDOP;                                         //位置精度  
  22.     double HDOP;                                         //水平精度  
  23.     double VDOP;                                         //垂直精度  
  24.     double MSL_Altitude;                         //MSL海拔高度  
  25.     unsigned char Use_EPH_Sum;       //使用的卫星数量  
  26.     unsigned char User_EPH[12];         //当前搜索到的卫星编号  
  27.     unsigned short EPH_State[12][4]; //当前使用的12颗卫星的编号、仰角、方位角、信噪比  
  28. } GPS_Information; //GPS信息  
  29. /******************************************************************************************************** 
  30. **函数信息 :void USART2_IRQHandler(void)  
  31. **功能描述 :UART2中断服务函数 
  32. **输入参数 :无 
  33. **输出参数 :无 
  34. ********************************************************************************************************/  
  35. void USART2_IRQHandler( void ) //串口2中断服务程序  
  36. {  
  37.     unsigned char Recv;  
  38.     if ( USART_GetITStatus( USART2, USART_IT_RXNE ) != RESET ) //接收中断  
  39.     {  
  40.         Recv = USART_ReceiveData( USART2 );          //接收数据  
  41.         if ( Recv == '$' )  
  42.         {  
  43.             GPS_Real_buf.rx_pc = 0;  
  44.         }  
  45.         else  
  46.         {  
  47.             if ( GPS_Real_buf.rx_pc < sizeof( GPS_Real_buf.data ) - 1 )  
  48.             {  
  49.                 GPS_Real_buf.rx_pc++;  
  50.             }  
  51.         }  
  52.         GPS_Real_buf.data[GPS_Real_buf.rx_pc] = Recv;  
  53.         if ( Recv == '\r' )    //当接收数据为0x0D时开始处理GPS数据  
  54.         {  
  55.             if ( Real_Process_Enabled == Valid )  
  56.             {  
  57.                 if ( Calc_GPS_Sum( GPS_Real_buf.data ) == Valid )  
  58.                 {  
  59.                     Creat_DH_Index( GPS_Real_buf.data );  
  60.                     Real_GPS_Command_Process();  
  61.                 }  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     if ( USART_GetFlagStatus( USART2, USART_FLAG_ORE ) == SET ) //溢出中断  
  67.     {  
  68.         USART_ClearFlag( USART2, USART_FLAG_ORE );   //清溢出位  
  69.         USART_ReceiveData( USART2 );                                //读DR  
  70.     }  
  71. }  
  72.   
  73.   
  74. /******************************************************************************************************** 
  75. **函数信息 :void Creat_DH_Index( char* buffer ) 
  76. **功能描述 :寻找所有逗号的位置,创建索引 
  77. **输入参数 :接收GPS数据的缓冲区 
  78. **输出参数 :创建全局变量数组中的逗号索引,原GPS数据中的逗号将会被0x00替代 
  79. ********************************************************************************************************/  
  80. unsigned char DH_id_sep[32];//全局变量数组,最多处理32个逗号索引  
  81. void Creat_DH_Index( char* buffer )  
  82. {  
  83.     unsigned short i, len;  
  84.     unsigned char idj;  
  85.   
  86.     memset( DH_id_sep, 0, sizeof( DH_id_sep ) );  
  87.     len = strlen( buffer );  
  88.     for ( i = 0, idj = 0; i < len; i++ )  
  89.     {  
  90.         if ( buffer[i] == ',' )  
  91.         {  
  92.             DH_id_sep[idj] = i;  
  93.             idj++;  
  94.             buffer[i] = 0x00;  
  95.         }  
  96.     }  
  97. }  
  98.   
  99. /******************************************************************************************************** 
  100. **函数信息 :char* Real_Process_DH( char* buffer, unsigned char num ) 
  101. **功能描述 :查找GPS数据第N个参数的偏移 
  102. **输入参数 :创建索引后的接收GPS数据缓冲区 
  103. **输出参数 :返回第N个","之后的信息,需要*buffer有效并创建索引后才可以执行 
  104. ********************************************************************************************************/  
  105. char* Real_Process_DH( char* buffer, unsigned char num )  
  106. {  
  107.     if ( num < 1 )  
  108.         return  &buffer[0];  
  109.     return  &buffer[ DH_id_sep[num - 1] + 1];  
  110. }  
  111.   
  112.   
  113. /******************************************************************************************************** 
  114. **函数信息 :void Real_GPS_Command_Process( void ) 
  115. **功能描述 :处理做好参数索引的数据并填入GPS数据结构中 
  116. **输入参数 : 
  117. **输出参数 : 
  118. ********************************************************************************************************/  
  119. void Real_GPS_Command_Process( void )  
  120. {  
  121.     char* temp;  
  122.     unsigned char i, j, zhen;  
  123.   
  124.     if ( strstr( GPS_Real_buf.data, "GPGGA" ) )//$GPGGA,112118.000,3743.5044,N,11540.5393,E,1,06,1.6,15.3,M,-9.1,M,,0000*7E  
  125.     {  
  126.         GPS_Information.Use_EPH_Sum = atof( Real_Process_DH( GPS_Real_buf.data, 7 ) ); //第7个参数为卫星使用数量  
  127.         GPS_Information.MSL_Altitude = atof( Real_Process_DH( GPS_Real_buf.data, 9 ) ); //第9个参数为海拔高度  
  128.         return;  
  129.     }  
  130.   
  131.     if ( strstr( GPS_Real_buf.data, "GPGSA" ) )  //$GPGSA,A,3,28,17,11,09,08,07,,,,,,,3.4,1.6,3.0*3B  
  132.     {  
  133.         temp = Real_Process_DH( GPS_Real_buf.data, 2 ); //第2个参数为定位模式  
  134.         if ( ( *temp == '2' ) || ( *temp == '3' ) )  
  135.             GPS_Information.Locate_Mode = *temp;  
  136.         else  
  137.             GPS_Information.Locate_Mode = Invalid;  
  138.         for ( i = 0; i < 12; i++ ) //总共最多为12颗星  
  139.         {  
  140.             GPS_Information.User_EPH[i] = atof( Real_Process_DH( GPS_Real_buf.data, i + 3 ) ); //从第3个参数开始为所使用的卫星编号  
  141.         }  
  142.       
  143.         GPS_Information.PDOP = atof( Real_Process_DH( GPS_Real_buf.data, 15 ) ); //第15个参数为位置精度  
  144.         GPS_Information.HDOP = atof( Real_Process_DH( GPS_Real_buf.data, 16 ) ); //第16个参数为水平精度  
  145.         GPS_Information.VDOP = atof( Real_Process_DH( GPS_Real_buf.data, 17 ) ); //第17个参数为垂直精度  
  146.       
  147.         return;  
  148.     }  
  149.   
  150.     if ( strstr( GPS_Real_buf.data, "GPRMC" ) )//$GPRMC,112118.000,A,3743.5044,N,11540.5393,E,0.25,198.81,130613,,,A*67  
  151.     {  
  152.         temp = Real_Process_DH( GPS_Real_buf.data, 1 ); //第1个参数为时间  
  153.         if ( *temp != 0 )  
  154.             memcpy( GPS_Information.UTC_Time, temp, 6 );  
  155.   
  156.         if ( *( Real_Process_DH( GPS_Real_buf.data, 2 ) ) == 'A' ) //第2个参数  
  157.         {  
  158.             GPS_Information.Real_Locate = Valid; //实时数据有效  
  159.             GPS_Information.Located = Valid;  
  160.         }  
  161.         else  
  162.         {  
  163.             GPS_Information.Real_Locate = Invalid;  //实时数据无效  
  164.         }  
  165.       
  166.         temp = Real_Process_DH( GPS_Real_buf.data, 3 ); //第3个参数为纬度  
  167.         if ( ( *temp >= 0x31 ) && ( *temp <= 0x39 ) )  
  168.         {  
  169.             memcpy( GPS_Information.Latitude, temp, 9 );  
  170.             GPS_Information.Latitude[9] = 0;  
  171.         }  
  172.         else  
  173.         {  
  174.             GPS_Information.Latitude[0] = '0';  
  175.             GPS_Information.Latitude[1] = 0;  
  176.         }  
  177.   
  178.         GPS_Information.NS_Indicator = *( Real_Process_DH( GPS_Real_buf.data, 4 ) ); //第4个参数为南北  
  179.       
  180.         temp = Real_Process_DH( GPS_Real_buf.data, 5 ); //第5个参数为经度  
  181.         if ( ( *temp >= 0x31 ) && ( *temp <= 0x39 ) )  
  182.         {  
  183.             memcpy( GPS_Information.Longitude, temp, 10 );  
  184.             GPS_Information.Longitude[10] = 0;  
  185.         }  
  186.         else  
  187.         {  
  188.             GPS_Information.Longitude[0] = '0';  
  189.             GPS_Information.Longitude[1] = 0;  
  190.         }  
  191.       
  192.         GPS_Information.EW_Indicator = *( Real_Process_DH( GPS_Real_buf.data, 6 ) ); //第6个参数为东西  
  193.       
  194.         GPS_Information.Speed = atof( Real_Process_DH( GPS_Real_buf.data, 7 ) ); //第7个参数为速度  
  195.       
  196.         GPS_Information.Course = atof( Real_Process_DH( GPS_Real_buf.data, 8 ) ); //第8个参数为航向  
  197.       
  198.         temp = Real_Process_DH( GPS_Real_buf.data, 9 ); //第9个参数为日期  
  199.         if ( *temp != 0 )  
  200.         {  
  201.             memcpy( GPS_Information.UTC_Date, temp, 6 );  
  202.         }  
  203.       
  204.         return;  
  205.     }  
  206.   
  207.     if ( strstr( GPS_Real_buf.data, "GPGSV" ) )//$GPGSV,3,1,11,28,73,321,32,17,39,289,43,11,38,053,17,09,37,250,41*78  
  208.     {  
  209.         zhen = atof( Real_Process_DH( GPS_Real_buf.data, 2 ) ); //取当前帧号  
  210.         if ( ( zhen <= 3 ) && ( zhen != 0 ) )  
  211.         {  
  212.             for ( i = ( zhen - 1 ) * 4, j = 4; i < zhen * 4; i++ )  
  213.             {  
  214.                 GPS_Information.EPH_State[i][0] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取星号  
  215.                 GPS_Information.EPH_State[i][1] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取仰角  
  216.                 GPS_Information.EPH_State[i][2] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取方位角  
  217.                 GPS_Information.EPH_State[i][3] = atof( Real_Process_DH( GPS_Real_buf.data, j++ ) ); //取信噪比  
  218.             }  
  219.         }  
  220.         return;  
  221.     }  
  222. }  
  223.   
  224. /******************************************************************************************************** 
  225. **函数信息 :unsigned char Calc_GPS_Sum( const char* Buffer ) 
  226. **功能描述 :计算GPS的校验和 
  227. **输入参数 :接收完成的GPS数据 
  228. **输出参数 : 
  229. ********************************************************************************************************/  
  230. #include <ctype.h>  
  231. unsigned char gps_sum = 0;  
  232. unsigned char Calc_GPS_Sum( const char* Buffer )  
  233. {  
  234.     unsigned char i, j, k, sum;  
  235.   
  236.     sum = 0;  
  237.   
  238.     for ( i = 1; i < 255; i++ ) //i从1开始是闪过$开始符  
  239.     {  
  240.         if ( ( Buffer[i] != '*' ) && ( Buffer[i] != 0x00 ) ) //判断结束符  
  241.         {  
  242.             sum ^= Buffer[i];//GPS校验和算法为XOR  
  243.         }  
  244.         else  
  245.         {  
  246.             break;  
  247.         }  
  248.     }  
  249.     j = Buffer[i + 1];//取结束符后两位字符  
  250.     k = Buffer[i + 2];  
  251.   
  252.     if ( isalpha( j ) ) //判断字符是否为英文字母,为英文字母时返回非零值,否则返回零  
  253.     {  
  254.         if ( isupper( j ) ) //判断字符为大写英文字母时,返回非零值,否则返回零  
  255.         {  
  256.             j -= 0x37;//强制转换为16进制  
  257.         }  
  258.         else  
  259.         {  
  260.             j -= 0x57;//强制转换为16进制  
  261.         }  
  262.     }  
  263.     else  
  264.     {  
  265.         if ( ( j >= 0x30 ) && ( j <= 0x39 ) )  
  266.         {  
  267.             j -= 0x30;//强制转换为16进制  
  268.         }  
  269.     }  
  270.   
  271.     if ( isalpha( k ) ) //判断字符是否为英文字母,为英文字母时返回非零值,否则返回零  
  272.     {  
  273.         if ( isupper( k ) ) //判断字符为大写英文字母时,返回非零值,否则返回零  
  274.         {  
  275.             k -= 0x37;//强制转换为16进制  
  276.         }  
  277.         else  
  278.         {  
  279.             k -= 0x57;//强制转换为16进制  
  280.         }  
  281.     }  
  282.     else  
  283.     {  
  284.         if ( ( k >= 0x30 ) && ( k <= 0x39 ) )  
  285.         {  
  286.             k -= 0x30;//强制转换为16进制  
  287.         }  
  288.     }  
  289.   
  290.     j = ( j << 4 ) + k; //强制合并为16进制  
  291.     gps_sum = j;  
  292.   
  293.     if ( sum == j )  
  294.     {  
  295.         return Valid; //校验和正常  
  296.     }  
  297.     else  
  298.     {  
  299.         return Invalid; //校验和错误  
  300.     }  


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值