|
楼主 |
发表于 2014-4-1 23:01:12
|
显示全部楼层
GPStest:14/4/1 22:55:12
altitude= 255
weixingshu= 5
latitude= latitude:xxxx.xxxx N
longitude= longitude:xxxxx.xxxx E
仅适用于经纬度小数点后4位的情况,如果是5位的,则要做相应的修改
至于通用的又要复杂一点,要判断逗号的位置,类似于提取年月日的过程(部分数据长度不确定),所以,这里以节约资源的名义偷工减料了
- char temp1[6],GPGGA[80],GPRMC[80];
-
- String test1= "";
- String latitude = ""; //纬度
- String longitude = ""; //经度
-
-
- int jsq1,jsq2,jsq3;
- boolean change1,change2,change3;
- int GPGGAlong,GPRMClong;//GPGGA、GPRMC的长度
- int yihuoyunsuan;
- boolean jiaoyanjieguoA,jiaoyanjieguoB;
-
-
- //UTC +8(北京时间)时、分、秒、年、月、日
- int utc8s,utc8f,utc8m,utc8n,utc8y,utc8r;
- //小月的数组
- int xiaoyue[5]={4,6,9,11};
- //日进位,月进位,年进位,大小月判断值
- boolean rijinwei,yuejinwei,nianjinwei,xiaoyueok;
- boolean dingweiok;//定位ok
- int weixingshu;//有效卫星数
- int altitude; //海拔
-
-
- void setup() {
- Serial.begin(9600);
- }
-
-
- void loop() {
-
- jsq1=0;
- jsq2=0;
- jsq3=0;
-
- change1=0;
- change2=0;
- change3=0;
-
- GPGGAlong=0;
- GPRMClong=0;
- jiaoyanjieguoA=0;
- jiaoyanjieguoB=0;
-
-
- //日进位,月进位
- rijinwei=0;
- yuejinwei=0;
- nianjinwei=0;
- xiaoyueok=0;
-
- dingweiok=0;//默认未定位
-
- weixingshu=0;//有效卫星数
- altitude=0; //海拔
-
- while (Serial.available() > 0) { //监听串口输入
-
- if(!change1){
-
- if(jsq1<4){
- temp1[jsq1]=Serial.read();
- delayMicroseconds(1200);
- jsq1++; //jsq1最终值为4,temp1:0-4共计5个字节
-
- if(jsq1==4){//值得注意的是,此时,temp1[4]并没有赋值
- temp1[4]=Serial.read(); //为temp1[4]赋值
- delayMicroseconds(1200);
- panduan1();//此时,收集到5个字符,可以进行判断
- }
-
-
- }else{
-
- //传递过程,temp1只有5个字节
- temp1[0]=temp1[1];
- temp1[1]=temp1[2];
- temp1[2]=temp1[3];
- temp1[3]=temp1[4];
- temp1[4]=Serial.read();
-
- delayMicroseconds(1200);
-
- panduan1();
-
- }
-
- ///////////////////////////////////////////////////////////////////////////
- }else if(change2){
-
- //GPGGA
- GPGGA[jsq1]=Serial.read();
- delayMicroseconds(1200);
-
- if(GPGGA[jsq1-2]=='*'){ //GPGGA字符串的结束
- change1=0;//恢复以前的状态,继续由临时数组temp1判断
- change2=0;//不再执行这段代码
- GPGGAlong=jsq1-2;//记录这段字符串的长度GPGGAlong=jsq1-3+1(0位有一个字节)
- jsq1=0;//计数器1还原
-
- }else jsq1++;
-
- //////////////////////////////////////////////////////////////////////////
- }else if(change3){
- //GPRMC
-
- GPRMC[jsq1]=Serial.read();
- delayMicroseconds(1200);
-
- if(GPRMC[jsq1-2]=='*'){
- change1=0;//恢复以前的状态,继续由临时数组temp1判断
- change2=0;//不再执行这段代码
- GPRMClong=jsq1-2;
- jsq1=0;//计数器1还原
-
- }else jsq1++;
-
- }
-
-
-
- }
-
-
-
-
- /////////////////////////////////////////////////////异或运算,验证其数据可信
-
- if(GPGGAlong>0){ //字符串GPGGA的验证
- for(int col=0;col<GPGGAlong;col++){
- if(col==0)yihuoyunsuan=GPGGA[col];
- else yihuoyunsuan=yihuoyunsuan ^ GPGGA[col];
- }
- panduan2();
- if(test1[0]==GPGGA[GPGGAlong+1] && test1[1]==GPGGA[GPGGAlong+2]){
- //一致,则说明数据是有效的,输出校验结果
- jiaoyanjieguoA=1;
- }else{
- //不一致
- jiaoyanjieguoA=0;
- }
- }
-
-
- if(GPRMClong>0){//字符串GPRMC的验证
- for(int col=0;col<GPRMClong;col++){
- if(col==0)yihuoyunsuan=GPRMC[col];
- else yihuoyunsuan=yihuoyunsuan ^ GPRMC[col];
- }
- panduan2();
- if(test1[0]==GPRMC[GPRMClong+1] && test1[1]==GPRMC[GPRMClong+2]){
- //一致,则说明数据是有效的,输出校验结果
- jiaoyanjieguoB=1;
- }else{
- //不一致
- jiaoyanjieguoB=0;
- }
- }
-
-
- /////////////////////////////////////////////////
-
- if(jiaoyanjieguoA && jiaoyanjieguoB){ //要求GPGGA、GPRMC同时通过奇偶验证才能进行下一步
-
- gpstime(); //gps时间提取,日月年、时分秒、转为北京时间
- Serial.println(test1);//这个字符串是gpstime
-
- jingduweidu();//拾取经度、维度
-
- if(dingweiok)haiba();//在定位有效的情况下拾取海拔、有效卫星数
-
-
- Serial.print("altitude= ");
- Serial.println(altitude);
-
- Serial.print("weixingshu= ");
- Serial.println(weixingshu);
-
-
- Serial.print("latitude= ");
- Serial.println(latitude);
-
- Serial.print("longitude= ");
- Serial.println(longitude);
- Serial.print("GPGGA[jsq1]=");
- Serial.println(GPGGA);
- Serial.print("GPRMC[jsq1]=");
- Serial.println(GPRMC);
- Serial.println("----------------------");
- }
-
-
-
-
- //最后的收尾工作
- if(GPRMClong>0 || GPGGAlong>0){
- //置0
- for(int col=0;col<80;col++)GPGGA[col]=0;
- for(int col=0;col<80;col++)GPRMC[col]=0;
- }
-
- }
-
-
- void panduan1(){ //找到特定字符串的开始
-
- //清空字符串,且数组转字符串
- //神奇的地球,数组==“字符串”貌似不能成立
- test1 = String(temp1[0]);
- test1 += temp1[1];
- test1 += temp1[2];
- test1 += temp1[3];
- test1 += temp1[4];
-
-
-
-
- if(test1=="GPGGA"){//字符串GPGGA
-
- // Serial.println("find GPGGA");
- change1=1;
- change2=1;
- change3=0;
-
- //交接工作,接下来的数据都会给GPGGA
- GPGGA[0]=temp1[0];
- GPGGA[1]=temp1[1];
- GPGGA[2]=temp1[2];
- GPGGA[3]=temp1[3];
- GPGGA[4]=temp1[4];
- jsq1=5;
-
- }else if(test1=="GPRMC"){//字符串GPRMC
-
- // Serial.println("find GPRMC");
- change1=1;
- change2=0;
- change3=1;
-
- GPRMC[0]=temp1[0];
- GPRMC[1]=temp1[1];
- GPRMC[2]=temp1[2];
- GPRMC[3]=temp1[3];
- GPRMC[4]=temp1[4];
- jsq1=5;
- }
-
- }
-
- void panduan2(){ //异或运算的结果转化为字符串,以便于比较
-
-
- if(yihuoyunsuan==0){
- //校验数10进制为0,直接填充字符串00
- test1="00";
- }else if(yihuoyunsuan>15){
- //此时转换为16进制以后,天然有2位,很理想,不用处理
- test1 = String(yihuoyunsuan,HEX);
- }else{
- //校验数10进制为1-15时,转换为16进制就只有1位数,所以需要在前面填0
- test1 = "0";
- test1 += String(yihuoyunsuan,HEX);
- }
-
- test1.toUpperCase();//将其字母转换为大写
-
- }
-
- void gpstime(){
-
-
- //时间部分:UTC转为UTC+8,北京时间(时:分:秒)
- //时:
- test1 = String(GPRMC[6]);//复用test1这个数组来节约内存
- test1 += GPRMC[7];
- utc8s=test1.toInt()+8;
- if(utc8s>23)rijinwei=1;//提示后面程序换算为北京时间的时候,日要+1天
- utc8s=utc8s%24;//字符串转换为整数,参与运算
- //分:
- test1 = String(GPRMC[8]);//复用test1这个数组来节约内存
- test1 += GPRMC[9];
- utc8f=test1.toInt();//字符串转换为整数,参与运算
- //秒:
- test1 = String(GPRMC[10]);//复用test1这个数组来节约内存
- test1 += GPRMC[11];
- utc8m=test1.toInt();//字符串转换为整数,参与运算
- ////////////////////////////////////////////////
- //提取UTC日期(日、月、年),这个日期位于GPRMC第9个数据中,所以定位第九个逗号的位置即可
- jsq2=0;
- jsq3=0;
- for(int col=0;col<80;col++){
- if(GPRMC[col]==',')jsq2++;
- if(jsq2==9){
- jsq3=col;//找到9第个逗号的前一个位置,循环0开始,0的时候就已经后推了一位置
- col=80;//找到9个逗号就跳出循环
- }
- }
- //日
- test1 = String(GPRMC[jsq3+1]);//复用test1这个数组来节约内存,9第个逗号前一位后推2个位置
- test1 += GPRMC[jsq3+2];
- utc8r=test1.toInt();//字符串转换为整数,参与运算
- //月
- test1 = String(GPRMC[jsq3+3]);//复用test1这个数组来节约内存
- test1 += GPRMC[jsq3+4];
- utc8y=test1.toInt();//字符串转换为整数,参与运算
- //年
- test1 = String(GPRMC[jsq3+5]);//复用test1这个数组来节约内存
- test1 += GPRMC[jsq3+6];
- utc8n=test1.toInt();//字符串转换为整数,参与运算
- jsq2=0; //防止以后会用,先行清零
- jsq3=0;
- //讨论日、月、年进位(大月、小月、平年、闰年的问题)
- if(rijinwei){
- //先讨论2月的问题
- if(utc8y==2 && utc8r==28){
- if(utc8n%4==0)utc8r=29;//闰年可加一天
- else {
- utc8r=1;
- yuejinwei=1;
- }
- }else{
- //判断大小月
- for(int col=0;col<4;col++){
- if(xiaoyue[col]==utc8y)xiaoyueok=1;
- }
- if(xiaoyueok && utc8r==30){ //小月最后一天
- utc8r=1;
- yuejinwei=1;
- }else if(!xiaoyueok && utc8r==31){ //大月最后一天
- utc8r=1;
- yuejinwei=1;
- }else{
- utc8r++;//剩下的情况自加1就可以了
- }
- }
- }
- if(yuejinwei && utc8y==12){ //最后一月
- utc8y=1;
- nianjinwei=1;
- }else if(yuejinwei){
- utc8y++;
- }
- if(nianjinwei)utc8n++;
- ////////////////
- test1 = "GPStest:";
- test1 += utc8n;
- test1 += "/";
- test1 += utc8y;
- test1 += "/";
- test1 += utc8r;
- test1 += " ";
- test1 += utc8s;
- test1 += ":";
- test1 += utc8f;
- test1 += ":";
- test1 += utc8m;
-
- }
-
-
- void jingduweidu(){
-
- if(GPRMC[17]=='A'){//已定位
- dingweiok=1;//已定位
-
- latitude = "latitude:"; //纬度
- for(int col=19;col<28;col++) latitude += GPRMC[col];
- latitude += " ";
- latitude += GPRMC[29];
-
- longitude = "longitude:"; //经度
- for(int col=31;col<41;col++) longitude += GPRMC[col];
- longitude += " ";
- longitude += GPRMC[42];
-
- }
-
- }
-
-
- void haiba(){
-
- //有效卫星数
- test1 = String(GPGGA[44]);
- test1 += GPGGA[45];
- weixingshu=test1.toInt();//字符串转换为整数,参与运算
-
- //海拔
- //找到开始的逗号,与结束的逗号位置
- for(int col=47;col<64;col++){
- if(GPGGA[col]==',' && jsq2==0)jsq2=col;//海拔开始的逗号
- if(col>jsq2){
- if(GPGGA[col]==','){
- jsq3=col;//海拔结束的逗号
- col=64;//跳出循环
- }
- }
- }
-
- //拾取海拔高度
- for(int col=jsq2+1;col<jsq3;col++){
- if(col==jsq2+1)test1 = String(GPGGA[col]);
- else test1 += GPGGA[col];
- }
-
- altitude=test1.toInt();//字符串转换为整数,参与运算;
- }
-
-
-
-
-
-
复制代码 |
|