//str转换为数字,以','或者'*'结束 //buf:数字存储区 //dx:小数点位数,返回给调用函数 //返回值:转换后的数值 int NMEA_Str2num(u8* buf, u8* dx) { u8* p = buf; u32 ires = 0, fres = 0; u8 ilen = 0, flen = 0, i; u8 mask = 0; int res; while (1) //得到整数和小数的长度 { if (*p == '-') { mask |= 0X02; //是负数 p++; } if (*p == ',' || (*p == '*'))break; //遇到结束了 if (*p == '.') { mask |= 0X01; //遇到小数点了 p++; } else if (*p > '9' || (*p < '0')) //有非法字符 { ilen = 0; flen = 0; break; } if (mask & 0X01)flen++; else ilen++; p++; } if (mask & 0X02)buf++; //去掉负号 for (i = 0; i < ilen; i++) //得到整数部分数据 { ires += NMEA_Pow(10, ilen - 1 - i) * (buf[i] - '0'); } if (flen > 5)flen = 5; //最多取5位小数 *dx = flen; //小数点位数 for (i = 0; i < flen; i++) //得到小数部分数据 { fres += NMEA_Pow(10, flen - 1 - i) * (buf[ilen + 1 + i] - '0'); } res = ires * NMEA_Pow(10, flen) + fres; if (mask & 0X02)res = -res; return res; }
void NMEA_GNVTG_Analysis(nmea_msg *gpsx,uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; p1=(uint8_t*)strstr((const char *)buf,"$GNVTG"); //搜索字符串$GNVTG在p中第一次出现的位置 posx=NMEA_Comma_Pos(p1,7); //得到地面速率 if(posx!=0XFF) { gpsx->speed=NMEA_Str2num(p1+posx,&dx); if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //确保扩大1000倍 } }
//分析GPVTG信息 //gpsx:nmea信息结构体 //buf:接收到的GPS数据缓冲区首地址 void NMEA_GPVTG_Analysis(nmea_msg *gpsx,u8 *buf) { u8 *p1,dx; u8 posx; p1=(u8*)strstr((const char *)buf,"$GPVTG"); posx=NMEA_Comma_Pos(p1,7); //得到地面速率 if(posx!=0XFF) { gpsx->speed=NMEA_Str2num(p1+posx,&dx); if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //确保扩大1000倍 } }
//分析GNRMC信息 //gpsx:nmea信息结构体 //buf:接收到的GPS数据缓冲区首地址 void NMEA_GNRMC_Analysis(nmea_msg *gpsx, uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; uint32_t temp; float rs; p1=(uint8_t*)strstr((const char *)buf,"GNRMC"); //"$GNRMC",经常有&和GNRMC分开的情况,故只判断GNRMC. posx=NMEA_Comma_Pos(p1,1); //得到UTC时间 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx)/NMEA_Pow(10,dx); //得到UTC时间,去掉ms gpsx->utc.hour=temp/10000 + 8; // + 8:转换为北京时间 gpsx->utc.min=(temp/100)%100; gpsx->utc.sec=temp%100; } posx=NMEA_Comma_Pos(p1,3); //得到纬度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->latitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' gpsx->latitude=gpsx->latitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° } posx=NMEA_Comma_Pos(p1,4); //南纬还是北纬 if(posx!=0XFF)gpsx->nshemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,5); //得到经度 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); gpsx->longitude=temp/NMEA_Pow(10,dx+2); //得到° rs=temp%NMEA_Pow(10,dx+2); //得到' gpsx->longitude=gpsx->longitude*NMEA_Pow(10,5)+(rs*NMEA_Pow(10,5-dx))/60;//转换为° } posx=NMEA_Comma_Pos(p1,6); //东经还是西经 if(posx!=0XFF)gpsx->ewhemi=*(p1+posx); posx=NMEA_Comma_Pos(p1,9); //得到UTC日期 if(posx!=0XFF) { temp=NMEA_Str2num(p1+posx,&dx); //得到UTC日期 gpsx->utc.date=temp/10000; gpsx->utc.month=(temp/100)%100; gpsx->utc.year=2000+temp%100; } }
void NMEA_GNVTG_Analysis(nmea_msg *gpsx, uint8_t *buf) { uint8_t *p1,dx; uint8_t posx; p1=(uint8_t*)strstr((const char *)buf,"$GNVTG"); //?????$GNVTG?p????????? posx=NMEA_Comma_Pos(p1,1); if(posx!=0XFF) { gpsx->course_earth=NMEA_Str2num(p1+posx,&dx); //???????????????(0-359?)(??100?) } posx=NMEA_Comma_Pos(p1,3); if(posx!=0XFF) { gpsx->course_mag=NMEA_Str2num(p1+posx,&dx); //???????????????(0-359?)(??100?) } posx=NMEA_Comma_Pos(p1,7); //?????? if(posx!=0XFF) { gpsx->speed=NMEA_Str2num(p1+posx,&dx); if(dx<3)gpsx->speed*=NMEA_Pow(10,3-dx); //????1000?(1??/?? -> 0.001??/??) else if(dx>3)gpsx->speed/=NMEA_Pow(10,dx-3); //????1000?(1??/?? -> 0.001??/??)(??1000?) } }