【第一篇】(GPS NMEA0813协议)根据逗号为节点解析GPS数据
2016-07-12 20:42阅读:
【第一篇】(GPS NMEA0813协议)根据逗号为节点解析GPS数据
由于公司项目,故有幸接触GPS,并略懂皮毛,研究GPS也有一段时间,今天总结下,根据这种最简单的解析方式,得到经纬度,时间,对地速度和磁偏角。当然读懂这些程序,GPS部分代表懂了,并不能实际用于飞控。但是后续算法,还得继续研究。
开篇我们来普及下GPS基础知识:
NMEA-0183通信标准,输出采用ASCII码。
一般从GPS得到的数据是经纬度。经纬度有多种表示方法1.)
ddd.ddddd, 度 .
度的十进制小数部分(5位)例如:31.12035º2.)
ddd.mm.mmm,度 . 分 .
分的十进制小数部分(3位)例如31º10.335'3.)ddd.mm.ss,
度 . 分 . 秒 例如
31º12'42'
1.现在我们得到的语句为ddd.mm.mmm
转换公式:Decimal Degrees = Degrees + minutes/60
+seconds/3600
2.对地速度为:单位为(节(kn))
1节(kn
SPAN>=1海里/小时=1852/3600(m/s)
3.字符串数据转换为十进制数
关键是得到逗号位置的函数,如下。这个程序输入为一串字符串和逗号的位子,最后输出为逗号后一字符的位置标号。
static uchar GetComma(uchar num,char
*str)
{ uchari,j = 0;
intlen=strlen(str);
for(i= 0;i < len;i
++)
{
if(str[i]==
',')
j++;
if(j==
num)
returni + 1;
//是函数返回的值
}
return0;
//这个代表正常退出
}
先解析GPGGA的语句,得到海拔高度和地表平均高度:
int GPS_GGA_Parse(char *line,GPS_INFO *GPS)
{
ucharch,
status;
char*buf =
line;
ch=
buf[4];
status=
buf[GetComma(2, buf)];
if(ch == 'G')
//$GPGGA
{
if(status != ',')
{
GPS->height_sea=
Get_Float_Number(&buf[GetComma(9, buf)]);
GPS->height_ground=
Get_Float_Number(&buf[GetComma(11, buf)]);
return1;
}
}
return0;
}
$代表buf[0]通过查语句可以发现,buf[4]为字符G则代表为语句$GPGGA
以一下为例
$GPGGA,111255.00,3110.4904,N,12123.8925,E,7,08,1.2,38.97,M,11.48,M,,*54
可知海平面高度=38.97(米)
地表平均高度为=11.48
(米)
但是由于NMEA-0183通信标准,输出采用ASCII码。则我们还得进行字符串转十进制。
通过这个函数可以得到连续的一个十进制数
static float Get_Float_Number(char *s)
{
charbuf[10];
uchari;
floatrev;
i=GetComma(1,s);
i= i -
1;
strncpy(buf,s, i);
buf[i]=
0;
rev=Str_To_Float(buf);
returnrev;
}
再讲下关于纬度的提取(通一个两个就都通了),具体都标注在程序上:
GPS->latitude =
Get_Double_Number(&buf[GetComma(3,buf)]);
GPS->latitude_Degree = (int)GPS->latitude /
100;
//由于是取整,则,当除以100时可以知道只剩下度了。
lati_cent_tmp
= (GPS->latitude -GPS->latitude_Degree *
100); //现在的结构是mm.mmmmmm
GPS->latitude_Cent =
(int)lati_cent_tmp;
//取整就可以得到分,具体可以看笔记
lati_second_tmp
= (lati_cent_tmp -GPS->latitude_Cent) * 60;
//现在的结构是(0.mmmmmmm)x60
GPS->latitude_Second = (int)lati_second_tmp;
//现在的结构就是直接用秒取整。【舍去小数点后面的一些位数会不会对航向有什么影响?】
接下来说下UTC时间转换为我们当地时间:
GPS->D.hour = (buf[7] - '0') * 10
+ (buf[8] - '0');
//时时
//
把字符串数据变为十进制的数据,这样才能算出的数据才不是ASCII码。
GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] -
'0'); //分分
GPS->D.second = (buf[11] - '0') * 10 +(buf[12] -
'0'); //秒秒
tmp = GetComma(9, buf);
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;
好了就写到这,接下来将看APM的程序。欢迎大家与我讨论。。。我的QQ:295951389
附录
此函数把字符串转换为十进制
static float Str_To_Float(char *buf)
{
floatrev = 0;
floatdat;
intinteger =
1;
char*str =
buf;
inti;
while(*str!=
'\0')
{
switch(*str)
{
case'0':
dat= 0;
break;
case'1':
dat= 1;
break;
case'2':
dat= 2;
break;
case'3':
dat= 3;
break;
case'4':
dat= 4;
break;
case'5':
dat= 5;
break;
case'6':
dat= 6;
break;
case'7':
dat= 7;
break;
case'8':
dat= 8;
break;
case'9':
dat= 9;
break;
case'.':
dat= '.';
break;
}
if(dat== '.')
{
integer= 0;
i= 1;
str++;
continue;
}
if(integer == 1 )
{
rev= rev * 10 + dat;
}
else
{
rev= rev + dat / (10 * i);
i= i * 10 ;
}
str++;
}
returnrev;
}