GPS(NMEA)数据解析
一、GPS定位信息
创新互联公司-专业网站定制、快速模板网站建设、高性价比桂东网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式桂东网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖桂东地区。费用合理售后完善,十余年实体公司更值得信赖。
设置好gps模式,启动gps,正常的话在gps通路有NMEA数据上报,如下:
$GPGSV,3,1,11,01,62,130,42,07,61,201,43,11,72,075,28,17,20,251,38*7A
$GPGSV,3,2,11,30,63,272,44,03,00,149,,08,34,046,,13,05,309,*76
$GPGSV,3,3,11,22,08,127,,27,03,057,,28,34,312,*4C
$GPGGA,042523.0,3413.610533,N,10854.063257,E,1,05,2.6,438.5,M,-28.0,M,,*78
$GPVTG,245.9,T,245.9,M,0.0,N,0.0,K,A*23
$GPRMC,042523.0,A,3413.610533,N,10854.063257,E,0.0,245.9,190716,0.0,E,A*0F
$GPGSA,A,2,01,07,11,17,30,,,,,,,,2.8,2.6,1.0*3F
(1) $GPGGA (GPS定位信息)
协议格式:
$GPGGA,161229.487,3723.2475,N,12158.3416,W,1,07,1.0,9.0,M, , ,,0000*18
协议格式详细分析:
(2) $GPGLL (地理定位信息)
协议格式:
$GPGLL,<1>,<2>,<3>,<4>,<5>,<6>*hh
样例数据:
$GPGLL,3723.2475,N,12158.3416,W,161229.487,A*2C
协议格式详细分析:
(3) $GPGSA (当前卫星信息)
协议格式:
$GPGSA,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>,<13>,<14>,<15>,<16>,<17>*hh
样例数据:
$GPGSA,A,3,07,02,26,27,09,04,15, , , , , ,1.8,1.0,1.5*33
协议格式详细分析:
(4) $GPGSV(可见卫星信息)
协议格式:
$GPGSV, <1>,<2>,<3>,<4>,<5>,<6>,<7>,...,<4>,<5>,<6>,<7>*hh
样例数据:
$GPGSV,2,1,07,07,79,048,42,02,51,062,43,26,36,256,42,27,27,138,42*71$GPGSV,2,2,07,09,23,313,42,04,19,159,41,15,12,041,42*41
需要注意的是这里的样例数据有2条,这是因为当前可见卫星一共有7个,但是每条语句最多包括四颗卫星的信息,所以分成了2条语句。每颗卫星的信息有四个数据项,即:<4>(卫星编号)、<5>(卫星仰角)、<6>(卫星方位角)、<7>(信噪比)。
协议格式详细分析(只分析第1条样例数据语句):
(5) $GPRMC(最简定位信息)
协议格式:
$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>*hh
样例数据:
$GPRMC,161229.487,A,3723.2475,N,12158.3416,W,0.13,309.62,120598,,*10
协议格式详细分析:
(6) $GPVTG(地面速度信息)
协议格式:
$GPVTG,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>*hh
样例数据:
$GPVTG,309.62,T, ,M,0.13,N,0.2,K*6E
协议格式详细分析:
二、GPS(NMEA)数据解析
/*********************************************************************************/
ingps.h
/*********************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*********************************************************************************/
degps.h
/*********************************************************************************/
#include "ingps.h"
#define TTYUSB "/dev/ttyUSB3" /*串口设备*/
#define BAUD_RATE 4800 /*波特率 */
#define DATA_BITS 8 /*数据位*/
#define NEVENT 'N' /*校验 */
#define NSTOP 1 /*停止位*/
#define BUFLEN 512 /*可随意取,但要大于GPGGA_MAX*/
#define GPGGA_MAX 100 /*"$GPGGA……"的最大值,待定*/
#define DBG_GPS
typedef struct{
int year;
int month;
int day;
int hour;
int minute;
int second;
}date_time;
typedef struct{
date_time D;/*时间*/
char status; /*接收状态 */
double latitude; /*纬度*/
double longitude; /*经度 */
char NS; /*南北极*/
char EW; /*东西 */
int num; /*卫星数*/
double speed; /*速度 */
double high; /*高度*
}GPS_INFO;
/*********************************************************************************/
getgps.c
/*********************************************************************************/
#include “degps.h”
#include "ingps.h"
static int GetComma(int num,char *str)
{
int i,j=0;
int len=strlen(str);
for(i=0;i { if(str[i]==',') j++; if(j==num) return i+1; /*返回当前找到的逗号位置的下一个位置*/ } return 0; } static double get_double_number(char *s) { char buf[128]; int i; double rev; i=GetComma(1,s); /*得到数据长度 */ strncpy(buf,s,i); buf[i]=0; /*加字符串结束标志*/ rev=atof(buf); /*字符串转float */ return rev; } static int get_int_number(char *s) { char buf[128]; int i; double rev; i=GetComma(1,s); /*得到数据长度*/ strncpy(buf,s,i); buf[i]=0; /*加字符串结束标志 */ rev=atoi(buf); /*字符串转float */ return rev; } static void UTC2BTC(date_time *GPS) { /*如果秒号先出,再出时间数据,则将时间数据+1秒 */ GPS->second++; /*加一秒*/ if(GPS->second>59){ GPS->second=0; GPS->minute++; if(GPS->minute>59){ GPS->minute=0; GPS->hour++; } } GPS->hour+=8; /*北京时间跟UTC时间相隔8小时 */ if(GPS->hour>23) { GPS->hour-=24; GPS->day+=1; if(GPS->month==2 ||GPS->month==4 ||GPS->month==6 ||GPS->month==9 ||GPS->month==11 ){ if(GPS->day>30){ /*上述几个月份是30天每月,2月份还不足30*/ GPS->day=1; GPS->month++; } } else{ if(GPS->day>31){ /*剩下的几个月份都是31天每月 */ GPS->day=1; GPS->month++; } } if(GPS->year % 4 == 0 ){ if(GPS->day > 29 && GPS->month ==2){ /*闰年的二月是29天*/ GPS->day=1; GPS->month++; } } else{ if(GPS->day>28 &&GPS->month ==2){ /*其他的二月是28天每月*/ GPS->day=1; GPS->month++; } } if(GPS->month>12){ GPS->month-=12; GPS->year++; } } } void gps_parse(char *line,GPS_INFO *GPS) { int tmp; char c; char* buf=line; c=buf[5]; if(c=='C')/* "GPRMC" */ { GPS->D.hour =(buf[7]-'0')*10+(buf[8]-'0'); GPS->D.minute =(buf[9]-'0')*10+(buf[10]-'0'); GPS->D.second =(buf[11]-'0')*10+(buf[12]-'0'); tmp = GetComma(9,buf); /*得到第9个逗号的下一字符序号*/ GPS->D.day =(buf[tmp+0]-'0')*10+(buf[tmp+1]-'0'); GPS->D.month =(buf[tmp+2]-'0')*10+(buf[tmp+3]-'0'); GPS->D.year =(buf[tmp+4]-'0')*10+(buf[tmp+5]-'0')+2000; /*********************************************************/ GPS->status =buf[GetComma(2,buf)]; /*状态*/ GPS->latitude =get_double_number(&buf[GetComma(3,buf)]); /*纬度*/ GPS->NS =buf[GetComma(4,buf)]; /*南北纬 */ GPS->longitude=get_double_number(&buf[GetComma(5,buf)]); /*经度*/ GPS->EW =buf[GetComma(6,buf)]; /*东西经 */ UTC2BTC(&GPS->D); /*转北京时间*/ } if(c=='A') /*"$GPGGA" */ { GPS->high =get_double_number(&buf[GetComma(9,buf)]); GPS->num =get_int_number(&buf[GetComma(7,buf)]); } } voidshow_gps(GPS_INFO *GPS) { printf("年份 : %ld-%02d-%02d\n",GPS->D.year,GPS->D.month,GPS->D.day); printf("时间 : %02d:%02d:%02d\n",GPS->D.hour,GPS->D.minute,GPS->D.second); printf("纬度 : %s %10.4f\n",(GPS->NS=='N')?"北纬":"南纬",GPS->latitude); printf("经度 : %s %10.4f\n",(GPS->EW=='W')?"西经":"东经",GPS->longitude); printf("卫星数 : %02d\n",GPS->num); printf("高度 : %.4f\n",GPS->high); printf("状态 : %s\n",(GPS->status=='A')?"定位":"导航"); printf("--------------------\n"); } int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio,oldtio; if ( tcgetattr( fd,&oldtio) != 0) { perror("SetupSerial 1"); return -1; } bzero( &newtio, sizeof( newtio ) ); newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; switch( nBits ) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } switch( nEvent ) { case 'o': case 'O': newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'e': case 'E': newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'n': case 'N': newtio.c_cflag &= ~PARENB; break; case 's': case 'S': newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; break; default: printf("Unsupported parity\n"); return -1; } switch( nSpeed ) { case 2400: cfsetispeed(&newtio, B2400); cfsetospeed(&newtio, B2400); break; case 4800: cfsetispeed(&newtio, B4800); cfsetospeed(&newtio, B4800); break; case 9600: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; case 115200: cfsetispeed(&newtio, B115200); cfsetospeed(&newtio, B115200); break; case 460800: cfsetispeed(&newtio, B460800); cfsetospeed(&newtio, B460800); break; default: cfsetispeed(&newtio, B9600); cfsetospeed(&newtio, B9600); break; } if( nStop == 1 ) newtio.c_cflag &= ~CSTOPB; else if ( nStop == 2 ) newtio.c_cflag |= CSTOPB; newtio.c_cc[VTIME] = 0;/*超时 重要*/ newtio.c_cc[VMIN] = 100;/*返回的最小值 重要*/ tcflush(fd,TCIFLUSH); if((tcsetattr(fd,TCSANOW,&newtio))!=0) { perror("com set error"); return -1; } return 0; } int Get_GPSData(char* gpd,char* buf,char* tar_value) { char *pos = NULL; int cur = 0,counter=1,i =0; pos = strstr(buf,gpd); if(pos == NULL){ return counter; } cur = pos - buf; tar_value[0]='$'; for(i = cur; i < BUFLEN; i++){ if(buf[i]!='$' && buf[i]!='\n' ){ tar_value[counter]=buf[i]; counter++; } else{ tar_value[counter]='\0'; break; } } return counter; } int main(void) { GPS_INFO GPS; int fd1,nset1,nread; char buf[BUFLEN],tar_value[512]; fd1 = open(TTYUSB, O_RDWR);/*打开串口*/ if (fd1 == -1) exit(1); nset1 = set_opt(fd1,BAUD_RATE, DATA_BITS, NEVENT, NSTOP);/*设置串口属性*/ if (nset1 == -1) exit(1); while(1) { memset(buf,0,BUFLEN); memset(tar_value,0,sizeof(tar_value)); nread = read(fd1, buf, BUFLEN);/*读串口*/ if (nread > 0){ if(Get_GPSData("GPGGA",buf,tar_value) <70){ sleep(2); continue; } gps_parse(tar_value,&GPS); memset(tar_value,0,sizeof(tar_value)); if(Get_GPSData("GPRMC",buf,tar_value) <70){ sleep(2); continue; } gps_parse(tar_value,&GPS); show_gps(&GPS); } sleep(2);/*睡眠,等待数据多一点 */ } close(fd1); return 0; } 参考文:http://www.cnblogs.com/tianciliangen/p/3796701.html ,http://blog.csdn.net/zhandoushi1982/article/details/7947682执行结果如下:
年份 : 2014-07-20
时间 : 10:16:20
纬度 : 北纬 3913.6049
经度 : 东经 10154.0622
卫星数 : 05
高度 : 449.3000
状态 : 定位
网站名称:GPS(NMEA)数据解析
URL地址:http://myzitong.com/article/geoddi.html