GPS的NMEA数据解析

NMEA是一套定义接收机输出的标准信息,有几种不同的格式,每种都是独立相关的ASCII格式,逗点隔开数据流,数据流长度从30-100字符不 等,通常以每秒间隔选择输出,最常用的格式为"GGA",它包含了定位时间,纬度,经度,高度,定位所用的卫星数,其他的有速度,跟踪,日期等。

        NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等,说明如下:

$GPGGA(定位信息)
eg:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F 
$GPGSA(当前卫星信息)
eg:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A 
$GPGSV(可见卫星信息)
eg:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70 
$GPVTG(地面速度信息)
eg:$GPVTG,89.68,T,,M,0.00,N,0.0,K*5F 
$GPGLL(地理定位信息)
$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D

        以下以代码段来说明$GPGGA的解析过程,其他类推。假设已从串口读到字符串。

(1)结构体信息

[cpp]  view plain copy
  1. typedef struct{  
  2.     int year;    
  3.     int month;   
  4.     int day;  
  5.     int hour;  
  6.     int minute;  
  7.     int second;  
  8. }date_time;  
  9.   
  10. typedef struct{  
  11.      date_time D;//时间  
  12.      char status;       //接收状态  
  13.      double latitude;   //纬度  
  14.      double longitude;  //经度  
  15.      char NS;           //南北极  
  16.      char EW;           //东西  
  17.      double speed;      //速度  
  18.      double high;       //高度  
  19. }GPS_INFO;  

(2)得到指定序号的逗号位置,以解析各个定义段

[cpp]  view plain copy
  1. static int GetComma(int num,char *str)  
  2. {  
  3.     int i,j=0;  
  4.     int len=strlen(str);  
  5.     for(i=0;i<len;i++)  
  6.     {  
  7.         if(str[i]==',')j++;  
  8.         if(j==num)return i+1;   //返回当前找到的逗号位置的下一个位置  
  9.     }  
  10.     return 0;     
  11. }  

        得到精度纬度等高精度数据

[cpp]  view plain copy
  1. static double get_double_number(char *s)  
  2. {  
  3.     char buf[128];  
  4.     int i;  
  5.     double rev;  
  6.     i=GetComma(1,s);    //得到数据长度  
  7.     strncpy(buf,s,i);  
  8.     buf[i]=0;           //加字符串结束标志  
  9.     rev=atof(buf);      //字符串转float  
  10.     return rev;  
  11. }  

        将世界时转换为北京时间

[cpp]  view plain copy
  1. static void UTC2BTC(date_time *GPS)  
  2. {  
  3. //***************************************************  
  4. //如果秒号先出,再出时间数据,则将时间数据+1秒  
  5.         GPS->second++; //加一秒  
  6.         if(GPS->second>59){  
  7.             GPS->second=0;  
  8.             GPS->minute++;  
  9.             if(GPS->minute>59){  
  10.                 GPS->minute=0;  
  11.                 GPS->hour++;  
  12.             }  
  13.         }     
  14.   
  15. //***************************************************  
  16.         GPS->hour+=8;        //北京时间跟UTC时间相隔8小时  
  17.         if(GPS->hour>23)  
  18.         {  
  19.             GPS->hour-=24;  
  20.             GPS->day+=1;  
  21.             if(GPS->month==2 ||GPS->month==4 ||GPS->month==6 ||GPS->month==9 ||GPS->month==11 ){  
  22.                 if(GPS->day>30){          //上述几个月份是30天每月,2月份还不足30  
  23.                     GPS->day=1;  
  24.                     GPS->month++;  
  25.                 }  
  26.             }  
  27.             else{  
  28.                 if(GPS->day>31){          //剩下的几个月份都是31天每月  
  29.                     GPS->day=1;  
  30.                     GPS->month++;  
  31.                 }  
  32.             }  
  33.             if(GPS->year % 4 == 0 ){//  
  34.                 if(GPS->day > 29 && GPS->month ==2){       //闰年的二月是29天  
  35.                     GPS->day=1;  
  36.                     GPS->month++;  
  37.                 }  
  38.             }  
  39.             else{  
  40.                 if(GPS->day>28 &&GPS->month ==2){      //其他的二月是28天每月  
  41.                     GPS->day=1;  
  42.                     GPS->month++;  
  43.                 }  
  44.             }  
  45.             if(GPS->month>12){  
  46.                 GPS->month-=12;  
  47.                 GPS->year++;  
  48.             }         
  49.         }  
  50. }  

(3)解析GPS数据,以line作为传入的字符串数据,GPS是待赋值的全局变量。以下第一行是字符顺序号

//0      7  0   4 6   0     6 8 0        90         0  3      0        9   
//$GPRMC,091400,A,3958.9870,N,11620.3278,E,000.0,000.0,120302,005.6,W*62 
//$GPGGA,091400,3958.9870,N,11620.3278,E,1,03,1.9,114.2,M,-8.3,M,,*5E

[cpp]  view plain copy
  1. void gps_parse(char *line,GPS_INFO *GPS)  
  2. {  
  3.     int i,tmp,start,end;  
  4.     char c;  
  5.     char* buf=line;  
  6.     c=buf[5];  
  7.   
  8.     if(c=='C'){//"GPRMC"  
  9.         GPS->D.hour   =(buf[ 7]-'0')*10+(buf[ 8]-'0');  
  10.         GPS->D.minute =(buf[ 9]-'0')*10+(buf[10]-'0');  
  11.         GPS->D.second =(buf[11]-'0')*10+(buf[12]-'0');  
  12.         tmp = GetComma(9,buf);      //得到第9个逗号的下一字符序号  
  13.         GPS->D.day    =(buf[tmp+0]-'0')*10+(buf[tmp+1]-'0');  
  14.         GPS->D.month  =(buf[tmp+2]-'0')*10+(buf[tmp+3]-'0');  
  15.         GPS->D.year   =(buf[tmp+4]-'0')*10+(buf[tmp+5]-'0')+2000;  
  16.         //------------------------------  
  17.         GPS->status   =buf[GetComma(2,buf)];     //状态  
  18.         GPS->latitude =get_double_number(&buf[GetComma(3,buf)]); //纬度  
  19.         GPS->NS       =buf[GetComma(4,buf)];             //南北纬  
  20.         GPS->longitude=get_double_number(&buf[GetComma(5,buf)]); //经度  
  21.         GPS->EW       =buf[GetComma(6,buf)];             //东西经  
  22.         UTC2BTC(&GPS->D);                        //转北京时间  
  23.     }  
  24.     if(c=='A'){ //"$GPGGA"  
  25.         GPS->high     = get_double_number(&buf[GetComma(9,buf)]);  
  26.           
  27.     }  
  28. }  

       显示解析结果

[cpp]  view plain copy
  1. void show_gps(GPS_INFO *GPS)  
  2. {  
  3.     printf("DATE     : %ld-%02d-%02d \n",GPS->D.year,GPS->D.month,GPS->D.day);  
  4.     printf("TIME     :  %02d:%02d:%02d \n",GPS->D.hour,GPS->D.minute,GPS->D.second);  
  5.     printf("Latitude : %10.4f %c\n",GPS->latitude,GPS->NS);     
  6.     printf("Longitude: %10.4f %c\n",GPS->longitude,GPS->EW);    
  7.     printf("high     : %10.4f \n",GPS->high);      
  8.     printf("STATUS   : %c\n",GPS->status);     
  9. }  
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值