用51单片机解析串口GPS模块发来的信息,在1602液晶显示 ,用51单片机的TXD口接GPS模块的RXD口。程序略做修改并修正了一些错误。
这是电路原理图。程序是结合我单片机的板子做了修改。
就是先焊接一个51单片机最小系统。我的程序中是用的P0口与1602液晶通信。
这是做的改进,由原来的串口GPS模块,换成了蓝牙GPS模块。最右边是诺基亚的蓝牙GPS模块,小的四方的板子上蓝牙串口主模块,用来接收蓝牙GPS发出的信号。程序还是原程序。
程序是结合网络资料,自己加已修改。
因无法上传附件,只有把代码贴 这了。
//这是1602液晶的驱动头文件,文件名为1602.h /* LCD1602驱动,兼容LCD2402 */ sbit LCD_DB0= P0^0; sbit LCD_DB1= P0^1; sbit LCD_DB2= P0^2; sbit LCD_DB3= P0^3; sbit LCD_DB4= P0^4; sbit LCD_DB5= P0^5; sbit LCD_DB6= P0^6; sbit LCD_DB7= P0^7; sbit LCD1602_RS=P1^0; sbit LCD1602_RW=P1^1; sbit LCD1602_EN=P1^2; void LCD_write_char( unsigned x,unsigned char y,unsigned char dat); //在指定位置显示字符 void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s);//在指定位置显示字符串 void LCD_cls(void);//清屏 void LCD_en_command(unsigned char command); void LCD_en_dat(unsigned char temp); void LCD_set_xy( unsigned char x, unsigned char y ); void LCD_init(unsigned char bw); void SET_LCD(unsigned char IO_temp); void delayms(unsigned char ms); void lcddelay(void); unsigned char LCDIO; unsigned char BitWidth; void LCD_cls(void) { LCD_en_command(0x01); //0x01 清屏 delayms(2); } void LCD_en_command(unsigned char command) { LCD1602_RS=0; LCD1602_RW=0; LCD1602_EN=0; switch(BitWidth){ case 4: LCDIO=(command & 0xf0); //取高4位 break; case 8: LCDIO=command; break; } SET_LCD(LCDIO); LCD1602_EN=1; lcddelay(); LCD1602_EN=0; if (BitWidth==4){ LCDIO=(command & 0x0f)<<4; //取低4位 SET_LCD(LCDIO); LCD1602_EN=1; lcddelay(); LCD1602_EN=0; } } void SET_LCD(unsigned char IO_temp) { //高4位 LCD_DB7=IO_temp&0x80; LCD_DB6=IO_temp&0x40; LCD_DB5=IO_temp&0x20; LCD_DB4=IO_temp&0x10; //低4位 if (BitWidth==8){ LCD_DB3=IO_temp&0x08; LCD_DB2=IO_temp&0x04; LCD_DB1=IO_temp&0x02; LCD_DB0=IO_temp&0x01; } } void LCD_en_dat(unsigned char dat) { LCD1602_RS=1; LCD1602_RW=0; LCD1602_EN=0; switch(BitWidth){ case 4: LCDIO=(dat & 0xf0); //取高4位 break; case 8: LCDIO=dat; break; } SET_LCD(LCDIO); LCD1602_EN=1; lcddelay(); LCD1602_EN=0; if (BitWidth==4){ LCDIO=(dat & 0x0f)<<4; //取低4位 SET_LCD(LCDIO); LCD1602_EN=1; lcddelay(); LCD1602_EN=0; } } /*======================================================= *1602 * 输入参数:x、y : 显示字符串的坐标,X:0-15,Y:0-1 *LCD第一行显示寄存器地址:0X80-0X8F *LCD第二行显示寄存器地址:0XC0-0XCF *2404 *LCD第1行显示地址:1~20(0x80~0x93) *LCD第2行显示地址:1~20(0xc0~0xd3) *LCD第3行显示地址:1~20(0x94~0xa7) *LCD第4行显示地址:1~20(0xd4~0xe7) =======================================================*/ void LCD_set_xy( unsigned char x, unsigned char y ) { unsigned char address; if (y ==0) address = 0x80 + x; else if(y==1) address = 0xC0 + x; else if(y==2) address = 0x94 + x; else if(y==3) address = 0xD4 + x; LCD_en_command(address); } void LCD_write_char( unsigned x,unsigned char y,unsigned char dat) { LCD_set_xy( x, y ); LCD_en_dat(dat); } void LCD_write_string(unsigned char X,unsigned char Y,unsigned char *s) { LCD_set_xy( X, Y ); //set address while (*s) // write character { LCDIO=*s; SET_LCD(LCDIO); LCD_en_dat(*s); s ++; } } void LCD_init(unsigned char bw) { BitWidth=bw; switch(BitWidth){ case 4: LCD_en_command(0x33); // delayms(20); LCD_en_command(0x32); // delayms(20); break; case 8: LCD_en_command(0x38); // delayms(20); LCD_en_command(0x38); // delayms(20); break; } LCD_en_command(0x08); //0x08 令显示器off delayms(5); LCD_en_command(0x01); //0x01 清屏 清屏指令 delayms(5); LCD_en_command(0x06); //0x06 光标模式设置 进入模式设置指令 写入数据后光标右移 delayms(5); LCD_en_command(0x0c); //0x0c 显示开 令光标,0x0c=不显示,0x0d=显示闪动 delayms(5); } void delayms(unsigned char ms) { unsigned char i; while(ms--) { for(i = 0; i < 115; i++); } } void lcddelay(void) { unsigned char i; for(i = 0; i < 2; i++); } //这是解码主程序
/************************************* GPS解码显示程序, ***************************************/ #include<reg52.h> #include "1602.h" //#include"math.h" //#include <stdlib.h> sbit GPS_SPD=P2^1; //接收波特率设置 sbit KEY1=P2^0; //显示内容分屏切换,(T0,T1引脚 的第二功能为计数器。) char code TIME_AREA= 8; //时区 /*************************************** 这是做的部分更改 ************************************/ unsigned long maxspeed,b; unsigned int count=0; unsigned int a[5]; unsigned char hspeed[5]; unsigned int dot_count; //小数点计数器 //unsigned char x; //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'}; //速度 unsigned char high[6]; //高度 unsigned char angle[5]={'0','0','0','0','0'}; //方位角 unsigned char use_sat[2]; //使用的卫星数 unsigned char total_sat[2]; //天空中总卫星数 unsigned char lock; //定位状态 //串口中断需要的变量 unsigned char seg_count; //逗号计数器 unsigned char byte_count; //位数计数器 unsigned char cmd_number; //命令类型 unsigned char mode; //0:结束模式,1:命令模式,2:数据模式 unsigned char buf_full; //1:整句接收完成,相应数据有效。0:缓存数据无效。 unsigned char cmd[5]; //命令类型存储数组 //显示需要的变量 unsigned int dsp_count; //刷新次数计数器 //unsigned char time_count; bit page; void sys_init(void); bit chk_key(void); main() { unsigned char i; char Bhour; sys_init(); lock=1; use_sat[0]='0'; use_sat[1]='0'; total_sat[0]='0'; total_sat[1]='0'; while(1){ if(buf_full==0) //无GPS信号时 { dsp_count++; if(dsp_count>=65000){ LCD_cls(); //清屏 LCD_write_string(0,0,"No GPS connect.."); LCD_write_string(0,1,"Please Check.."); while(buf_full==0); LCD_cls(); dsp_count=0; } } else{ //有GPS信号时 /************************************* 最大速度处理 *************************************/ dot_count=0; b=0; for(i=0;i<5;i++) { if(speed!='.') dot_count++; else break ; } switch(dot_count) { case 1: b=((speed[0]-'0')*10+(speed[2]-'0'))*1.852; break; case 2: b=((speed[0]-'0')*100+(speed[1]-'0')*10+(speed[4]-'0'))*1.852; break; case 3: b=((speed[0]-'0')*1000+(speed[1]-'0')*100+(speed[2]-'0')*10+(speed[4]-'0'))*1.852; break; } if(b>maxspeed) { maxspeed=b; } /************************************* 最大速度处理 *************************************/ if(chk_key()){ //检测到按键切换显示 page=!page; LCD_cls(); } if(!page){ //页面1 if(buf_full|0x01){ //GGA语句 if(lock==0){ //如果未定位 LCD_write_string(0,0,"*---.--.---- "); LCD_write_string(0,1,"* --.--.---- "); }else{ //如果已定位 LCD_write_char(0,0,JD_a); //显示经度 for(i=0;i<3;i++) { LCD_write_char(i+1,0,JD); } LCD_write_char(4,0,'.'); for(i=3;i<10;i++) { LCD_write_char(i+2,0,JD); } LCD_write_char(0,1,WD_a); //显示纬度 LCD_write_char(1,1,' '); for(i=0;i<2;i++) { LCD_write_char(i+2,1,WD); } LCD_write_char(4,1,'.'); for(i=2;i<9;i++) { LCD_write_char(i+3,1,WD); } } LCD_write_char(14,1,use_sat[0]); //显示接收卫星数 LCD_write_char(15,1,use_sat[1]); buf_full&=~0x01; dsp_count=0; } if(buf_full|0x02){ //GSV语句 LCD_write_char(14,1,total_sat[0]); LCD_write_char(15,1,total_sat[1]); buf_full&=~0x02; dsp_count=0; } if(buf_full|0x04){ if(lock==0){ //如果未定位 LCD_write_string(0,0,"*---.--.---- "); LCD_write_string(0,1,"* --.--.---- "); }else{ //如果已定位 LCD_write_char(0,0,JD_a); //显示经度 for(i=0;i<3;i++) { LCD_write_char(i+1,0,JD); } LCD_write_char(4,0,'.'); for(i=3;i<10;i++) { LCD_write_char(i+2,0,JD); } LCD_write_char(0,1,WD_a); //显示纬度 LCD_write_char(1,1,' '); for(i=0;i<2;i++) { LCD_write_char(i+2,1,WD); } LCD_write_char(4,1,'.'); for(i=2;i<9;i++) { LCD_write_char(i+3,1,WD); } } LCD_write_char(14,0,use_sat[0]); //显示接收卫星数 LCD_write_char(15,0,use_sat[1]); buf_full&=~0x04; dsp_count=0; } } else{ //页面2 if(buf_full|0x01){ //GGA语句 buf_full&=~0x01; dsp_count=0; } if(buf_full|0x02){ buf_full&=~0x02; dsp_count=0; } if(buf_full|0x04){ //RMC语句 Bhour=((time[0]-0x30)*10+time[1]-0x30)+TIME_AREA; if(Bhour>=24){ Bhour-=24; }else if(Bhour<0){ Bhour+=24; } LCD_write_char(0,1,date[4]); LCD_write_char(1,1,date[5]); LCD_write_char(2,1,date[2]); LCD_write_char(3,1,date[3]); LCD_write_char(4,1,date[0]); LCD_write_char(5,1,date[1]); LCD_write_char(8,1,Bhour/10+0x30); LCD_write_char(9,1,Bhour%10+0x30); LCD_write_char(10,1,':'); LCD_write_char(11,1,time[2]); LCD_write_char(12,1,time[3]); LCD_write_char(13,1,':'); LCD_write_char(14,1,time[4]); LCD_write_char(15,1,time[5]); LCD_write_string(5,0,"knot A"); if(lock=='0'){ //如果未定位 LCD_write_string(0,0,"---.-"); LCD_write_string(11,0,"---.-"); }else{ //已经定位,在此处做的改动。 /*******************************************************************************/ if(count<10) { for(i=0;i<5;i++) { LCD_write_char(i,0,speed);//knot显示 } count++; } else { if(count>15) { count=0; } hspeed[0]=maxspeed/1000+0x30; //把小数转成字符数组 hspeed[1]=(maxspeed/100)%10+0x30; hspeed[2]=(maxspeed/10)%10+0x30; hspeed[3]='.'; hspeed[4]= maxspeed%10+0x30; count++; LCD_write_string(5,0,"Km/h A"); LCD_write_char(0,0,hspeed[0]); LCD_write_char(1,0,hspeed[1]); LCD_write_char(2,0,hspeed[2]); LCD_write_char(3,0,hspeed[3]); LCD_write_char(4,0,hspeed[4]); //最大速度显 */ } /*******************************************************************************/ for(i=0;i<5;i++){ LCD_write_char(11+i,0,angle); } } buf_full&=~0x04; dsp_count=0; } } } } } bit chk_key(void) { if(!KEY1){ delayms(10); if(!KEY1){ while(!KEY1); delayms(10); return(1); } } LCD_cls(); //清屏 return(0); } //系统初始化 void sys_init() { unsigned char i; SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */ TMOD = 0x21; /* TMOD: timer 1, mode 2, 8-bit reload */ if(GPS_SPD){ TH1 = 0xfa; /* TH1: reload value for 9600 baud @ 11.059MHz */ }else{ TH1 = 0xfd; /* TH1: reload value for 4800 baud @ 11.059MHz */ } TR1 = 1; /* TR1: timer 1 run */ LCD_init(8); //初始化LCD LCD_write_string(0,0," GPS SIRF II 2 "); LCD_write_string(0,1," 11-11-23 1342 "); for(i=1;i<4;i++){ delayms(250); } //LCD_cls(); IE=0x90; //开总中断、串口中断 } //串口接收中断 void uart(void) interrupt 4 { unsigned char tmp; if(RI){ tmp=SBUF; switch(tmp){ case '$': cmd_number=0; //命令类型清空 mode=1; //接收命令模式 byte_count=0; //接收位数清空 break; case ',': seg_count++; //逗号计数加1 byte_count=0; break; case '*': switch(cmd_number){ case 1: buf_full|=0x01; break; case 2: buf_full|=0x02; break; case 3: buf_full|=0x04; break; } mode=0; break; default: if(mode==1){ //命令种类判断 cmd[byte_count]=tmp; //接收字符放入类型缓存 if(byte_count>=4){ //如果类型数据接收完毕,判断类型 if(cmd[0]=='G'){ if(cmd[1]=='P'){ if(cmd[2]=='G'){ if(cmd[3]=='G'){ if(cmd[4]=='A'){ cmd_number=1; mode=2; seg_count=0; byte_count=0; } } else if(cmd[3]=='S'){ if(cmd[4]=='V'){ cmd_number=2; mode=2; seg_count=0; byte_count=0; } } } else if(cmd[2]=='R'){ 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){ case 1: //类型1数据接收。GPGGA switch(seg_count){ case 2: //纬度处理 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: //定位判断 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: //类型2数据接收。GPGSV switch(seg_count){ case 3: //天空中的卫星总数 if(byte_count<2){ total_sat[byte_count]=tmp; } break; } break; case 3: //类型3数据接收。GPRMC switch(seg_count){ case 1: //时间处理 if(byte_count<6){ time[byte_count]=tmp; } break; case 2: //定位判断 if(byte_count<1){ if (tmp=='A') {lock=1;} else{ lock=0;} } break; case 3: //纬度处理 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; } 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: //方位角处理 if(byte_count<6){ date[byte_count]=tmp; } break; } break; } } byte_count++; //接收数位加1 break; } } RI=0; }