#include <REG52.H> #include <stdio.h> #include <intrins.h> #include <lcd1602.h> #include <uart.h> #include <delay.h> #include "string.h" #include <stdlib.h> unsigned char flag_rec=0; //接收数据标志 unsigned char num_rec=0; // 计数标志 //char code TIME_AREA= 8; //时区,我们不需要它 unsigned char flag_data; //date flag //only displaty cmd $GPGGA information unsigned char JD[16]; //longitude unsigned char JD_a; //经度方向 unsigned char WD[15]; //latitude unsigned char WD_a; // 纬度方向 unsigned char date[6]; //date unsigned char time[6]; //date unsigned char time1[6]; //date 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; //位置状态 //date handing variable unsigned char seg_count; // 逗号计数器 unsigned char dot_count; //小数点计数器 unsigned char byte_count; // 位计数器 unsigned char cmd_number; // 命令模式 unsigned char mode; // unsigned char buf_full; unsigned char cmd[5]; // 存储命令模式 //serial disconnect timer unsigned long int tt=0;
主函数 系统初始化
//main void main () { int jd_second,wd_second; // 中间变量 init_uart(); //初始化序列号 lcd_init() ; // 初始化 lcd1602 delay(200); LCD_Write_String(0,0,"Please Waiting..."); // "Please Waiting" when it is boot up delay(200); delay(200); delay(200); delay(200); delay(200); delay(200); delay(200); delay(200); delay(200); delay(200); // 延迟显示 write_com(0x01); // 清屏
设置延时函数,以形成视觉暂留
while(1) { tt++; if(tt>10000) { tt=10000; write_com(0x01); LCD_Write_String(3,0,"No Data!"); LCD_Write_String(3,1,"No Data!"); delay(200); delay(200); delay(200); delay(200); delay(200); }
if(flag_rec==1) // 获取gps数据 { flag_rec=0; // 清除标志符 if (lock==1) // 获取位置信息 { // LCD_Write_String(0,0,"JD :"); // 显示经度 LCD_Write_String(6,0,JD); // 显示数据 LCD_Write_String(9,0,"."); // 进制转换 LCD_Write_String(10,0,JD+3); jd_second=60*atof((char *)(JD+5)); LCD_Write_Char(13,0,jd_second/10+'0'); // 将上一步转换得到浮点数据打印在lcd LCD_Write_Char(14,0,jd_second%10+'0'); // 将上面得到的数据分为两部分,分别打印在LCD 上 LCD_Write_Char(15,0,' '); //填充空间 delay(200); // 保护lcd LCD_Write_String(0,1,"WD :"); // 显示下一行 LCD_Write_String(6,1,WD); LCD_Write_String(8,1,"."); LCD_Write_String(9,1,WD+2); // 小数点 wd_second=60*atof((char *)(WD+4)); // 将字符串转换成浮点数 LCD_Write_Char(12,1,wd_second/10+'0'); LCD_Write_Char(13,1,wd_second%10+'0'); LCD_Write_String(14,1," "); delay(200); } } } }
串口中断函数及模式判断
判断的主要依据就是接收端接受消息与预结果匹配,通过设置数组[i,j]和if函数进行判断匹配(发送报文的消息内容见1.3的UM220的通信协议详解)
//serial interruupt service function void ser_int (void) interrupt 4 { unsigned char tmp; if(RI) { tt=0; RI=0; tmp=SBUF; // 从缓冲区接收数据 switch(tmp) //if $GPGGA,$GNGSW,$GNRMC,get data then processing it { //date start with $ case '$': cmd_number=0; // 清除命令模式 mode=1; // 选项命令接收模式 byte_count=0; //清除位计数器 flag_data=1; // 设置数据标志 flag_rec=1; // 设置数据接收标志 break; case ',': //Eg:$GNRMC,134645.000,A,2603.964436,N,11912.410232,E,0.000,15.744,030718,,E,A*0B seg_count++; // 计数器增加 byte_count=0; break; case '*': switch(cmd_number) { case 1: buf_full|=0x01; //00000001 break; case 2: buf_full|=0x02; //00000010 break; case 3: buf_full|=0x04; //00000100 break; } mode=0; //clear mode break; default: // receive date cmd if(mode==1) { cmd[byte_count]=tmp; // 获取数据和存储缓冲区 if(byte_count>=4) //overlook cmd which less 4 bit { if(cmd[0]=='G') // 第一个字符 { if(cmd[1]=='N') { if(cmd[2]=='G') { if(cmd[3]=='G') { if(cmd[4]=='A')//判断$GNGGA { cmd_number=1; //数据类型 mode=2; //接收日期 seg_count=0; //comma counter clear byte_count=0; //位计数器清除 } } else if(cmd[3]=='S') //命令模式$GNGSV { if(cmd[4]=='V') { cmd_number=2; mode=2; //获取数据 seg_count=0; byte_count=0; } } } else if(cmd[2]=='R') //命令模式 $GNRMC { if(cmd[3]=='M') { if(cmd[4]=='C') { cmd_number=3; mode=2; //存储数据 seg_count=0; byte_count=0; } } } } } } } //日期处理
else if(mode==2) { switch (cmd_number) //if receive data { case 1: //get and store data,$GPGGA,[],[],[],[],[],[],[],[],[]..... switch(seg_count) // comma 计数器 { case 2: // 2rd逗号后的纬度 if(byte_count<9) { WD[byte_count]=tmp; //获取纬度 } break; case 3: //纬度方向 if(byte_count<1) { WD_a=tmp; } break; case 4: //经度 if(byte_count<10) { JD[byte_count]=tmp; //存储 } break; case 5: //经度方向 if(byte_count<1) { JD_a=tmp; } break; case 6: //location if(byte_count<1) { lock=tmp; } break; case 7: if(byte_count<2) { use_sat[byte_count]=tmp; } break; case 9: // 高度 if(byte_count<6) { high[byte_count]=tmp; } break; } break; case 2: //命令模式 $GPGSV switch(seg_count) { case 3: // 卫星总数 if(byte_count<2) { total_sat[byte_count]=tmp; } break; } break;
//命令模式3:无SUE case 3: //$GPRMC switch(seg_count) { case 1: //time if(byte_count<6) { time[byte_count]=tmp; } break; case 2: // 位置 if(byte_count<1) { if (tmp=='V') {lock=0;} else { lock=1; } } break; case 3: //lititude // if(byte_count<9) // { // WD[byte_count]=tmp;//我们只需要一次 // } break; case 4: // if(byte_count<1) { WD_a=tmp; } break; case 5: // // if(byte_count<10) // { // JD[byte_count]=tmp; //do not get again // } break; case 6: // 直线方向 if(byte_count<1) { JD_a=tmp; } break; case 7: // 速度处理 if(byte_count<5) { speed[byte_count]=tmp; } break; case 8: // 方向角 if(byte_count<5) { angle[byte_count]=tmp; } break; case 9: //other if(byte_count<6) { date[byte_count]=tmp; } break; } break; } } byte_count++; // 位计数器++ break; } }