NMEA-0183
u 以下为GPS芯片串口发出的数据:
201512_15:42:3712,$GPTXT,ANTSTATUS=SHORT*43
201512_15:42:37$GNGGA,074219.000,3021.516740,N,12005.998703,E,1,9,1.09,20.996,M,6.991,M,,*42
201512_15:42:37$GNGLL,3021.516740,N,12005.998703,E,074219.000,A,A*45
201512_15:42:37$GPGSA,A,3,20,18,25,10,24,15,22,14,,,,,1.38,1.09,0.85*07
201512_15:42:37$BDGSA,A,3,06,,,,,,,,,,,,1.38,1.09,0.85*1A
201512_15:42:37$GPGSV,3,1,12,18,89,182,30,10,55,320,35,24,47,038,31,12,40,107,33*73
201512_15:42:38$GPGSV,3,2,12,14,34,297,29,22,33,315,32,25,31,156,32,15,25,077,31*7F
201512_15:42:38$GPGSV,3,3,12,20,22,140,31,31,08,227,27,37,,,,193,,,31*4A
201512_15:42:38$BDGSV,1,1,01,06,75,066,27*58
201512_15:42:38$GNVTG,128.46,T,,M,0.00,N,0.00,K,A*2A
201512_15:42:38$GNRMC,074219.000,A,3021.516740,N,12005.998703,E,0.00,128.46,311215,,,A*7E
u 数据接收:
GPRMC格式,数据长度不会超过70;
GPGGA格式,数据长度不会超过72;
Ø 以’$’开始保存,若长度超过74则丢弃并重新接收,否则判断结束符’\r’’\n’;
Ø 首次收到’\r’’\n’则向GPS芯片发送模式(GPS/BD/MIX)控制命令字;
Ø 判断GPS_RX[3、4、5]是否为’R、M、C’,是则开始处理;
u 数据处理:
Ø 判断锁定位;
Ø 时间:小时要+8,若>24则需-24;
Ø 日期:需修正
static void DateRepair(void)
{
uint8 day_tmp , mon_tmp , year_tmp; // 日,月,年暂存
year_tmp = ((gps_data.date_time[0] >> 4) * 10) + (gps_data.date_time[0] & 0xf);
mon_tmp = ((gps_data.date_time[1] >> 4) * 10) + (gps_data.date_time[1] & 0xf);
day_tmp = ((gps_data.date_time[2] >> 4) * 10) + (gps_data.date_time[2] & 0xf);
day_tmp++;
//GPSDATA.date[0]++;
if(mon_tmp == 2) // 如果是2月份
{
if((year_tmp % 4) != 0)
{ //闰年
if(day_tmp > 28)
{ //28天
day_tmp = 1;
mon_tmp++;
}
}
else
{
if(day_tmp > 29)
{ //29天
day_tmp = 1;
mon_tmp++;
}
}
}
else if((mon_tmp == 4) || (mon_tmp == 6) || (mon_tmp == 9) || (mon_tmp == 11))
{ //4,6,9,11月份
if(day_tmp > 30)
{
day_tmp = 1;
mon_tmp++;
}
}
else
{
if(day_tmp > 31)
{ //1,3,5,7,8,10,12月份
day_tmp = 1;
mon_tmp++;
if(mon_tmp > 12)
{
mon_tmp = 1;
year_tmp++;
}
}
}
gps_data.date_time[0] = ((year_tmp / 10) << 4) + (year_tmp % 10); // year
gps_data.date_time[1] = ((mon_tmp / 10) << 4) + (mon_tmp % 10); // mon
gps_data.date_time[2] = ((day_tmp / 10) << 4) + (day_tmp % 10); // day
}
Ø 经纬度
纬度ddmm.mmmm(度分)格式(前面的0也被传输),如3021.5167=120.099786;
经度dddmm.mmmm(度分)格式(前面的0也被传输),如12005.9872=30.358613;
static void longlat_sel(uint8 *pd , uint8 len)
{
uint8 j , jj , jjj;
// 先处理纬度
j = lookup(pd , ',' , 3 , len);
if(j)
{
for(jj = 0; jj < 5; jj++)
{
if((pd[j + jj] == '.') || (pd[j + jj] == ','))
break;
}
//gps_data.latitude[0] = 0;
switch(jj)
{
case 4:
gps_data.latitude[0] = ((pd[j] & 0x0f) << 4) + (pd[j + 1] & 0x0f);
gps_data.latitude[1] = ((pd[j + 2] & 0x0f) << 4) + (pd[j + 3] & 0x0f);
break;
case 3:
gps_data.latitude[0] = pd[j] & 0x0f;
gps_data.latitude[1] = ((pd[j + 1] & 0x0f) << 4) + (pd[j + 2] & 0x0f);
break;
case 2:
gps_data.latitude[0] = 0;
gps_data.latitude[1] = ((pd[j] & 0x0f) << 4) + (pd[j + 1] & 0x0f);
break;
case 1:
gps_data.latitude[0] = 0;
gps_data.latitude[1] = pd[j] & 0x0f;
break;
default:
gps_data.latitude[0] = 0;
gps_data.latitude[1] = 0;
break;
}
jjj = lookup(pd , ',' , 4 , len);
switch(jjj - j - jj - 2) // 小数点后的位数
{
case 6:
case 5:
case 4:
gps_data.latitude[2] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.latitude[3] = ((pd[j + jj + 3] & 0x0f) << 4) + (pd[j + jj + 4] & 0x0f);
break;
case 3:
gps_data.latitude[2] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.latitude[3] = (pd[j + jj + 3] & 0x0f) << 4;
break;
case 2:
gps_data.latitude[2] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.latitude[3] = 0;
break;
case 1:
gps_data.latitude[2] = (pd[j + jj + 1] & 0x0f) << 4;
gps_data.latitude[3] = 0;
break;
default:
gps_data.latitude[2] = 0;
gps_data.latitude[3] = 0;
break;
}
}
// 再处理经度
j = lookup(pd , ',' , 5 , len);
if(j)
{
for(jj = 0; jj < 5; jj++)
{
if((pd[j + jj] == '.') || (pd[j + jj] == ','))
break;
}
switch(jj)
{
case 5:
gps_data.longitude[0] = pd[j] & 0x0f;
gps_data.longitude[1] = ((pd[j + 1] & 0x0f) << 4) + (pd[j + 2] & 0x0f);
gps_data.longitude[2] = ((pd[j + 3] & 0x0f) << 4) + (pd[j + 4] & 0x0f);
break;
case 4:
gps_data.longitude[0] = 0;
gps_data.longitude[1] = ((pd[j] & 0x0f) << 4) + (pd[j + 1] & 0x0f);
gps_data.longitude[2] = ((pd[j + 2] & 0x0f) << 4) + (pd[j + 3] & 0x0f);
break;
case 3:
gps_data.longitude[0] = 0;
gps_data.longitude[1] = pd[j] & 0x0f;
gps_data.longitude[2] = ((pd[j + 1] & 0x0f) << 4) + (pd[j + 2] & 0x0f);
break;
case 2:
gps_data.longitude[0] = 0;
gps_data.longitude[1] = 0;
gps_data.longitude[2] = ((pd[j] & 0x0f) << 4) + (pd[j + 1] & 0x0f);
break;
case 1:
gps_data.longitude[0] = 0;
gps_data.longitude[1] = 0;
gps_data.longitude[2] = pd[j] & 0x0f;
break;
default:
gps_data.longitude[0] = 0;
gps_data.longitude[1] = 0;
gps_data.longitude[2] = 0;
break;
}
jjj = lookup(pd , ',' , 6 , len);
switch(jjj - j - jj - 2) // 小数点后的位数
{
case 6:
case 5:
case 4:
gps_data.longitude[3] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.longitude[4] = ((pd[j + jj + 3] & 0x0f) << 4) + (pd[j + jj + 4] & 0x0f);
break;
case 3:
gps_data.longitude[3] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.longitude[4] = (pd[j + jj + 3] & 0x0f) << 4;
break;
case 2:
gps_data.longitude[3] = ((pd[j + jj + 1] & 0x0f) << 4) + (pd[j + jj + 2] & 0x0f);
gps_data.longitude[4] = 0;
break;
case 1:
gps_data.longitude[3] = (pd[j + jj + 1] & 0x0f) << 4;
gps_data.longitude[4] = 0;
break;
default:
gps_data.longitude[3] = 0;
gps_data.longitude[4] = 0;
break;
}
}
}
//换算为以秒为单位0.1234’=0.1*60’’ + 0.02*60’’ + 0.003*60’’ + 0.0004*60’’;
//扩大1000倍=1*6000 + 2*600 + 3*60 + 4*6;
latitude_tmp = ((gps_data.latitude[0] >> 4) * 10 + (gps_data.latitude[0] & 0xf)) * 3600000;
latitude_tmp += (gps_data.latitude[1] >> 4) * 600000 + (gps_data.latitude[1] & 0xf) * 60000;
latitude_tmp += (gps_data.latitude[2] >> 4) * 6000 + (gps_data.latitude[2] & 0xf) * 600;
latitude_tmp += (gps_data.latitude[3] >> 4) * 60 + (gps_data.latitude[3] & 0xf) * 6;
longitude_tmp = ((gps_data.longitude[0] & 0xf) * 100 + (gps_data.longitude[1] >> 4) * 10 + (gps_data.longitude[1] & 0xf)) * 3600000;
longitude_tmp += (gps_data.longitude[2] >> 4) * 600000 + (gps_data.longitude[2] & 0xf) * 60000;
longitude_tmp += (gps_data.longitude[3] >> 4) * 6000 + (gps_data.longitude[3] & 0xf) * 600;
longitude_tmp += (gps_data.longitude[4] >> 4) * 60 + (gps_data.longitude[4] & 0xf) * 6;
longitude_tmp /= 64;
latitude_tmp /= 64;
Ø 速度
车辆速度不会大于255
speed_tmp = (gps_data.speed[0] >> 4) * 1000 + (gps_data.speed[0] & 0xf) * 100 + (gps_data.speed[1] >> 4) * 10 + (gps_data.speed[1] & 0xf);
speed_tmp *= 1852; // 将速度knot转换成公里/小时
speed_tmp /= 10000; // 缩小10000倍还原速度值
Ø 角度
角度可能大于255,需缩小才能单字节传送;
direct_tmp = (gps_data.angle[0] >> 4) * 1000 + (gps_data.angle[0] & 0xf) * 100 + (gps_data.angle[1] >> 4) * 10 + (gps_data.angle[1] & 0xf);
direct_tmp /= 16; // 方向为原来方向/1.6