|
楼主 |
发表于 2010-9-20 21:00:21
|
显示全部楼层
1楼 GPS 数据解析
/*------------------------------------------------------
功能:GPS 数据解析
by wowbanui
2010年9月
说明:
GPS 数据解析是直接在串口中断中进行的, 一般编程中并不推荐这么做,
但是在这小项目中效果不错...
而且, 暂时没有容错设计, 也不对GPS语句的CheckSum值校验.
目前测试了一周, 未出现严重错误.
-------------------------------------------------------*/
// 先定义缩写:
#define UCHAR unsigned char
#define UINT unsigned int
//定义数据结构, GPRMC 语句中能解析的数据
typedef struct
{
UCHAR Block;
UCHAR BlockIndex;
UCHAR UTCTime[10]; //hhmmss.mmm
UCHAR Status; //A- 有效定位 V-无效定位
UCHAR Latitude[9]; //ddmm.mmmm
UCHAR NS; //N/S
UCHAR Longitude[10]; //dddmm.mmmm
UCHAR EW; //E/W
UCHAR Speed[5]; //速率000.0~999.9节
UCHAR Course[5]; //航向000.0~359.9度
UCHAR UTCDate[6]; //ddmmyy
}stru_GPSRMC;
typedef struct
{
UCHAR Block;
UCHAR BlockIndex;
// UCHAR UTCTime[10]; //hhmmss.mmm RMC中已有, 所以不解析
// UCHAR Latitude[9]; //ddmm.mmmm
// UCHAR NS; //N/S
// UCHAR Longitude[10]; //dddmm.mmmm
// UCHAR EW; //E/W
UCHAR PositionFix; //0,1,2,6
UCHAR SateUsed[2]; //00~12
// UCHAR HDOP[4]; //0.5~99.9
UCHAR Altitude[7]; //-9999.9~99999.9
}stru_GPSGGA;
typedef struct
{
UCHAR Block;
UCHAR BlockIndex;
UCHAR Mode; //A-自动 /M-手动
UCHAR Mode2; //0,1,2,3
UCHAR SateUsed[12][2];
UCHAR PDOP[4];
UCHAR HDOP[4];
UCHAR VDOP[4];
}stru_GPSGSA;
typedef struct
{
UCHAR SatelliteID[2];//卫星编号
// UCHAR Elevation[2]; //0-90 degree //不显示GPS卫星的方位图, 所以不解析, 节省 5*12 RAM
// UCHAR Azimuth[3]; //0-359 degree//需要解析时去除注释'//'和解析前的'//'即可
UCHAR SNR[2]; //0-99 dbHz
}stru_SatelliteInfo;
typedef struct
{
UCHAR Block;
UCHAR BlockIndex;
UCHAR SateInView[2];
UCHAR GSVID;//当前 GSV语句编号
stru_SatelliteInfo SatelliteInfo[12];
}stru_GPSGSV;
//--------------------------------------------------------------
#define GPS_NULL 0x00 //GPS语句类型
#define GPS_GPGGA 0x01
#define GPS_GPGSA 0x02
#define GPS_GPGSV 0x04
#define GPS_GPRMC 0x08
UCHAR GPSDataType=GPS_NULL; //GPS语句类型
UCHAR GPSDataTypeStrBuff[]="$GPxxx,"; //GPS语句类型缓存, 判断类型时使用,
UCHAR GPSDataTypeStrBuffIndex=0; //GPS语句类型字符串的当前位置
UCHAR xdata MainDateTime[]="00/00/00 00:00:00\0"; //日期时间
UCHAR xdata MainDateTimeShort[]="00/00 00:00:00\0"; //日期时间
UCHAR xdata MainLatitude[]="N dd'mm'ss.ssss\"\0"; //纬度
UCHAR xdata MainLongitude[]="Eddd'mm'ss.ssss\"\0"; //经度
bit GPSDataStart=0; //GPS语句开始. 检测到 $ 时置1
bit ReciveFlag=0; //数据接收完成. 最后一条 GPRMC 语句发送完毕置1,
stru_GPSRMC xdata GPS_RMC_Data;
stru_GPSGGA xdata GPS_GGA_Data;
stru_GPSGSA xdata GPS_GSA_Data;
stru_GPSGSV xdata GPS_GSV_Data;
//------------------------------------------------------------------
/*-------------------------------------------------------
串口中断函数, 同时解析GPS数据到变量中
仅是字符串提取, 没有容错考虑, 不检查GPS语句后的CheckSum值
虽然语句比较多, 但如下图所示, 每次执行的只是其中一条支路
-------------------------------------------------------*/
解析框图:
(原文件名:GPS 解析框图.png)
void Serial() interrupt 4
{
LED_1=0;//串口数据指示灯
if (RI)
{
RI=0;
//判断是否是GPS语句:
if(GPSDataStart)
{ //已经判断到GPS语句头字符$,
switch(GPSDataTypeStrBuffIndex)
{ //已经读取了多少个表示GPS数据类型的字符
case 6:
{ //已经全部读取, 开始判断
if(GPSDataTypeStrBuff[4]=='G'&&GPSDataTypeStrBuff[5]=='A') GPSDataType=GPS_GPGGA;
if(GPSDataTypeStrBuff[4]=='S'&&GPSDataTypeStrBuff[5]=='A') GPSDataType=GPS_GPGSA;
if(GPSDataTypeStrBuff[5]=='V') GPSDataType=GPS_GPGSV;
if(GPSDataTypeStrBuff[5]=='C') GPSDataType=GPS_GPRMC;
if(SBUF==',') GPSDataTypeStrBuffIndex=255; //判断完毕, 数据接收开始
break;
}
case 255:
{ //GPS数据类型的字符全部读取并判断完毕, 正接收数据
switch(GPSDataType)
{ //该句的类型
case GPS_GPGGA:
{
switch(SBUF)
{
case '*': //语句结束
GPSDataStart=0;
break;
case ',': //该字段结束, 下一个
GPS_GGA_Data.Block++;
GPS_GGA_Data.BlockIndex=0; //字段索引置0:第一个字符
break;
default:
{ //字段字符
switch(GPS_GGA_Data.Block)
{ //判断当前处于哪个字段
// case 0:
// GPS_GGA_Data.UTCTime[GPS_GGA_Data.BlockIndex]=SBUF;
// break;
// case 1:
// GPS_GGA_Data.Latitude[GPS_GGA_Data.BlockIndex]=SBUF;
// break;
// case 2:
// GPS_GGA_Data.NS=SBUF;
// break;
// case 3:
// GPS_GGA_Data.Longitude[GPS_GGA_Data.BlockIndex]=SBUF;
// break;
// case 4:
// GPS_GGA_Data.EW=SBUF;
// break;
case 5:
GPS_GGA_Data.PositionFix=SBUF;
break;
case 6:
GPS_GGA_Data.SateUsed[GPS_GGA_Data.BlockIndex]=SBUF;
break;
// case 7:
// GPS_GGA_Data.HDOP[GPS_GGA_Data.BlockIndex]=SBUF;
// break;
case 8:
GPS_GGA_Data.Altitude[GPS_GGA_Data.BlockIndex]=SBUF;
break;
}
GPS_GGA_Data.BlockIndex++; //字段索引++, 指向下一个字符
}
}
break;
}
case GPS_GPRMC:
{
switch(SBUF)
{
// SerialSendChar(SBUF);
case '*':
{
GPSDataStart=0;
GPSDataTypeStrBuffIndex=0;
ReciveFlag=1; //接收完毕, 可以处理
break;
}
case ',':
{
GPS_RMC_Data.Block++;
GPS_RMC_Data.BlockIndex=0;
break;
}
default:
{
switch(GPS_RMC_Data.Block)
{
case 0:
GPS_RMC_Data.UTCTime[GPS_RMC_Data.BlockIndex]=SBUF;
break;
case 1:
GPS_RMC_Data.Status=SBUF;
break;
case 2:
GPS_RMC_Data.Latitude[GPS_RMC_Data.BlockIndex]=SBUF;
break;
case 3:
GPS_RMC_Data.NS=SBUF;
break;
case 4:
GPS_RMC_Data.Longitude[GPS_RMC_Data.BlockIndex]=SBUF;
break;
case 5:
GPS_RMC_Data.EW=SBUF;
break;
case 6:
GPS_RMC_Data.Speed[GPS_RMC_Data.BlockIndex]=SBUF;
break;
case 7:
GPS_RMC_Data.Course[GPS_RMC_Data.BlockIndex]=SBUF;
break;
case 8:
GPS_RMC_Data.UTCDate[GPS_RMC_Data.BlockIndex]=SBUF;
break;
}
GPS_RMC_Data.BlockIndex++;
}
}
break;
}
case GPS_GPGSA:
{
switch(SBUF)
{
case '*':
GPSDataStart=0;
break;
case ',':
GPS_GSA_Data.Block++;
GPS_GSA_Data.BlockIndex=0;
break;
default:
switch(GPS_GSA_Data.Block)
{
case 0:
GPS_GSA_Data.Mode=SBUF;
break;
case 1:
GPS_GSA_Data.Mode2=SBUF;
break;
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13: //2-13 是已使用的卫星ID, 保存于数组中
GPS_GSA_Data.SateUsed[GPS_GSA_Data.Block-2][GPS_GSA_Data.BlockIndex]=SBUF;
break;
case 14:
GPS_GSA_Data.PDOP[GPS_GSA_Data.BlockIndex]=SBUF;
break;
case 15:
GPS_GSA_Data.HDOP[GPS_GSA_Data.BlockIndex]=SBUF;
break;
case 16:
GPS_GSA_Data.VDOP[GPS_GSA_Data.BlockIndex]=SBUF;
break;
}
GPS_GSA_Data.BlockIndex++;
}
break;
}
case GPS_GPGSV:
{
switch(SBUF)
{
case '*':
GPSDataStart=0;
break;
case ',':
GPS_GSV_Data.Block++;
GPS_GSV_Data.BlockIndex=0;
break;
default:
{
switch(GPS_GSV_Data.Block)
{
case 1:
GPS_GSV_Data.GSVID=SBUF-'1'; //当前GPFSV语句的序号, 该序号计算出该组卫星数据应该存放于数组的哪个位置
break;
case 2:
GPS_GSV_Data.SateInView[GPS_GSV_Data.BlockIndex]=SBUF;
break;
case 3:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].SatelliteID[GPS_GSV_Data.BlockIndex]=SBUF;
break;
// case 4:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].Elevation[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
// case 5:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].Azimuth[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
case 6:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4].SNR[GPS_GSV_Data.BlockIndex]=SBUF;
break;
case 7:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].SatelliteID[GPS_GSV_Data.BlockIndex]=SBUF;
break;
// case 8:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].Elevation[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
// case 9:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].Azimuth[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
case 10:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+1].SNR[GPS_GSV_Data.BlockIndex]=SBUF;
break;
case 11:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].SatelliteID[GPS_GSV_Data.BlockIndex]=SBUF;
break;
// case 12:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].Elevation[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
// case 13:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].Azimuth[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
case 14:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+2].SNR[GPS_GSV_Data.BlockIndex]=SBUF;
break;
case 15:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].SatelliteID[GPS_GSV_Data.BlockIndex]=SBUF;
break;
// case 16:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].Elevation[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
// case 17:
// GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].Azimuth[GPS_GSV_Data.BlockIndex]=SBUF;
// break;
case 18:
GPS_GSV_Data.SatelliteInfo[GPS_GSV_Data.GSVID*4+3].SNR[GPS_GSV_Data.BlockIndex]=SBUF;
break;
}
GPS_GSV_Data.BlockIndex++;
}
}
break;
}
default:
{ //GPS类型判断失败, 进入未接收到GPS语句($)的状态, 重新循环
GPSDataStart=0;
GPSDataType=GPS_NULL;
}
}
break;
}
default:
{ //未判断, 继续接收, Index++
GPSDataTypeStrBuff[GPSDataTypeStrBuffIndex]=SBUF;
GPSDataTypeStrBuffIndex++;
}
}
}
else
{ //未发现语句头字符, 继续接收并判断
if (SBUF=='$')
{ //接收到$, 下一个字符即为类型判断字符, 先进行相关变量初始化
GPSDataTypeStrBuff[0]=SBUF;
GPSDataStart=1; //从头存放GPS类型字符到变量
GPSDataType=GPS_NULL;
GPSDataTypeStrBuffIndex=1;
GPS_RMC_Data.Block=0; //每种语句的标志位
GPS_RMC_Data.BlockIndex=0;
GPS_GSV_Data.Block=0;
GPS_GSV_Data.BlockIndex=0;
GPS_GGA_Data.Block=0;
GPS_GGA_Data.BlockIndex=0;
GPS_GSA_Data.Block=0;
GPS_GSA_Data.BlockIndex=0;
}
}
}
LED_1=1;
}
/*-------------------------------------------------------
获取纬度并转换成度分秒格式
算法(也谈不上算法~~)请看我的帖子 :
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4228218
-------------------------------------------------------*/
void GetLatitude()
{
unsigned long s;
MainLatitude[0]=GPS_RMC_Data.NS; //北纬 南纬标志
MainLatitude[2]=GPS_RMC_Data.Latitude[0]; //度, 直接提取
MainLatitude[3]=GPS_RMC_Data.Latitude[1];
MainLatitude[4]=0x02; //度(°)符号
MainLatitude[5]=GPS_RMC_Data.Latitude[2]; //分, 直接提取
MainLatitude[6]=GPS_RMC_Data.Latitude[3];
//直接提取后四位分并扩大10000倍为整数存于Long型, 避免小数运算
s=(GPS_RMC_Data.Latitude[5]-'0')*1000+(GPS_RMC_Data.Latitude[6]-'0')*100+
(GPS_RMC_Data.Latitude[7]-'0')*10+(GPS_RMC_Data.Latitude[8]-'0');
s*=60; //转换成单位 秒(")
//提取到字符串中
MainLatitude[8]=s/100000+'0';
s=s%100000;
MainLatitude[9]=s/10000+'0';
s=s%10000;
MainLatitude[11]=s/1000+'0';
s=s%1000;
MainLatitude[12]=s/100+'0';
s=s%100;
MainLatitude[13]=s/10+'0';
s=s%10;
MainLatitude[14]=s+'0';
}
/*-------------------------------------------------------
获取经度并转换成度分秒格式
算法(也谈不上算法~~)请看我的帖子 :
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4228218
-------------------------------------------------------*/
void GetLongitude()
{
unsigned long s;
MainLongitude[0]=GPS_RMC_Data.EW;
MainLongitude[1]=GPS_RMC_Data.Longitude[0];
MainLongitude[2]=GPS_RMC_Data.Longitude[1];
MainLongitude[3]=GPS_RMC_Data.Longitude[2];
MainLongitude[4]=0x02;
MainLongitude[5]=GPS_RMC_Data.Longitude[3];
MainLongitude[6]=GPS_RMC_Data.Longitude[4];
s=(GPS_RMC_Data.Longitude[6]-'0')*1000+(GPS_RMC_Data.Longitude[7]-'0')*100+
(GPS_RMC_Data.Longitude[8]-'0')*10+(GPS_RMC_Data.Longitude[9]-'0');
s*=60;
MainLongitude[8]=s/100000+'0';
s=s%100000;
MainLongitude[9]=s/10000+'0';
s=s%10000;
MainLongitude[11]=s/1000+'0';
s=s%1000;
MainLongitude[12]=s/100+'0';
s=s%100;
MainLongitude[13]=s/10+'0';
s=s%10;
MainLongitude[14]=s+'0';
} |
|