GPS-GPZDA数据解析C语言
- 格式:doc
- 大小:414.50 KB
- 文档页数:19
gpgga 格工解析GPGGA格式解析GPGGA是全球定位系统(GPS)中的一种卫星定位报文格式。
本文将对GPGGA格式进行详细解析,包括其组成部分和各字段的含义。
一、GPGGA格式简介GPGGA格式是GPS定位信息的一种标准格式,用于描述接收器定位信息。
它由一系列以逗号分隔的字段组成,每个字段都有特定的含义和数据类型。
以下是GPGGA格式的示例:GPGGA,053930.00,2230.942,N,11354.905,E,1,08,1.0,17.3,M,-22.4,M,,*42接下来,我们将对其中的各字段进行详细解析。
二、GPGGA字段解析1. Sentence ID(报文ID): "GPGGA"是GPGGA格式的唯一标识符,用于区分其他GPS报文。
2. UTC Time(协调世界时): 以hhmmss.ss格式表示,表示接收到GPS信号时的时间。
在上述示例中,时间为05:39:30.00。
3. Latitude(纬度): 以ddmm.mmm格式表示,表示接收器所在位置的纬度。
上述示例中纬度为22度30.942分北纬。
4. Latitude Indicator(纬度指示): "N"表示北纬,"S"表示南纬。
5. Longitude(经度): 以dddmm.mmm格式表示,表示接收器所在位置的经度。
上述示例中经度为113度54.905分东经。
6. Longitude Indicator(经度指示): "E"表示东经,"W"表示西经。
7. Fix Quality(定位质量指示): 表示接收器定位的质量。
常见值有:1 - 定位解可用,但定位精度较差;2 - 差分GPS解可用,定位精度较好;0 - 定位解不可用。
上述示例中定位质量为1。
8. Satellites Tracked(跟踪卫星数): 表示接收器当前正在追踪的卫星数。
NMEA协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。
GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA 等设备。
NMEA-0183协议是GPS接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。
不过,也有少数厂商的设备使用自行约定的协议比如GARMIN的GPS设备(部分GARMIN设备也可以输出兼容NMEA-0183协议的数据)。
软件方面,我们熟知的Google Earth目前也不支持NMEA-0183协议,但Google Earth已经声明会尽快实现对NMEA-0183协议的兼容。
呵呵,除非你确实强壮到可以和工业标准分庭抗礼,否则你就得服从工业标准。
NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。
下面给出这些常用NMEA-0183语句的字段定义解释。
$GPGGA例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1 F字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data (GGA)GPS定位信息字段1:UTC 时间,hhmmss.sss,时分秒格式字段2:纬度ddmm.mmmm,度分格式(前导位数不足则补0)字段3:纬度N(北纬)或S(南纬)字段4:经度dddmm.mmmm,度分格式(前导位数不足则补0)字段5:经度E(东经)或W(西经)字段6:GPS状态,0=未定位,1=非差分定位,2=差分定位,3=无效PPS,6=正在估算字段7:正在使用的卫星数量(00 - 12)(前导位数不足则补0)字段8:HDOP水平精度因子(0.5 - 99.9)字段9:海拔高度(-9999.9 - 99999.9)字段10:地球椭球面相对大地水准面的高度字段11:差分时间(从最近一次接收到差分信号开始的秒数,如果不是差分定位将为空)字段12:差分站ID号0000 - 1023(前导位数不足则补0,如果不是差分定位将为空)字段13:校验值$GPGSA例:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A字段0:$GPGSA,语句ID,表明该语句为GPS DOP and Active Satellites(GSA)当前卫星信息字段1:定位模式,A=自动手动2D/3D,M=手动2D/3D字段2:定位类型,1=未定位,2=2D定位,3=3D定位字段3:PRN码(伪随机噪声码),第1信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段4:PRN码(伪随机噪声码),第2信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段5:PRN码(伪随机噪声码),第3信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段6:PRN码(伪随机噪声码),第4信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段7:PRN码(伪随机噪声码),第5信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段8:PRN码(伪随机噪声码),第6信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段9:PRN码(伪随机噪声码),第7信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段10:PRN码(伪随机噪声码),第8信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段11:PRN码(伪随机噪声码),第9信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段12:PRN码(伪随机噪声码),第10信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段13:PRN码(伪随机噪声码),第11信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段14:PRN码(伪随机噪声码),第12信道正在使用的卫星PRN码编号(00)(前导位数不足则补0)字段15:PDOP综合位置精度因子(0.5 - 99.9)字段16:HDOP水平精度因子(0.5 - 99.9)字段17:VDOP垂直精度因子(0.5 - 99.9)字段18:校验值$GPGSV例:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70字段0:$GPGSV,语句ID,表明该语句为GPS Satellites in View(GSV)可见卫星信息字段1:本次GSV语句的总数目(1 - 3)字段2:本条GSV语句是本次GSV语句的第几条(1 - 3)字段3:当前可见卫星总数(00 - 12)(前导位数不足则补0)字段4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)字段5:卫星仰角(00 - 90)度(前导位数不足则补0)字段6:卫星方位角(00 - 359)度(前导位数不足则补0)字段7:信噪比(00-99)dbHz字段8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)字段9:卫星仰角(00 - 90)度(前导位数不足则补0)字段10:卫星方位角(00 - 359)度(前导位数不足则补0)字段11:信噪比(00-99)dbHz字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不足则补0)字段13:卫星仰角(00 - 90)度(前导位数不足则补0)字段14:卫星方位角(00 - 359)度(前导位数不足则补0)字段15:信噪比(00-99)dbHz字段16:校验值$GPRMC例:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A* 50字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息字段1:UTC时间,hhmmss.sss格式字段2:状态,A=定位,V=未定位字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)字段4:纬度N(北纬)或S(南纬)字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)字段6:经度E(东经)或W(西经)字段7:速度,节,Knots字段8:方位角,度字段9:UTC日期,DDMMYY格式字段10:磁偏角,(000 - 180)度(前导位数不足则补0)字段11:磁偏角方向,E=东W=西字段16:校验值$GPVTG例:$GPVTG,89.68,T,,M,0.00,N,0.0,K*5F字段0:$GPVTG,语句ID,表明该语句为Track Made Good and Ground Speed (VTG)地面速度信息字段1:运动角度,000 - 359,(前导位数不足则补0)字段2:T=真北参照系字段3:运动角度,000 - 359,(前导位数不足则补0)字段4:M=磁北参照系字段5:水平运动速度(0.00)(前导位数不足则补0)字段6:N=节,Knots字段7:水平运动速度(0.00)(前导位数不足则补0)字段8:K=公里/时,km/h字段9:校验值$GPGLL例:$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D字段0:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息字段1:纬度ddmm.mmmm,度分格式(前导位数不足则补0)字段2:纬度N(北纬)或S(南纬)字段3:经度dddmm.mmmm,度分格式(前导位数不足则补0)字段4:经度E(东经)或W(西经)字段5:UTC时间,hhmmss.sss格式字段6:状态,A=定位,V=未定位字段7:校验值1、GPS DOP and Active Satellites(GSA)当前卫星信息$GPGSA,<1>,<2>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<3>,<4>,<5>, <6>*hh<CR><LF><1> 模式,M=手动,A=自动<2> 定位类型,1=没有定位,2=2D定位,3=3D定位<3> PRN码(伪随机噪声码),正在用于解算位置的卫星号(01~32,前面的0也将被传输)。
$GPGGA,121252.000,3937.3032,N,11611.6046,E,1,05,2.0,45.9,M,-5.7,M,,0000*77 $GPRMC,121252.000,A,3958.3032,N,11629.6046,E,15.15,359.95,070306,,,A*54$GPVTG,359.95,T,,M,15.15,N,28.0,K,A*04$GPGGA,121253.000,3937.3090,N,11611.6057,E,1,06,1.2,44.6,M,-5.7,M,,0000*72$GPGSA,A,3,14,15,05,22,18,26,,,,,,,2.1,1.2,1.7*3D$GPGSV,3,1,10,18,84,067,23,09,67,067,27,22,49,312,28,15,47,231,30*70GPS上电后,每隔一定的时间就会返回一定格式的数据,数据格式为:$信息类型,x,x,x,x,x,x,x,x,x,x,x,x,x每行开头的字符都是‘$’,接着是信息类型,后面是数据,以逗号分隔开。
一行完整的数据如下:$GPRMC,080655.00,A,4546.40891,N,12639.65641,E,1.045,328.42,170809,,,A*60信息类型为:GPGSV:可见卫星信息GPGLL:地理定位信息GPRMC:推荐最小定位信息GPVTG:地面速度信息GPGGA:GPS定位信息GPGSA:当前卫星信息这里我们只解析GPRMC和GPGGA的信息GPRMC数据详解:$GPRMC,<1>,<2>,<3>,<4>,<5>,<6>,<7>,<8>,<9>,<10>,<11>,<12>*hh<1> UTC时间,hhmmss(时分秒)格式<2> 定位状态,A=有效定位,V=无效定位<3> 纬度ddmm.mmmm(度分)格式(前面的0也将被传输)<4> 纬度半球N(北半球)或S(南半球)<5> 经度dddmm.mmmm(度分)格式(前面的0也将被传输)<6> 经度半球E(东经)或W(西经)<7> 地面速率(000.0~999.9节,前面的0也将被传输)<8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)<9> UTC日期,ddmmyy(日月年)格式<10> 磁偏角(000.0~180.0度,前面的0也将被传输)<11> 磁偏角方向,E(东)或W(西)<12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)解析内容:1.时间,这个是格林威治时间,是世界时间(UTC),我们需要把它转换成北京时间(BTC),BTC和UTC差了8个小时,要在这个时间基础上加8个小时。
GPS解析程序GPS.H#ifndef __GPS_H__#define __GPS_H__#include "common.h"typedef struct{u8 UTCDateTime[6]; //YMDHMSu8 Status; //A/Vu8 Latitude[9]; //ddmm.mmmmu8 NS; //N/Su8 Longitude[10]; //dddmm.mmmmu8 EW; //E/Wu8 Speed[5]; //速率000.0~999.9节u8 Course[5]; //航向000.0~359.9度}stru_GPSRMC;typedef struct{// u8 UTCTime[10]; //hhmmss.mmm // u8 Latitude[9]; //ddmm.mmmm// u8 NS; //N/S// u8 Longitude[10]; //dddmm.mmmm // u8 EW; //E/Wu8 PositionFix; //0,1,2,6u8 SatUsed[2]; //00~12// u8 HDOP[4]; //0.5~99.9u8 Altitude[7]; //-9999.9~99999.9}stru_GPSGGA;typedef struct{u8 Mode; //A/Mu8 Mode2; //0,1,2,3u8 SatUsedList[12];u8 PDOP[4];u8 HDOP[4];u8 VDOP[4];}stru_GPSGSA;typedef struct{u8 SatID;// u8 Elevation[2];//0-90 degree// u8 Azimuth[3]; //0-359 degreeu8 SNR; //0-99 dbHz}stru_SatInfo;typedef struct{u8 SatInView;stru_SatInfo SatInfo[12];}stru_GPSGSV;#define NMEA_NULL 0x00 //GPS语句类型#define NMEA_GPGGA 0x01#define NMEA_GPGSA 0x02#define NMEA_GPGSV 0x04#define NMEA_GPRMC 0x08void GPS(void);void ShowLongitude(u8,u8);void ShowLatitude(u8,u8);void ShowGPSTime(u8,u8);void GPSSateDataInit(void);bit ReciveOK(void);void ShowSatSNR(u8,u8);#endifGPS.C//-------------------------------------------------------//GPS 解析模块By wowbanui//版本历史:// 2010/08 v0.1 初始版本// 2011/03 v0.2 注释掉不需要的字段,部分数据直接处理成数值, // 减少内存占用.输出部分直接调用LCD命令,移植需更改//---------------------------------------------------------#include "GPS.H"#include "S1D15E06.h"static u8 NMEA_CMD=NMEA_NULL; //NMEA 语句static u8 NMEA_CMD_Buff[]="$GPxxx,"; //NMEA 语句类型缓存static u8 NMEA_CMD_Index=0; //读取CMD字符的个数static bit NMEA_CMD_Parsered=0; //CMD类型解析完毕static u8 NMEA_DAT_Block=0; //NMEA 数据字段号从0开始static u8 NMEA_DAT_BlockIndex=0; //NMEA 数据每个字段内字符索引从0开始static bit NMEA_CMD_Start=0; //NMEA 语句开始. 检测到$ 时置1static bit ReciveFlag=0; //数据接收完成. 最后一条GPRMC 语句发送完毕置1,static u8 ucTempA=0; //存储解析两位数字用的的十位临时变量static u8 SateInfoIndex=0; ////static u8 ucTemp[5];stru_GPSRMC xdata GPS_RMC_Data;stru_GPSGGA xdata GPS_GGA_Data;stru_GPSGSA xdata GPS_GSA_Data;stru_GPSGSV xdata GPS_GSV_Data;void GPSSateDataInit(void){u8 i;for(i=0;i<12;i++){GPS_GSV_Data.SatInfo[i].SatID=0x00;GPS_GSA_Data.HDOP[0]=0x01;GPS_GSA_Data.HDOP[1]=0x01;GPS_GSA_Data.HDOP[2]=0x01;GPS_GSA_Data.HDOP[3]=0x01;}}void ShowGPSTime(u8 ucLX,u8 ucLY){GPS_RMC_Data.UTCDateTime[3]+=8;if (GPS_RMC_Data.UTCDateTime[3]>23) {GPS_RMC_Data.UTCDateTime[3]-=24; //Hour GPS_RMC_Data.UTCDateTime[2]++; //Dayif (((GPS_RMC_Data.UTCDateTime[1]==1)||\ (GPS_RMC_Data.UTCDateTime[1]==3)||\ (GPS_RMC_Data.UTCDateTime[1]==5)||\ (GPS_RMC_Data.UTCDateTime[1]==7)||\ (GPS_RMC_Data.UTCDateTime[1]==8)||\ (GPS_RMC_Data.UTCDateTime[1]==10)||\ (GPS_RMC_Data.UTCDateTime[1]==12))&&\ (GPS_RMC_Data.UTCDateTime[2]>31)){GPS_RMC_Data.UTCDateTime[2]=1;//DayGPS_RMC_Data.UTCDateTime[1]++;//Month}if (((GPS_RMC_Data.UTCDateTime[1]==4)||\(GPS_RMC_Data.UTCDateTime[1]==6)||\(GPS_RMC_Data.UTCDateTime[1]==9)||\(GPS_RMC_Data.UTCDateTime[1]==11))&&\(GPS_RMC_Data.UTCDateTime[2]>30)){GPS_RMC_Data.UTCDateTime[2]=1;GPS_RMC_Data.UTCDateTime[1]++;}if((GPS_RMC_Data.UTCDateTime[1]==2)&&(GPS_RMC_Data.UTC DateTime[2]>28)){GPS_RMC_Data.UTCDateTime[2]=1;GPS_RMC_Data.UTCDateTime[1]++;}if(GPS_RMC_Data.UTCDateTime[1]>12){GPS_RMC_Data.UTCDateTime[1]=1;GPS_RMC_Data.UTCDateTime[0]++;}}LCD_SetLocation(ucLX,ucLY);LCD_PutChar(GPS_RMC_Data.UTCDateTime[0]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[0]%10+'0');LCD_PutChar('/');LCD_PutChar(GPS_RMC_Data.UTCDateTime[1]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[1]%10+'0');LCD_PutChar('/');LCD_PutChar(GPS_RMC_Data.UTCDateTime[2]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[2]%10+'0');LCD_PutChar(' ');LCD_PutChar(GPS_RMC_Data.UTCDateTime[3]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[3]%10+'0');LCD_PutChar(':');LCD_PutChar(GPS_RMC_Data.UTCDateTime[4]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[4]%10+'0');LCD_PutChar(':');LCD_PutChar(GPS_RMC_Data.UTCDateTime[5]/10+'0');LCD_PutChar(GPS_RMC_Data.UTCDateTime[5]%10+'0');}void ShowLatitude(u8 ucX,u8 ucY) // N dd'mm'ss.ssss{unsigned long s;LCD_SetLocation(ucX,ucY);LCD_PutChar(GPS_RMC_Data.NS); //北纬南纬标志LCD_PutChar(' ');LCD_PutChar(GPS_RMC_/doc/d61302 2198.html,titude[0]); //度, 直接提取LCD_PutChar(GPS_RMC_/doc/d61302 2198.html,titude[1]);LCD_PutChar(0x02); //度(°)符号LCD_PutChar(GPS_RMC_/doc/d61302 2198.html,titude[2]); //分, 直接提取LCD_PutChar(GPS_RMC_/doc/d61302 2198.html,titude[3]);//直接提取后四位分并扩大10000倍为整数存于Long型, 避免小数运算s=(GPS_RMC_/doc/d613022198.html,titud e[5]-'0')*1000+\(GPS_RMC_/doc/d613022198.html,tit ude[6]-'0')*100+\(GPS_RMC_/doc/d613022198.html,tit ude[7]-'0')*10+\(GPS_RMC_/doc/d613022198.html,tit ude[8]-'0');s*=60; //转换成单位秒(")LCD_PutChar('\'');LCD_PutChar(s/100000+'0');s=s%100000;LCD_PutChar(s/10000+'0');s=s%10000;LCD_PutChar('.');LCD_PutChar(s/1000+'0');s=s%1000;LCD_PutChar(s/100+'0');s=s%100;LCD_PutChar(s/10+'0');s=s%10;LCD_PutChar(s+'0');LCD_PutChar('"');}void ShowLongitude(u8 ucX,u8 ucY){unsigned long s;LCD_SetLocation(ucX,ucY);LCD_PutChar(GPS_RMC_Data.EW);LCD_PutChar(GPS_RMC_Data.Longitude[0]);LCD_PutChar(GPS_RMC_Data.Longitude[1]); LCD_PutChar(GPS_RMC_Data.Longitude[2]); LCD_PutChar(0x02);LCD_PutChar(GPS_RMC_Data.Longitude[3]); LCD_PutChar(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;LCD_PutChar('\'');LCD_PutChar(s/100000+'0');s=s%100000;LCD_PutChar(s/10000+'0');LCD_PutChar('.');s=s%10000;LCD_PutChar(s/1000+'0');s=s%1000;LCD_PutChar(s/100+'0');s=s%100;LCD_PutChar(s/10+'0');s=s%10;LCD_PutChar(s+'0');LCD_PutChar('"');}void ShowSatSNR(u8 ucX,u8 ucY){u8 i,j,Mode;for (i=0;i<12;i++){Mode=1;for (j=0;j<12;j++){if(GPS_GSV_Data.SatInfo[i].SatID==GPS_GSA_Data.SatUsedList[j]) Mode=3;}LCD_SNRBar(i*8,6,GPS_GSV_Data.SatInfo[i].SNR/4,Mode);}}bit ReciveOK(void){if (ReciveFlag)ReciveFlag=0;return 1;}else{return 0;}}static void ParserGPGGA(void){switch(SBUF){case '*': //语句结束NMEA_CMD_Start=0;break;case ',': //该字段结束NMEA_DAT_Block++;NMEA_DAT_BlockIndex=0;break;default: //字段字符switch(NMEA_DAT_Block) //判断当前处于哪个字段{case 5: //<6> GPS状态0=未定位, 1=非差分定位, 2=差分定位, 6=正在估算GPS_GGA_Data.PositionFix=SBUF;break;case 6: //<7> 正在使用的卫星数量00~12GPS_GGA_Data.SatUsed[NMEA_DAT_BlockIndex]=SBUF;break;case 8: //<9> 海拔高度-9999.9~99999.9GPS_GGA_Data.Altitude[NMEA_DAT_BlockIndex]=SBUF;break;}NMEA_DAT_BlockIndex++; //字段字符索引++, 指向下一个字符}}static void ParserGPRMC(void){switch(SBUF)case '*':NMEA_CMD_Start=0;ReciveFlag=1; //接收完毕, 可以处理break;case ',':NMEA_DAT_Block++;NMEA_DAT_BlockIndex=0;break;default:switch(NMEA_DAT_Block){case 0: //<1> UTC时间hhmmss.mmmswitch(NMEA_DAT_BlockIndex){case 0:case 2:case 4:ucTempA=SBUF-'0';break;case 1:GPS_RMC_Data.UTCDateTime[3]=ucT empA*10+SBUF-'0';break;case 3:GPS_RMC_Data.UTCDateTime[4]=ucT empA*10+SBUF-'0';break;case 5:GPS_RMC_Data.UTCDateTime[5]=ucT empA*10+SBUF-'0';break;}break;case 1: //<2> 定位状态A=有效定位, V=无效定位GPS_RMC_Data.Status=SBUF;break;case 2: //<3> 纬度ddmm.mmmmGPS_RMC_/doc/d613022198.html,titu de[NMEA_DAT_BlockIndex]=SBUF;break;case 3: //<4> 纬度半球N/SGPS_RMC_Data.NS=SBUF;break;case 4: //<5> 经度dddmm.mmmmGPS_RMC_Data.Longitude[NMEA_DAT_BlockIndex]=SBUF; break;case 5: //<6> 经度半球E/WGPS_RMC_Data.EW=SBUF;break;case 6: //<7> 地面速率000.0~999.9 节GPS_RMC_Data.Speed[NMEA_DAT_BlockIndex]=SBUF; break;case 7: //<8> 地面航向000.0~359.9 度, 以真北为参考基准GPS_RMC_Data.Course[NMEA_DAT_BlockIndex]=SBUF; break;case 8: //<9> UTC日期ddmmyyswitch(NMEA_DAT_BlockIndex){case 0:case 2:case 4:ucTempA=SBUF-'0';break;case 1:GPS_RMC_Data.UTCDateTime[2]=ucT empA*10+SBUF-'0'; break;case 3:GPS_RMC_Data.UTCDateTime[1]=ucT empA*10+SBUF-'0'; break;case 5:GPS_RMC_Data.UTCDateTime[0]=ucT empA*10+SBUF-'0';break;}break;}NMEA_DAT_BlockIndex++;}}static void ParserGPGSA(void){switch(SBUF){case '*':NMEA_CMD_Start=0;break;case ',':NMEA_DAT_Block++;NMEA_DAT_BlockIndex=0;//清空已使用卫星号, 避免上次数据干扰if((NMEA_DAT_Block>=2)||(NMEA_DAT_Block<=13)) GPS_GSA_Data.SatUsedList[NMEA_DAT_Block-2]=0x00; break;default:switch(NMEA_DAT_Block){case 0: //<1>模式M=手动, A=自动GPS_GSA_Data.Mode=SBUF;break;case 1: //<2>定位型式1=未定位, 2=二维定位, 3=三维定位GPS_GSA_Data.Mode2=SBUF;break;case 2: //<3> PRN 01~32 使用中的卫星编号case 3:case 4:case 5:case 6:case 7:case 8:case 9:case 10:case 11:case 12:case 13:switch(NMEA_DAT_BlockIndex){case 0:ucTempA=SBUF-'0';break;case 1:GPS_GSA_Data.SatUsedList[NMEA_DAT_Block-2]=ucTempA*10+SBUF-'0';break;}break;case 14: //<4> PDOP 位置精度因子0.5~99.9GPS_GSA_Data.PDOP[NMEA_DA T_BlockIndex]=SBUF;break;case 15: //<5> HDOP 水平精度因子0.5~99.9GPS_GSA_Data.HDOP[NMEA_DAT_BlockIndex]=SBUF;break;case 16: //<6> VDOP 垂直精度因子0.5~99.9GPS_GSA_Data.VDOP[NMEA_DAT_BlockIndex]=SBUF; break;}NMEA_DAT_BlockIndex++;}}static void ParserGPGSV(void){switch(SBUF){case '*':NMEA_CMD_Start=0;break;case ',':NMEA_DAT_Block++;NMEA_DAT_BlockIndex=0;break;default:switch(NMEA_DAT_Block){case 1: //<2> 本句GSV的编号if (SBUF=='1') SateInfoIndex=0;//解析到第一句GSV 语句则判断卫星信息从心开始break;case 2: //<3> 可见卫星的总数00~12switch(NMEA_DAT_BlockIndex){case 0:ucTempA=SBUF-'0';break;GPS_GSV_Data.SatInView=ucTempA*10+SBUF-'0';break;}break;case 3: //<4> 卫星编号01~32case 7:case 11:case 15:switch(NMEA_DAT_BlockIndex){case 0:ucTempA=SBUF-'0';break;case 1:GPS_GSV_Data.SatInfo[SateInfoIndex].SatID=ucT empA*10+S BUF-'0';GPS_GSV_Data.SatInfo[SateInfoIndex].SNR=0x00;//清空信噪比数据, 避免上次数据干扰//因为当卫星信噪比无时GPS输出的NMEA数据中信噪比字段没有,//而导致直接跳到下一字段, 此时上次若有数据则直接会残留下来SateInfoIndex++;//卫星信息索引+1, 以下都-1处理//同上, 避免放于"信噪比"字段为空时处理不到break;}break;case 6: //<7>讯号噪声比C/No 00~99case 10:case 18:switch(NMEA_DAT_BlockIndex){case 0:ucTempA=SBUF-'0';break;case 1:GPS_GSV_Data.SatInfo[SateInfoIndex-1].SNR=ucT empA*10+SBUF-'0';break;}break;}NMEA_DAT_BlockIndex++;}}void GPS(void){LED_G=0;if(NMEA_CMD_Start){ //解析到以$开始的NMEA 语句, 进入NMEA 解析流程: if(NMEA_CMD_Parsered){ //CMD语句类型解析完毕, 根据类型条用解析函数switch(NMEA_CMD){case NMEA_GPGGA:ParserGPGGA();break;case NMEA_GPGSA:ParserGPGSA();break;case NMEA_GPGSV:ParserGPGSV();break;case NMEA_GPRMC:ParserGPRMC();break;default: //无法识别的格式, 复位NMEA_CMD=NMEA_NULL;NMEA_CMD_Parsered=0;NMEA_CMD_Index=1;NMEA_CMD_Start=0;}}else{ //需要解析CMD语句类型switch(SBUF){case ',': //第一个字段结束if(NMEA_CMD_Buff[4]=='G'&&NMEA_CMD_Buff[5]=='A') NMEA_CMD=NMEA_GPGGA;if(NMEA_CMD_Buff[4]=='S'&&NMEA_CMD_Buff[5]=='A')NMEA_CMD=NMEA_GPGSA;if(NMEA_CMD_Buff[5]=='V') NMEA_CMD=NMEA_GPGSV;if(NMEA_CMD_Buff[5]=='C') NMEA_CMD=NMEA_GPRMC;//此处如果都不成立, 即语句不被识别, 则NMEA_CMD为NULL 或其他,//则转为根据类型解析时会跳转到无法识别的格式, 而后复位NMEA_CMD_Parsered=1;NMEA_CMD_Index=1;NMEA_DAT_Block=0;NMEA_DAT_BlockIndex=0;break;case '*':NMEA_CMD_Start=0;break;default: //处于第一个字段中, 继续接收NMEA_CMD_Buff[NMEA_CMD_Index]=SBUF;NMEA_CMD_Index++;if (NMEA_CMD_Index>6) NMEA_CMD_Start=0;// CMD 超过6个字符, (数组越界, 导致死机)// 则判断不是正常的CMD语句, 则略过此句.}}}else{ //未解析到$, 循环接收并判断直到$if (SBUF=='$'){ //接收到$, 下一个字符即为类型判断字符, 先进行相关变量初始化NMEA_CMD_Buff[0]=SBUF;NMEA_CMD_Start=1; //下次调用则进入NMEA 解析流程:NMEA_CMD_Index=1; //从头存放GPS类型字符到变量NMEA_CMD_Parsered=0;NMEA_CMD=NMEA_NULL;NMEA_DAT_Block=0;NMEA_DAT_BlockIndex=0;}}LED_G=1;//变量定义char code TIME_AREA= 8; //时区//GPS数据存储数组unsigned char JD[10]; //经度unsigned char JD_a; //经度方向unsigned char WD[9]; //纬度unsigned char WD_a; //纬度方向unsigned char date[6]; //日期unsigned char time[6]; //时间unsigned char speed[5]={'0','0','0','0','0'}; //速度unsigned char high[6]; //高度unsigned char angle[5]; //方位角unsigned char use_sat[2]; //使用的卫星数unsigned char total_sat[2]; //天空中总卫星数unsigned char lock; //定位状态//串口中断需要的变量unsigned char seg_count; //逗号计数器unsigned char dot_count; //小数点计数器unsigned char byte_count; //位数计数器unsigned char cmd_number; //命令类型unsigned char mode; //0:结束模式,1:命令模式,2:数据模式unsigned char buf_full; //1:整句接收完成,相应数据有效。
NMEA 0183是一种用于数据通信协议,常用于GPS和其他导航设备。
在C语言中解析NMEA 数据通常涉及以下几个步骤:1. **读取数据**:从GPS设备或其他源读取NMEA数据流。
2. **解析数据**:将NMEA数据字符串分解成其各个组成部分,如句子类型、时间、位置、速度等。
3. **验证校验和**:NMEA协议中的每个句子都有一个校验和,用于验证数据的完整性。
4. **提取有用信息**:根据需要提取有用的数据,如经纬度、速度、航向等。
5. **转换数据格式**:将提取的数据转换为所需的格式,例如从字符串转换为浮点数。
6. **处理数据**:根据需要对数据进行处理,例如计算距离或方位。
以下是一个简单的C语言示例,用于解析NMEA GPGGA(全球定位系统固定数据)句子:```c#include <stdio.h>#include <stdlib.h>#include <string.h>// 假设GPGGA句子的最大长度#define GPGGA_MAX_LENGTH 128// GPGGA句子的结构体typedef struct {char sentenceType[3]; // 句子类型,例如"GPGGA"double time; // 时间(小时)double latitude; // 纬度(度)double longitude; // 经度(度)int satellites; // 卫星数量double hdop; // 水平精度(DOP)double vdop; // 垂直精度(DOP)double checksum; // 校验和} GPGGA;// 解析GPGGA句子的函数int parseGPGGA(char *buffer, GPGGA *gpgga) {int i, j;double field[10];char *token;// 去除字符串前后的空格char *cleanBuffer = buffer;while (*cleanBuffer == ' ') cleanBuffer++;while (*cleanBuffer != '\0' && *cleanBuffer == ' ') cleanBuffer++;// 解析句子类型strncpy(gpgga->sentenceType, cleanBuffer, 3);cleanBuffer += 3;// 解析时间token = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[0]);gpgga->time = field[0];}cleanBuffer = token + 1;// 解析纬度token = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[1]);gpgga->latitude = field[1]; }cleanBuffer = token + 1;// 解析经度token = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[2]);gpgga->longitude = field[2]; }cleanBuffer = token + 1;// 解析卫星数量token = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%d", &field[3]);gpgga->satellites = field[3]; }cleanBuffer = token + 1;// 解析HDOPtoken = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[4]);gpgga->hdop = field[4];}cleanBuffer = token + 1;// 解析VDOPtoken = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[5]);gpgga->vdop = field[5];}cleanBuffer = token + 1;// 解析校验和token = strtok(cleanBuffer, ",");if (token != NULL) {sscanf(token, "%lf", &field[6]);gpgga->checksum = field[6]; }// 返回校验和字段的索引for (i = 0; i < 6; i++) {if (field[i] == gpgga->checksum) {return i;}}return -1; // 校验和不匹配}int main() {// 假设有一个GPGGA句子char buffer[GPGGA_MAX_LENGTH] = "GPGGA,123519,4807.038,N,01131.000,E,8,0.8,0.9,00000+00";// 解析GPGGA句子GPGGA gpgga;int result = parseGPGGA。
gpgga解析代码 javaGPS是全球定位系统(Global Positioning System)的简称,它是一种利用卫星进行定位、导航和定时服务的技术。
在GPS中,GPGGA 是一种特定的数据格式,用于提供卫星定位信息。
本文将介绍如何使用Java编写GPGGA解析代码,以从GPS接收器的输出中提取有用的定位信息。
在编写代码之前,首先需要了解GPGGA数据格式的结构。
GPGGA字符串由多个字段组成,每个字段之间以逗号分隔。
以下是GPGGA数据格式的各个字段及其含义:1. GPGGA标识:表示此字符串为GPGGA数据。
2. UTC时间:卫星定位的时间戳,格式为HHMMSS.SSS。
3. 纬度:以度为单位的纬度值,格式为ddmm.mmmm。
4. 纬度半球:表示纬度的北半球(N)或南半球(S)。
5. 经度:以度为单位的经度值,格式为dddmm.mmmm。
6. 经度半球:表示经度的东半球(E)或西半球(W)。
7. 定位质量指示符:表示定位质量的指示符,取值范围为0-8,其中0表示定位失效,1表示使用导航定位解算,2表示使用差分定位解算。
8. 使用卫星数量:表示用于定位解算的卫星数量。
9. HDOP:水平精度因子(Horizontal Dilution of Precision),表示定位的精度。
10. 海拔:以米为单位的海拔高度。
11. 高度单位:表示海拔高度的单位,一般为米。
12. 大地水准面偏差:相对于WGS-84椭球模型的大地水准面偏差。
13. 大地水准面偏差单位:表示大地水准面偏差的单位。
现在我们可以开始编写GPGGA解析代码了。
首先,需要创建一个名为"GPGGA解析代码.java"的Java文件,然后按照以下步骤编写代码:1. 导入所需的Java库:```import java.util.Arrays;```2. 创建一个名为"GPGGA解析代码"的Java类,并添加一个名为"main"的主方法:```public class GPGGA解析代码 {public static void main(String[] args) {// 在此处添加代码}}```3. 在"main"方法中,定义一个示例GPGGA字符串:```String gpggaString ="$GPGGA,123519.00,4807.038,S,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*4 7";```4. 使用String的split方法将GPGGA字符串分割为多个字段,并存储到一个数组中:```String[] gpggaFields = gpggaString.split(",");```5. 按照GPGGA数据格式的顺序,通过数组的索引提取各个字段的值,并将它们存储到适当的变量中:```String utcTime = gpggaFields[1];String latitude = gpggaFields[2];String latitudeHemisphere = gpggaFields[3];String longitude = gpggaFields[4];String longitudeHemisphere = gpggaFields[5];String positionQualityIndicator = gpggaFields[6];String satelliteCount = gpggaFields[7];String hdop = gpggaFields[8];String altitude = gpggaFields[9];String altitudeUnit = gpggaFields[10];String geoidSeparation = gpggaFields[11];String geoidSeparationUnit = gpggaFields[12];```6. 打印提取的定位信息:```System.out.println("UTC时间:" + utcTime);System.out.println("纬度:" + latitude + " " + latitudeHemisphere); System.out.println("经度:" + longitude + " " + longitudeHemisphere); System.out.println("定位质量指示符:" + positionQualityIndicator); System.out.println("使用卫星数量:" + satelliteCount);System.out.println("HDOP:" + hdop);System.out.println("海拔:" + altitude + " " + altitudeUnit);System.out.println("大地水准面偏差:" + geoidSeparation + " " + geoidSeparationUnit);```7. 运行代码,输出解析结果。
GPGGA协议解析GPGGA协议是Global Positioning System (GPS) 接收器输出的一种NMEA(National Marine Electronics Association)协议。
它包含了GPS接收器获取到的位置、时间、定位质量等相关信息。
GPGGA协议的解析是GPS数据处理中非常重要的一步,下面将详细介绍GPGGA协议的解析过程。
$GPGGA,hhmmss.sss,llll.ll,a,yyyyy.yy,a,x,xx,x.x,x.x,M,x.x,M, x.x,xxxx*hh<CR><LF>解析过程中,第一步是确定协议格式的正确性。
GPGGA协议的首字母必须是'$',最后两个字符必须是回车符(<CR>)和换行符(<LF>)。
在确定格式正确后,可以开始解析协议内容。
首先,我们需要提取协议中的每个字段。
以逗号(,)作为分隔符,将协议内容分割成多个字段。
第一个字段是协议的名称,通常是$GPGGA。
第二个字段是UTC时间,格式为hhmmss.sss。
第三个字段是纬度信息,格式为llll.ll。
第四个字段是纬度半球(N or S)。
第五个字段是经度信息,格式为yyyyy.yy。
第六个字段是经度半球(E or W)。
第七个字段表示定位质量指示符,可以为0-8的数字。
第八个字段是卫星数量。
第九个字段是水平精度因子。
第十个字段是天线离海平面的高度,单位为米。
第十一个字段是大地水准面相对于 WGS84 椭球面的高度偏差,单位为米。
第十二个字段是差分GPS数据期限,单位为秒。
最后一个字段是差错校验。
将每个字段提取出来后,可以进一步对其进行解析和处理。
首先,需要将UTC时间字段中的时、分、秒提取出来,并转换为相应的数字格式。
纬度和经度字段中的度数也需要进行提取和转换。
定位质量指示符用于判断GPS定位的质量,一般为0代表无效定位,1代表GPS定位解,2代表DGPS定位解。
GPS编码格式及C语⾔解码有关磁偏⾓和地图定位的问题:地图的⽅向:上北、下南、左西、右东是⼤多数地图的⽅向,但这可不是通⽤原则,如果地图上有⽅向标,可以通过⽅向标了解到这些。
地磁极是接近南极和北极的,但并不和南极、北极重合,⼀个约在北纬72°、 西经96°处;⼀个约在南纬70°、东经150°处。
磁北极距地理北极⼤约相差1500km。
现在磁北极的位置在加拿⼤北⽅,在⼀天中磁北极的位置也是不停的变动,它的轨迹⼤致为⼀椭圆形,磁北极平均每天向北以40m。
⽬前磁北极正在逐渐离开加拿⼤,⼤约于2005年进⼊俄罗斯境内。
东经25度地区,磁偏⾓在1-2度之间;北纬25度以上地区,磁偏⾓⼤于2度;若在西经低纬度地区,磁偏⾓是5-20度;西经45度以上,磁偏⾓为25-50度。
在我国,正常情况下,磁偏⾓最⼤可达6度,⼀般情况为2-3度。
在我国除部分磁⼒异常的地⽅外,⼀般磁偏⾓都是西偏。
磁偏⾓还是不断有规律变化的,地图上的磁偏⾓只是测图时的磁偏⾓(磁北⽐真北偏左,加上磁偏⾓;磁北⽐真北偏右,减去磁偏⾓;在我国⼀般是加上)。
使⽤地图本⾝所注的磁偏⾓要注意出版年限,地图太⽼误差较⼤。
GPS 0183协议GGA、GLL、GSA、GSV、RMC、VTG解释$GPGGA例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000*1F字段0:$GPGGA,语句ID,表明该语句为Global Positioning System Fix Data(GGA)GPS定位信息字段1:UTC 时间,hhmmss.sss,时分秒格式字段2:纬度ddmm.mmmm,度分格式(前导位数不⾜则补0)字段3:纬度N(北纬)或S(南纬)字段4:经度dddmm.mmmm,度分格式(前导位数不⾜则补0)字段5:经度E(东经)或W(西经)字段6:GPS状态,0=未定位,1=⾮差分定位,2=差分定位,3=⽆效PPS,6=正在估算字段7:正在使⽤的卫星数量(00 - 12)(前导位数不⾜则补0)字段8:HDOP⽔平精度因⼦(0.5 - 99.9)字段9:海拔⾼度(-9999.9 - 99999.9)字段10:地球椭球⾯相对⼤地⽔准⾯的⾼度字段11:差分时间(从最近⼀次接收到差分信号开始的秒数,如果不是差分定位将为空)字段12:差分站ID号0000 - 1023(前导位数不⾜则补0,如果不是差分定位将为空)字段13:校验值$GPGLL例:$GPGLL,4250.5589,S,14718.5084,E,092204.999,A*2D字段0:$GPGLL,语句ID,表明该语句为Geographic Position(GLL)地理定位信息字段1:纬度ddmm.mmmm,度分格式(前导位数不⾜则补0)字段2:纬度N(北纬)或S(南纬)字段3:经度dddmm.mmmm,度分格式(前导位数不⾜则补0)字段4:经度E(东经)或W(西经)字段5:UTC时间,hhmmss.sss格式字段6:状态,A=定位,V=未定位字段7:校验值$GPGSA例:$GPGSA,A,3,01,20,19,13,,,,,,,,,40.4,24.4,32.2*0A字段0:$GPGSA,语句ID,表明该语句为GPS DOP and Active Satellites(GSA)当前卫星信息字段1:定位模式,A=⾃动⼿动2D/3D,M=⼿动2D/3D字段2:定位类型,1=未定位,2=2D定位,3=3D定位字段3:PRN码(伪随机噪声码),第1信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段4:PRN码(伪随机噪声码),第2信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段5:PRN码(伪随机噪声码),第3信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段6:PRN码(伪随机噪声码),第4信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段7:PRN码(伪随机噪声码),第5信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段8:PRN码(伪随机噪声码),第6信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段9:PRN码(伪随机噪声码),第7信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段10:PRN码(伪随机噪声码),第8信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段11:PRN码(伪随机噪声码),第9信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段12:PRN码(伪随机噪声码),第10信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段13:PRN码(伪随机噪声码),第11信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段14:PRN码(伪随机噪声码),第12信道正在使⽤的卫星PRN码编号(00)(前导位数不⾜则补0)字段15:PDOP综合位置精度因⼦(0.5 - 99.9) 字段16:HDOP⽔平精度因⼦(0.5 - 99.9)字段17:VDOP垂直精度因⼦(0.5 - 99.9)字段18:校验值$GPGSV例:$GPGSV,3,1,10,20,78,331,45,01,59,235,47,22,41,069,,13,32,252,45*70字段0:$GPGSV,语句ID,表明该语句为GPS Satellites in View(GSV)可见卫星信息字段1:本次GSV语句的总数⽬(1 - 3)字段2:本条GSV语句是本次GSV语句的第⼏条(1 - 3)字段3:当前可见卫星总数(00 - 12)(前导位数不⾜则补0)字段4:PRN 码(伪随机噪声码)(01 - 32)(前导位数不⾜则补0)字段5:卫星仰⾓(00 - 90)度(前导位数不⾜则补0)字段6:卫星⽅位⾓(00 - 359)度(前导位数不⾜则补0)字段7:信噪⽐(00-99)dbHz字段8:PRN 码(伪随机噪声码)(01 - 32)(前导位数不⾜则补0)字段9:卫星仰⾓(00 - 90)度(前导位数不⾜则补0)字段10:卫星⽅位⾓(00 - 359)度(前导位数不⾜则补0)字段11:信噪⽐(00-99)dbHz字段12:PRN 码(伪随机噪声码)(01 - 32)(前导位数不⾜则补0)字段13:卫星仰⾓(00 - 90)度(前导位数不⾜则补0)字段14:卫星⽅位⾓(00 - 359)度(前导位数不⾜则补0)字段15:信噪⽐(00-99)dbHz字段16:校验值$GPRMC例:$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最⼩定位信息 字段1:UTC时间,hhmmss.sss格式字段2:状态,A=定位,V=未定位字段3:纬度ddmm.mmmm,度分格式(前导位数不⾜则补0)字段4:纬度N(北纬)或S(南纬)字段5:经度dddmm.mmmm,度分格式(前导位数不⾜则补0)字段6:经度E(东经)或W(西经)字段7:速度,节,Knots字段8:⽅位⾓,度字段9:UTC⽇期,DDMMYY格式字段10:磁偏⾓,(000 - 180)度(前导位数不⾜则补0)字段11:磁偏⾓⽅向,E=东W=西字段16:校验值$GPVTG例:$GPVTG,89.68,T,,M,0.00,N,0.0,K*5F字段0:$GPVTG,语句ID,表明该语句为Track Made Good and Ground Speed(VTG)地⾯速度信息字段1:运动⾓度,000 - 359,(前导位数不⾜则补0)字段2:T=真北参照系字段3:运动⾓度,000 - 359,(前导位数不⾜则补0)字段4:M=磁北参照系字段5:⽔平运动速度(0.00)(前导位数不⾜则补0)字段6:N=节,Knots字段7:⽔平运动速度(0.00)(前导位数不⾜则补0)字段8:K=公⾥/时,km/h字段9:校验值GPS编码格式及C语⾔解码GPS接收机只要处于⼯作状态就会源源不断地把接收并计算出的GPS导航定位信息通过串⼝传送到计算机中。
GPS数据解析函数1. 简介GPS(全球定位系统)是一种利用卫星信号进行地理定位的技术,它已广泛应用于导航、地图、交通、军事等领域。
GPS数据解析函数是一种用于解析GPS数据的功能模块,它可以将从GPS接收器获取的原始数据转化为有意义的位置信息,包括经度、纬度、海拔高度、速度等。
2. GPS数据结构GPS数据通常采用NMEA(National Marine Electronics Association)协议进行传输,其中最常用的数据格式是NMEA 0183。
该格式定义了一种文本协议,每个数据包都以’$’开头,以回车换行符结束。
2.1 数据包格式一个典型的NMEA 0183数据包由多个字段组成,字段之间用逗号进行分隔。
数据包的第一个字段表示数据的类型,后续字段表示具体的数据内容。
例如,$GPGGA表示全球定位系统定位信息数据。
2.2 常用数据字段在GPS数据解析函数中,常用的数据字段有:•经度和纬度:表示地理位置的坐标信息;•海拔高度:表示当前位置的海拔高度;•速度:表示当前位置的移动速度;•方向:表示当前移动方向的角度。
3. GPS数据解析算法GPS数据解析函数的核心是解析接收到的GPS数据包,提取其中的关键信息。
以下是一种常用的GPS数据解析算法:3.1 接收数据GPS数据解析函数首先需要从GPS接收器获取原始数据。
通常,GPS接收器会以串口的形式将数据传输给计算机。
3.2 分割数据包将接收到的数据按照回车换行符进行分割,得到多个完整的数据包。
然后遍历这些数据包,逐个解析。
3.3 解析数据包对于每个数据包,首先判断其类型。
如果是需要的数据类型(例如GPGGA),则解析后续字段;否则忽略该数据包。
3.4 提取信息对于需要解析的数据包,根据字段的位置提取其中的信息。
例如,经度和纬度字段通常位于数据包的第三个和第四个位置。
3.5 数据格式转换将提取到的信息进行格式转换,以便后续的使用。
例如,将经度和纬度字段的度、分、秒格式转换为十进制格式。
解析GPS RMC 语句 跳至 [1] [全屏预览] view sourceprint?001 /*002 * 解析串口接收到的字节串(RMC )推荐定位信息003 * $GPRMC,013946,A,3202.1855,N,11849.0769,E,0.05,218.30,111105,4.5,W ,A*20..004 * $GPRMC,<1> ,2,<3> ,4,<5> ,6,<7> ,<8> ,<9> ,10,11,12*hh<CR><LF> 005 * <1>UTC 时间,hhmmss (时分秒)格式 <2> 定位状态,A=有效定位,V=无效定位006 * <3>纬度ddmm.mmmm (度分)格式(前面的0也将被传输) <4> 纬度半球N (北半球)或S (南半球)007 * <5>经度dddmm.mmmm (度分)格式(前面的0也将被传输) <6> 经度半球E (东经)或W (西经)008 * <7>地面速率(000.0~999.9节,前面的0也将被传输) <8> 地面航向(000.0~359.9度,以真北为参考基准,前面的0也将被传输)009 * <9> UTC 日期,ddmmyy (日月年)格式 <10> 磁偏角(000.0~180.0度,前面的0也将被传输)010 * <11>磁偏角方向,E (东)或W (西) <12> 模式指示(仅NMEA0183 3.00版本输出,A=自主定位,D=差分,E=估算,N=数据无效)011 *012 *013 * 返回值 0 正确 1校验失败 2非GPRMC 信息 3无效定位 4格式错误 5校验错误014 */015 public int parseGPRMC(String by)016 {017 if(by==null||by.isEmpty())//判断非空018 return 4;019 if(checksum(by.getBytes())==false)//计算校验和并与语句中的校验和比较020 return 5;021 MyStringTokenizer str=new MyStringTokenizer(new String(by),',');022 String temp=null;023 temp=str.nextToken();//取第一个子串即标记024 if(!temp.equals("$GPRMC"))// 确定是$GPRMC025 return 2;026027 temp=str.nextToken();// 时间028 hour=(short)Integer.parseInt(temp.substring(0,2)); 029 minute=(short)Integer.parseInt(temp.substring(2,4)); 030 second=(short)Float.parseFloat(temp.substring(4)); 031 temp=str.nextToken();// 定位状态032 if(temp.length()!=1)//无033 return 42;034 else if(temp.charAt(0)=='V')//为A 则有效 为V 则无效 035 return 3;036 temp=str.nextToken();// 纬度037 lat=Double.parseDouble(temp.substring(0,2));// 纬度-度 038 lat+=Double.parseDouble(temp.substring(2))/60;// 纬度-分 039 temp=str.nextToken();// 纬度半球040 if(temp.length()!=1)041 return 44;042 else if(temp.charAt(0)=='N')043 lats='N';044 else if(temp.charAt(0)=='S')045 lats='S';046 else //错误信息047 return 45;048 temp=str.nextToken();// 经度049 lng=Double.parseDouble(temp.substring(0,3));// 经度-度050 lng+=Double.parseDouble(temp.substring(3))/60;// 经度-分 051 temp=str.nextToken();// 经度半球052 if(temp.length()!=1)053 return 47;054 else if(temp.charAt(0)=='E')055 lngs='E';056 else if(temp.charAt(0)=='W')057 lngs='W';058 else059 return 48;060 temp=str.nextToken();// 地面速率061 if(!temp.isEmpty())062 {063 speed=Double.parseDouble(temp)*1.852;//速度单位转换为千米每小时064 }065 this.valid=true;//转换成功,产生的数据有效066 return 0;067 }068069070071 private boolean checksum(byte[] b)072 {073 byte chk=0;// 校验和074 byte cb=b[1];// 当前字节075 int i=0;076 if(b[0]!='$')077 return false;078 for(i=2;i<b.length;i++)//计算校验和079 {080 if(b[i]=='*')081 break;082 cb=(byte)(cb^b[i]);083 }084 if(i!=b.length-3)//校验位不正常085 return false;086 i++;087 byte[] bb=new byte[2];//用于存放语句后两位088 bb[0]=b[i++];bb[1]=b[i];089 try090 {091 chk=(byte)Integer.parseInt(new String(bb),16);//后两位转换为一个字节092 }093 catch(Exception e)//后两位无法转换为一个字节,格式错误 094 {095 return false;096 }097 System.out.println("校验信息");098 System.out.println(" 原文:"+chk);099 System.out.println(" 计算:"+cb);100101 return chk==cb;//计算出的校验和与语句的数据是否一致 102 }。
摘要GPS是利用卫星,在全球范围内实时进行定位、导航的系统,目前可以说是最热门、最受人瞩目的一项科技。
它具有在海、陆、空进行全方位实时三维导航与定位能力,并提供实时、全天候和全球性的导航服务。
所以,船舶可以根据GPS的解析信息来确保稳定而精确最佳航线。
随着科技的迅速发展,各种新型的航海仪器均已实现了数字化和计算机化,目前各种航海仪器之间的通信一班采用NMEA-0183接口。
NMEA-0183现已成为GPS导航设备统一的标准协议,主要包括GPGGA,GPRMC,GPVTG,GPGSV,GPZDA等语句格式,其中GPVTG的功能就是解析卫星信号中的对地速度信息,将其信号序列变为非专业人员可读取的文字。
本文针对当前比较普及的GPS系统,介绍了GPS通信的NMEA-0183协议、GPVTG信息解析的实现方法。
关键字:GPS NMEA-0183协议 GPVTG目录前言 (1)第1章绪论 (2)1.1 GPS定位系统原理 (2)1.2 C语言编程特点 (3)第2章NMEA-0183协议的简介 (4)2.1 NMEA-0183协议的格式定义 (4)2.2 NMEA-0183的应用领域 (5)2.3 NMEA-0183数据处理中的注意事项 (5)第3章设计方案 (6)3.1 主要方案思路及步骤 (6)3.1.1主流程图 (6)3.1.2调用函数流程图: (7)3.1.3解析程序的编写及流程图 (7)3.2程序的编写及调试结果 (8)3.2.1 最终程序及其注解 (8)3.2.2调试步骤及显示结果 (11)3.3文本输出显示结果: (13)第4章小结 (14)4.1 设计中遇到的问题及解决方案 (14)4.2心得体会 (15)[参考文献] (17)前言GPS系统是美国研制的全球性、全天候的卫星导航系统。
它主要是为陆、海、空三大领域提供实时、全天候和全球性的导航服务,并用于情报收集、核爆监测和应急通讯等一些军事目的;其基本原理是根据高速运动的卫星瞬间位置作为已知的起算数据,采用空间距离后方交会的方法,确定待测点的位置;主要特点有:高精度、全天候、高效率、多功能、操作简便、应用广泛等。
GPS数据提取解析源码GPS source data extraction analysis, we can refer to learn fromGPS数据解析数据拆分\坐标转换\显示线路图\源代码逐条读取gps数据然后进行拆分解析,坐标转换,绘制线路。
很好的示例多多交流学习。
本程序是基于VC++ 建立的单文档工程。
废话少说,直接上代码//获取子字符串个数int GetSubStrCount(CString str,char cFlag){cFlag = ',';int i = 0;BOOL isHas = FALSE;for (int iStart = -1; -1 != (iStart = str.Find(cFlag,iStart+1)) ; i++){isHas = TRUE;}if (!isHas){return 0;}else{return i+1;}}//获取子字符串// i 序号0CString GetSubStr(CString str,int i,char cFlag){cFlag = ',';int iStart = -1;int iEnd = 0;int j = 0;int iStrCount;iStrCount = GetSubStrCount(str,cFlag);if (i>iStrCount -1 || i<0){str = "";return str;}else{//do nothing}if (i == iStrCount-1){i = iStrCount;for (;j<i-1;j++){iStart = str.Find(cFlag , iStart+1);}return str.Mid(iStart+1 , str.GetLength()-iStart-1);}else{//do nothing}for (; j<i; j++){iStart = str.Find(cFlag , iStart+1);}iEnd = str.Find(cFlag , iStart+1);return str.Mid(iStart+1 , iEnd-iStart-1);}//数据解析CString CGpsDataView::Analyzing(CString str){CString subStr[20];char cFlag = ',';int j = GetSubStrCount(str,cFlag); //得到该行的子字符串个数CStdioFile wFile;wFile.Open("save.txt",CFile::modeCreate | CFile::modeWrite | CFile::typeText);//将数据写入文件for (int i=0;i<j;i++){subStr[i] = GetSubStr(str,i,cFlag); }//GPGGA数据if (subStr[0] == "$GPGGA"){CoordCovert(subStr[2],subStr[4]);//提取时间subStr[1].Insert(2,':');subStr[1].Insert(5,':');subStr[1].Insert(0," UTC时间:");//提取纬度if (subStr[3] == 'N'){subStr[2].Insert(11,"分");subStr[2].Insert(2,"度");subStr[2].Insert(0," 北纬");}else if (subStr[3] == 'S'){subStr[2].Insert(11,"分");subStr[2].Insert(2,"度");subStr[2].Insert(0," 南纬");}//提取经度if (subStr[5] == 'E'){subStr[4].Insert(12,"分");subStr[4].Insert(3,"度");subStr[4].Insert(0," 东经");}else if (subStr[5] == 'W'){subStr[4].Insert(12,"分");subStr[4].Insert(3,"度");subStr[4].Insert(0," 西经");}//判断GPS状态CString GpsState;if (subStr[6] == '0'){GpsState = " GPS状态:无定位.";}else if (subStr[6] == '1'){GpsState = " GPS状态:无差分校正定位.";}else if (subStr[6] == '2'){GpsState = " GPS状态:差分校正定位.";}else if (subStr[6] == '9'){GpsState = " GPS状态:用星历计算定位.";}//提取卫星数subStr[7].Insert(0," 卫星数:");//提取平面位置精度因子subStr[8].Insert(0," 平面位置精度因子:");//天线海拔高度subStr[9].Insert(strlen(subStr[9]),subStr[10]);subStr[9].Insert(0," 天线海拔高度:");//海平面分离度subStr[11].Insert(strlen(subStr[11]),subStr[12]);subStr[11].Insert(0," 海平面分离度:");subStr[0] += subStr[1];subStr[0] += subStr[2];subStr[0] += subStr[4];subStr[0] += GpsState;subStr[0] += subStr[7];subStr[0] += subStr[8];subStr[0] += subStr[9];subStr[0] += subStr[11];//////////////////////////////////////MessageBox(subStr[0]);wFile.WriteString(subStr[0]);//将数据写入文件}//GPZDA数据else if (subStr[0] == "$GPZDA"){//提取时间subStr[1].Insert(2,':');subStr[1].Insert(5,':');subStr[1].Insert(0," UTC时间:");//提取日期subStr[2].Insert(strlen(subStr[2]),"日");subStr[2].Insert(0,"月");subStr[2].Insert(0,subStr[3]);subStr[2].Insert(0,"年");subStr[2].Insert(0,subStr[4]);subStr[2].Insert(0,' ');//当地时域描述subStr[5].Insert(strlen(subStr[5]),"小时");if (strlen(subStr[6]) > 3){subStr[6] = subStr[6].Left(2);}else{subStr[6] = '0';}subStr[6] += "分";subStr[6].Insert(0,subStr[5]);subStr[6].Insert(0," 当地时域:");subStr[0] += subStr[1];subStr[0] += subStr[2];subStr[0] += subStr[6];//////////////////////////////MessageBox(subStr[0]);wFile.WriteString(subStr[0]);//将数据写入文件}//GPGSA数据else if (subStr[0] == "$GPGSA"){//卫星捕获模式,以及定位模式CString CatchLocation;if (subStr[1] == 'M'){if (subStr[2] == '1'){CatchLocation = " 手动捕获卫星,未定位!";}else if (subStr[2] == '2'){CatchLocation = " 手动捕获卫星,2D定位!";}else if (subStr[2] == '3'){CatchLocation = " 手动捕获卫星,3D定位!";}}else if (subStr[1] == 'A'){if (subStr[2] == '1'){CatchLocation =" 自动捕获卫星,未定位!";}else if (subStr[2] == '2'){CatchLocation =" 自动捕获卫星,2D定位!";}else if (subStr[2] == '3'){CatchLocation =" 自动捕获卫星,3D定位!";}}//各卫星定位结果subStr[3].Insert(0," 各卫星定位结果:");subStr[3] += ' ';subStr[4].Insert(0,subStr[3]);subStr[4] += ' ';subStr[5].Insert(0,subStr[4]);subStr[5] += ' ';subStr[6].Insert(0,subStr[5]);subStr[6] += ' ';subStr[7].Insert(0,subStr[6]);subStr[7] += ' ';subStr[8].Insert(0,subStr[7]);subStr[8] += ' ';subStr[9].Insert(0,subStr[8]);subStr[9] += ' ';subStr[10].Insert(0,subStr[9]);subStr[10] += ' ';subStr[11].Insert(0,subStr[10]);subStr[11] += ' ';subStr[12].Insert(0,subStr[11]);subStr[12] += ' ';subStr[13].Insert(0,subStr[12]);subStr[13] += ' ';subStr[14].Insert(0,subStr[13]);subStr[14] += ' ';//空间(三维)位置精度因子subStr[15].Insert(0," 空间(三维)位置精度因子:");//平面位置精度因子subStr[16].Insert(0," 平面位置精度因子:");//高度位置精度因子subStr[17] = subStr[17].Left(3);subStr[17].Insert(0," 高度位置精度因子:");subStr[0] += CatchLocation;subStr[0] += subStr[14];subStr[0] += subStr[15];subStr[0] += subStr[16];subStr[0] += subStr[17];/////////////////////////////MessageBox(subStr[0]);wFile.WriteString(subStr[0]);//将数据写入文件}//GPGSV数据else if (subStr[0] == "$GPGSV"){///////////////////////////MessageBox(subStr[0]);//卫星编号、卫星仰角(0~90度)、卫星方位角(0~359度)、信噪比subStr[4].Insert(0,"卫星编号:");subStr[5].Insert(0," 仰角:");subStr[6].Insert(0," 方位角:");subStr[7].Insert(0," 信噪比:");subStr[4] += subStr[5];subStr[4] += subStr[6];subStr[4] += subStr[7];///////////////////MessageBox(subStr[4]);subStr[8].Insert(0,"卫星编号:");subStr[9].Insert(0," 仰角:");subStr[10].Insert(0," 方位角:");subStr[11].Insert(0," 信噪比:");subStr[8] += subStr[9];subStr[8] += subStr[10];subStr[8] += subStr[11];////////////////////////MessageBox(subStr[8]);subStr[12].Insert(0,"卫星编号:");subStr[13].Insert(0," 仰角:");subStr[14].Insert(0," 方位角:");subStr[15].Insert(0," 信噪比:");subStr[12] += subStr[13];subStr[12] += subStr[14];subStr[12] += subStr[15];/////////////////////MessageBox(subStr[12]);subStr[16].Insert(0,"卫星编号:");subStr[17].Insert(0," 仰角:");subStr[18].Insert(0," 方位角:");if (strlen(subStr[19]) > 3){subStr[19] = subStr[19].Left(2);}else{subStr[19] = '0';}subStr[19].Insert(0," 信噪比:");subStr[16] += subStr[17];subStr[16] += subStr[18];subStr[16] += subStr[19];/////////////////////////////////MessageBox(subStr[16]);wFile.WriteString(subStr[16]);//将数据写入文件}return str;}//读取文件数据并解析void CGpsDataView::OnFileRead(){// TODO: 在此添加命令处理程序代码CStdioFile myFile;CString oneLine;char cFlag = ',';CString subStr[20];//读取GPS数据文件if(!myFile.Open(("gps.txt"),CFile::modeRead | CFile::typeText)){AfxMessageBox(_T("打开文件错误!"));return;}else{/*do nothing*/}while (myFile.ReadString(oneLine))//读一行{//////////MessageBox(oneLine);int j = GetSubStrCount(oneLine,cFlag); //得到该行的子字符串个数//校验if(CheckNum(oneLine)){////////////MessageBox(_T("数据校验...接收正确!..."));for (int i=0;i<j;i++){subStr[i] = GetSubStr(oneLine,i,cFlag);//MessageBox(subStr[i]);}Analyzing(oneLine); //解析}else{AfxMessageBox(_T("数据校验..接收错误!..."));}}myFile.Close();}//*********************************************************************************** ************//坐标转换//度分秒--弧度double Dms2Rad(double Dms){double Degree, Miniute;double Second;int Sign;double Rad;if(Dms >= 0){Sign = 1;}else{Sign = -1;}Dms = fabs(Dms); //绝对值Degree = floor(Dms); // 取度floor(2.800)= 2.0000Miniute = floor(fmod(Dms * 100.0, 100.0)); //fmod 计算余数Second = fmod(Dms * 10000.0, 100.0);Rad = Sign * (Degree + Miniute / 60.0 + Second / 3600.0) * PI / 180.0;return Rad;}double Rad2Dms(double Rad){double Degree, Miniute;double Second;int Sign;double Dms;if(Rad >= 0){Sign = 1;}else{Sign = -1;}Rad = fabs(Rad * 180.0 / PI);Degree = floor(Rad);Miniute = floor(fmod(Rad * 60.0, 60.0));Second = fmod(Rad * 3600.0, 60.0);Dms = Sign * (Degree + Miniute / 100.0 + Second / 10000.0);return Dms;}//正算公式bool GpsPoint::BL2xy(){//大地测量学基础(吕志平乔书波北京:测绘出版社2010.03)double X; //由赤道至纬度为B的子午线弧长(P106 5-41)double N; //椭球的卯酉圈曲率半径double t;double t2;double m;double m2;double ng2;double cosB;double sinB;X = A1 * B * 180.0 / PI + A2 * sin(2 * B)+ A3 * sin(4 * B) + A4 * sin(6 * B);sinB = sin(B);cosB = cos(B);t = tan(B);t2 = t * t;N = a /sqrt(1 - e2 * sinB * sinB);m = cosB * (L - L0);m2 = m * m;ng2 = cosB * cosB * e2 / (1 - e2);//P156 (6-63公式)x = X + N * t *(( 0.5 + ( (5 - t2 + 9 * ng2 + 4 * ng2 * ng2)/ 24.0 + (61 - 58 * t2 + t2 * t2) * m2 / 720.0) * m2)* m2);y = N * m * ( 1 + m2 * ( (1 - t2 + ng2) / 6.0 + m2 * ( 5 - 18 * t2 + t2 * t2 + 14 * ng2 - 58 * ng2 * t2 ) / 120.0));//y += 500000;return true;}//反算公式bool GpsPoint::xy2BL(){double sinB;double cosB;double t;double t2;double N; //椭球的卯酉圈曲率半径double ng2;double V;double yN;double preB0;double B0;double eta;//y -= 500000;B0 = x / A1;do{preB0 = B0;B0 = B0 * PI / 180.0;B0 = (x - (A2 * sin(2 * B0) + A3 * sin(4 * B0) + A4 * sin(6 * B0))) / A1;eta = fabs(B0 - preB0);}while(eta > 0.000000001);B0 = B0 * PI / 180.0;B = Rad2Dms(B0);sinB = sin(B0);cosB = cos(B0);t = tan(B0);t2 = t * t;N = a / sqrt(1 - e2 * sinB * sinB);ng2 = cosB * cosB * e2 / (1 - e2);V = sqrt(1 + ng2);yN = y / N;B = B0 - (yN * yN - (5 + 3 * t2 + ng2 - 9 * ng2 * t2) * yN * yN * yN * yN/ 12.0 + (61 + 90 * t2 + 45 * t2 * t2) * yN * yN * yN * yN * yN * yN / 360.0)* V * V * t / 2;L = L0 + (yN - (1 + 2 * t2 + ng2) * yN * yN * yN / 6.0 + (5 + 28 * t2 + 24* t2 * t2 + 6 * ng2 + 8 * ng2 * t2) * yN * yN * yN * yN * yN / 120.0) / cosB;return true;}//设置中央子午线bool GpsPoint::SetL0(double dL0){L0 = Dms2Rad(dL0);return true;}//将度分秒经纬度转换为弧度后再转换为平面坐标bool GpsPoint::SetBL(double dB, double dL){B = Dms2Rad(dB);L = Dms2Rad(dL);BL2xy();return true;}bool GpsPoint::GetBL(double *dB, double *dL){*dB = Rad2Dms(B);*dL = Rad2Dms(L);return true;}//将平面坐标转换为(弧度)经纬度bool GpsPoint::Setxy(double dx, double dy){x = dx;y = dy;xy2BL();return true;}bool GpsPoint::Getxy(double *dx, double *dy){*dx = x;*dy = y;return true;}GpsPoint_Krasovsky::GpsPoint_Krasovsky(){a = 6378245; //长半径f = 298.3; //扁率的倒数(扁率:(a-b)/a)e2 = 1 - ((f - 1) / f) * ((f - 1) / f); //第一偏心率的平方e12 = (f / (f - 1)) * (f / (f - 1)) - 1; //第二偏心率的平方// 克拉索夫斯基椭球A1 = 111134.8611;A2 = -16036.4803;A3 = 16.8281;A4 = -0.0220;}//*************坐标转换bool CGpsDataView::CoordCovert(CString latitude, CString longitude){double bbb = atof(latitude);double lll = atof(longitude);//度分格式转换为度分秒格式bbb = Dm2Dms(bbb);lll = Dm2Dms(lll);double MyL0 ; //中央子午线double MyB = bbb ; //33 d 44 m 55.6666 sdouble MyL = lll ; //3度带,109 d 22 m 33.4444 s//计算当地中央子午线,3度带MyL0 = fabs(MyL);MyL0 = floor(MyL);MyL0 = 3 * floor(MyL0 / 3 );GpsPoint_Krasovsky MyPrj;MyPrj.SetL0(MyL0);MyPrj.SetBL(MyB, MyL);double OutMyX;double OutMyY;OutMyX = MyPrj.x; //正算结果:坐标xOutMyY = MyPrj.y; //结果:坐标yCString strTemp1;CString strTemp2;CString strTemp3;CString strTemp4;strTemp1.Format("%f",OutMyX);strTemp2.Format("%f",OutMyY);strTemp1.Insert(0,"x = ");strTemp2.Insert(0," , y = ");strTemp2.Insert(0,strTemp1);strTemp2.Insert(0," 坐标转换: ");strTemp3.Format("%f12",MyB);strTemp4.Format("%f12",MyL);strTemp3.Insert(0,"B = ");strTemp4.Insert(0," L = ");strTemp4.Insert(0,strTemp3);strTemp2.Insert(0,strTemp4);//MessageBox(strTemp2);DrawPoint(MyPrj.x,MyPrj.y);return true;}//================================== //度分格式转换为度分秒格式double CGpsDataView::Dm2Dms(double Dm){double Dms;double temp;temp = Dm - floor(Dm);temp = (temp * 60) / 100;Dm = floor(Dm);Dm += temp;Dm = Dm /100;Dms = Dm;return Dms;}//*************绘制线路显示出路线int count1=0;bool bFirst = true;double xTemp;double yTemp;void CGpsDataView::DrawPoint(double X, double Y){Sleep(100);//X = (X - floor(X))*100;//Y = (Y - floor(Y))*100;if (bFirst){xTemp=X;yTemp=Y;bFirst=false;}CDC *pDC=GetDC();CPen pen(PS_SOLID,3,RGB(255,20,20));CPen *pOldPen;CBrush *pOldBrush;CBrush *pBrush=CBrush::FromHandle( (HBRUSH)GetStockObject(NULL_BRUSH) );pOldPen=pDC->SelectObject(&pen);pOldBrush=pDC->SelectObject(pBrush);int a=(int)(100.0-(X-xTemp)*800.0);int b=(int)(100.0+(Y-yTemp)*800.0);//绘制点显示路径pDC->Ellipse(a,b,a+5,b+5);//计数count1=count1+1;pDC->SelectObject( pOldBrush );pDC->SelectObject( pOldPen );CString str;str.Format("%.1f,%.1f,%d,%d,%d",X-xTemp,Y-yTemp,a,b,count1);pDC->TextOut(10,10,str);}。
GPS模拟C语言第一篇:GPS模拟C语言GPS模拟# include # include # includeusing namespace std;ifstream fin(“1.txt”);//ofstream fout(“data_out.txt”);// 1 double x[5] = {-1, 0, 300, 0, 300};double y[5] = {-1, 450, 450, 0, 0};double t[5];double A, B, D,c = 2982000, p, r;double pi = 3.141592653;double xx, yy;//三角形算法void cal(int sign, double t1, double t2, double x1, double y1, double x2, double y2, double px, double py){double tt1 = c * t1, tt2 = c * t2;double q, ac;A = x2 *(x1*x1 + y1*y1x1 *(x2*x2 + y2*y2tt1*tt1)tt2*tt2);D = tt1 *(x2*x2 + y2*y2tt2 *(x1*x1 + y1*y1ac;r =(x1*x1 + y1*y10)< 1e-6){switch(h){case 1:cal(-1, t[2], t[4], 300, 0, 300,-450, 0, 450);break;case 2: cal(-1, t[1], t[3],-300, 0,-300,-450,300, 450);break;case 3: cal(1, t[1], t[2], 0, 450, 300, 450, 0, 0);break;case 4: cal(1, t[1], t[2],-300, 450, 0, 450, 300, 0);break;}break;} } system(“pause”);return 0;声源定位#include #include using namespace std;#define Max 50 int N=10;double xi[10];double yi[10];double ti[10][3];double det(double a[Max][Max],int n){ int i,j,start;double k,temp,result=1;for(start=0;start<=n-2;start++){i=1;while(a[start][start]==0&&start+i<=n-1){for(j=start;j<=n-1;j++){temp=-1*a[start][j];a[start][j]=a[start+i][j];a[start+i][j]=temp;}i++;}if(start+i==n)continue;for(i=start+1;i<=n-1;i++){k=a[i][start]/a[start][start];for(j=start;j<=n-1;j++)a[i][j]=a[i][j]-k*a[start][j];} } for(i=0;i<=n-1;i++)result*=a[i][i];return result;} int equalation(double a[Max][Max+1],double r[Max],int n){ double det(double a[Max][Max],int n);double det0[Max][Max],det1[Max][Max];int i,j,k;for(i=0;i<=n-1;i++)for(j=0;j<=n-1;j++)det0[i][j]=a[i][j];if(det(det0,n)==0)return 0;for(k=0;k<=n-1;k++){for(i=0;i<=n-1;i++)for(j=0;j<=n-1;j++){det0[i][j]=a[i][j];det1[i][j]=a[i][j];}for(i=0;i<=n-1;i++)det1[i][k]=a[i][n];r[k]=det(det1,n)/det(det0,n);} return 1;} double sqr(double x){ return x*x;} double g(double x,double y,double c,double xi,double yi,double ti){ return sqr(xi-x)+sqr(yi-y)-sqr(c*ti);} double fx(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum+=g(x,y,c,xi[i],yi[i],ti[i][k-1])*(xi[i]-x);return sum;} double fy(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum+=g(x,y,c,xi[i],yi[i],ti[i][k-1])*(yi[i]-y);return sum;} double fc(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum+=g(x,y,c,xi[i],yi[i],ti[i][k-1])*sqr(ti[i][k-1]);return sum;} double fxx(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*sqr(xi[i]-x)-g(x,y,c,xi[i],yi[i],ti[i][k-1]);return sum;} double fxy(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*(yi[i]-y)*(xi[i]-x);return sum;} double fxc(doublex,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++) sum=sum-2*c*sqr(ti[i][k-1])*(xi[i]-x);return sum;} double fyx(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*(xi[i]-x)*(yi[i]-y);return sum;} double fyy(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*sqr(yi[i]-y)-g(x,y,c,xi[i],yi[i],ti[i][k-1]);return sum;} double fyc(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*c*sqr(ti[i][k-1])*(yi[i]-y);return sum;} double fcx(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*(xi[i]-x)*sqr(ti[i][k-1]);return sum;} double fcy(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*(yi[i]-y)*sqr(ti[i][k-1]);return sum;} double fcc(double x,double y,double c,int k){ int i;double sum=0;for(i=0;i<=N-1;i++)sum=sum-2*c*sqr(sqr(ti[i][k-1]));return sum;} int main(){ int i=0,k;double x,y,c,x0,y0,c0;double a[Max][Max+1],r[Max];freopen(“1.txt”, “r”, stdin);freopen(“1_out.txt”, “w”, stdout);for(i=0;i<=9;i++){} cin>>xi[i]>>yi[i];xi[i] /= 10;yi[i] /= 10;cin>>ti[i][0]>>ti[i][1]>>ti[i][2];for(k=1;k<=3;k++){ cin>>x> >y;c=0.2;do {x0=x;y0=y;c0=c;i++;a[0][0]=fxx(x,y,c,k);a[0][1]=fxy(x,y,c,k);a[0][2]=fxc(x,y,c,k);a[1][0]=fyx(x,y,c,k);a[1][1]=fyy(x,y,c,k);a[1][2]=fyc(x,y,c,k);a[2][0]=fcx(x, y,c,k);a[2][1]=fcy(x,y,c,k);a[2][2]=fcc(x,y,c,k);a[0][3]=x*a[0][0]+y*a[ 0][1]+c*a[0][2]-fx(x,y,c,k);a[1][3]=x*a[1][0]+y*a[1][1]+c*a[1][2]-fy(x,y,c,k);a[2][3]=x*a[2][0]+y*a[2][1]+c*a[2][2]-fc(x,y,c,k);if(equalation(a,r,3)==0){cout<return 0;}x=r[0];y=r[1];c=r[2];} while(abs(x-x0)+abs(y-y0)+abs(c-c0)>=1e-6);cout<<<<第二篇:C语言模拟ATM机一、实验目的通过设计一个ATM机模拟操作的程序,全面运用课程的主要知识点,巩固对模块化程序设计、文件操作的理解,提高软件编程能力。
公交车智能报站系统的设计与实现黄金明,等公交车智能报站系统的设计与实现DesignandImplementationofGPSPassengerInformationSystemforBuses管舍明索明蓦(曲阜师范大学电气信息与自动化学院,山东日照”6826)摘要:针对公交车驾驶员手动报站存在的安全隐患问题,提出了一种新的智能报站系统设计。
该系统由SPCE061A单片机、GPS、LCD和键盘组成,通过实时比较GPS信号与存储在NANDFlash中的站点信息来确定当前站点信息,实现智能播报。
与传统的手动语音播报方式相比,该系统具有更好的安全性、智能性、稳定性,并且播报结果准确可靠。
关键词:SPCE061AGPSNANDFlash智能报站车辆导航中图分类号:TP273.5文献标志码:AAbstract:Toovercomethehiddendangerofmanualbroadcastinginbuses,anovelintelligentpassengerinformationsystemhasbeenpro-posed.ThesystemiscomposedofSPCE061Asinglechipcomputer。
GPS-LCDandkeyboard.ThroughcomparingGPSsignalandthebus・stopinformationstoredinNANDFlashinrealtimetodetermineinformationofthecomingstop,thentheinformationisreleased.Thesystemoffersmoresafety,intelligent。
accurateandstablepassengerinformationthanthoseprovidedbymanualbroadcasting.Keywords:SPCE061AGPSNANDFlashIntelligentbroadcastingVehiclenavigationO引言伴随着国内公共交通事业的发展,公交车报站的方式已经有了很大的改变。