以51单片机为主控制器,LCD1602显示,通过GPS定位模块收发信息,在LCD上显示经纬度。
还加了温湿度DHT11模块,可以在经纬度旁边显示温湿度。
实物图:
单片机源程序如下:
- #include <reg52.h>
- #include <intrins.h>
- #include <stdio.h>
- #include "delay.h"
- #include "1602.h"
- /**The UART1 stage1**/
- #define STAGE_SOHE 0x01
- #define STAGE_TYPE 0x02
- #define STAGE_NONE 0x03
- #define STAGE_DATA 0x04
- unsigned char Lin0_No[16]="N:000.000000 ";//显示北纬
- unsigned char Lin1_Ea[16]="E:000.000000 ";//显示东经
- unsigned long xdata time_20ms=0;
- unsigned char xdata devide_flag; //GPS数据逗号分隔符
- unsigned char xdata speed_end; //收速度数据结束标志
- unsigned char xdata dir_end; //收方向角数据结束标志
- unsigned char xdata sysmode_GPS=0; //gps有效无效标志
- unsigned char xdata ew_flag; //东西标志
- unsigned char xdata ns_flag; //南北标志
- unsigned char xdata gps_infor_weijing[17]; //暂存经纬度 格式是以度分秒的是形式
- unsigned char xdata gps_infor_speed[4]; //暂存速率
- unsigned char xdata gps_infor_time[6]; //时间暂存
- unsigned char xdata gps_infor_date[6]; //日期暂存
- unsigned char xdata gps_infor_dir[3]; //方向暂存
- unsigned char xdata recv1_step=STAGE_SOHE; //串口1接收指令步骤
- unsigned char xdata uart1_r_buf; //串口的缓存
- unsigned char xdata rev1_buf_busy; //串口接收忙碌标志
- unsigned char xdata temp1_buf[85]; //串口接收数组
- unsigned int xdata record1=0;
- unsigned char times = 0; //延时计数
- void Init_Timer0(void);//定时器初始化
- void UART_Init(void);
- void main (void)
- {
- unsigned char num=0;
- unsigned long Mid_Du; //中间变量 暂存经纬度的整数部分 即度
- unsigned long Mid_Fen; //中间变量 暂存经纬度的小数部分 即分 gps原始数据是度分秒格式
- unsigned long Mid_Vale; ////中间变量 暂存经纬度 并将其扩大了10000000倍
- unsigned char i ;
- Init_Timer0(); //定时器0初始化
-
- UART_Init();
-
- LCD_Init(); //初始化液晶
- DelayMs(20); //延时有助于稳定
- LCD_Clear(); //清屏
- DelayMs(120);
- while(1) //主循环
- {
- if(sysmode_GPS==1) //检测gps是否有效数据
- {
- sysmode_GPS=0; //清除有效位
- times = 0; //防止gps数据未更新就误判断数据无效
- Mid_Du=(gps_infor_weijing[0]-0x30)*10000000+(gps_infor_weijing[1]-0x30)*1000000; //处理纬度 暂存整数部分扩大10000000
-
- Mid_Fen=(gps_infor_weijing[2]-0x30)*10000000+(gps_infor_weijing[3]-0x30)*1000000+
- (gps_infor_weijing[4]-0x30)*100000+(gps_infor_weijing[5]-0x30)*10000+
- (gps_infor_weijing[6]-0x30)*1000+(gps_infor_weijing[7]-0x30)*100; //处理纬度 暂存小数部分扩大10000000
- Mid_Fen=Mid_Fen/60; //分秒换算为小数位
- Mid_Vale=Mid_Du+Mid_Fen; //最终纬度 格式为000.00000000 非度分秒格式
- Lin0_No[0]='N';
- Lin0_No[1]=':';
- Lin0_No[2]='0';
- Lin0_No[3]=Mid_Vale/10000000+0x30; //将处理后的纬度填入字符串 并打印显示
- Lin0_No[4]=(Mid_Vale/1000000)%10+0x30;
- Lin0_No[5]='.';
- Lin0_No[6]=(Mid_Vale/100000)%10+0x30;
- Lin0_No[7]=(Mid_Vale/10000)%10+0x30;
- Lin0_No[8]=(Mid_Vale/1000)%10+0x30;
- Lin0_No[9]=(Mid_Vale/100)%10+0x30;
- Lin0_No[10]=(Mid_Vale/10)%10+0x30;
- Lin0_No[11]=Mid_Vale%10+0x30;
-
- Mid_Du=(gps_infor_weijing[8]-0x30)*100000000+(gps_infor_weijing[9]-0x30)*10000000+(gps_infor_weijing[10]-0x30)*1000000; //处理经度 暂存整数部分扩大10000000
-
- Mid_Fen=(gps_infor_weijing[11]-0x30)*10000000+(gps_infor_weijing[12]-0x30)*1000000+
- (gps_infor_weijing[13]-0x30)*100000+(gps_infor_weijing[14]-0x30)*10000+
- (gps_infor_weijing[15]-0x30)*1000+(gps_infor_weijing[16]-0x30)*100; //处理经度 暂存小数部分扩大10000000
- Mid_Fen=Mid_Fen/60; //分秒换算为小数位
- Mid_Vale=Mid_Du+Mid_Fen; //最终经度 格式为000.00000000 非度分秒格式
- Lin1_Ea[0]='E';
- Lin1_Ea[1]=':';
- Lin1_Ea[2]=Mid_Vale/100000000+0x30; //将处理后的经度填入字符串 并打印显示
- Lin1_Ea[3]=(Mid_Vale/10000000)%10+0x30;
- Lin1_Ea[4]=(Mid_Vale/1000000)%10+0x30;
- Lin1_Ea[5]='.';
- Lin1_Ea[6]=(Mid_Vale/100000)%10+0x30;
- Lin1_Ea[7]=(Mid_Vale/10000)%10+0x30;
- Lin1_Ea[8]=(Mid_Vale/1000)%10+0x30;
- Lin1_Ea[9]=(Mid_Vale/100)%10+0x30;
- Lin1_Ea[10]=(Mid_Vale/10)%10+0x30;
- Lin1_Ea[11]=Mid_Vale%10+0x30;
-
- }
- else
- {
- times++;
- if(times>4) //防止gps数据未更新就误判断数据无效
- {
- times = 0; //清零计数
- Lin1_Ea[0]='G'; //无gps信号情况下 打印正在连接
- Lin1_Ea[1]='P';
- Lin1_Ea[2]='S';
- Lin1_Ea[3]=' '; //将处理后的纬度填入字符串 并打印显示
- Lin1_Ea[4]='L';
- Lin1_Ea[5]='I';
- Lin1_Ea[6]='N';
- Lin1_Ea[7]='K';
- Lin1_Ea[8]='I';
- Lin1_Ea[9]='N';
- Lin1_Ea[10]='G';
- Lin1_Ea[11]='.';
- for(i=0;i<12;i++) //数组重新填充
- {
- Lin0_No[i]=Lin1_Ea[i];
- }
- }
- }
- LCD_Write_String(0,0,Lin0_No);//显示第一行
- LCD_Write_String(0,1,Lin1_Ea);//显示第二行
- }
- }
- void Init_Timer0(void)
- {
- TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
- TH0=(65536-20000)/256; //重新赋值 20ms
- TL0=(65536-20000)%256;
- EA=1; //总中断打开
- ET0=1; //定时器中断打开
- TR0=1; //定时器开关打开
- }
- void Timer0_isr(void) interrupt 1
- {
- TH0=(65536-20000)/256; //重新赋值 20ms
- TL0=(65536-20000)%256;
- time_20ms++;
- }
- void UART_Init(void)
- {
- SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
- TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
- TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
- TR1 = 1; // TR1: timer 1 打开
- EA = 1; //打开总中断
- ES = 1; //打开串口中断
- }
- void UART_SER (void) interrupt 4 //串行中断服务程序
- {
- if(RI) //判断是接收中断产生
- {
- RI=0; //标志位清零
- uart1_r_buf=SBUF; //提取buf中的值
- rev1_buf_busy=0x00; //判别 放置break问题
- switch(recv1_step)
- {
- case STAGE_SOHE: if(uart1_r_buf == '') //判断接收到了 具体原因参考GPS标准协议NMEA0183
- {
- rev1_buf_busy=0x01;
- if(uart1_r_buf == '') //再次查看接收的是否是
- {
- recv1_step=STAGE_TYPE; //跳转到下一步
- record1=0; //计数清零
- }
- else
- {
- recv1_step=STAGE_SOHE; //恢复初始化
- record1=0;
- }
- }
- break;
- case STAGE_TYPE: if(rev1_buf_busy == 0x00)
- {
- rev1_buf_busy=0x01;
- temp1_buf[record1]=uart1_r_buf;
- record1++;
- if(record1 == 0x05)
- { //查看$GPRMC开头的命令行
- if((temp1_buf[0] == 'G') && (temp1_buf[1] == 'P') && (temp1_buf[2] == 'R') && (temp1_buf[3] == 'M') && (temp1_buf[4] == 'C'))
- {
- recv1_step=STAGE_NONE; //跳转到下一步
- record1=0;
- }
- else
- {
- recv1_step=STAGE_SOHE;//恢复初始化
- record1=0;
- }
- }
- }
- break;
- case STAGE_NONE: if(rev1_buf_busy == 0x00)//接收命令格式:$GPRMC,054347.00,A,3202.04770,N,11846.23632,E,0.000,0.00,221013,,,A*67
- {
- rev1_buf_busy=0x01;
- record1++;
- if((record1 > 0x01) && (record1 < 0x08))
- {
- gps_infor_time[record1-2]=uart1_r_buf; //时间存储
- }
- if((uart1_r_buf == ',') && (record1 > 0x07) && (record1 < 0x010)) //||((uart1_r_buf == ',') && (record1==0x02))
- {
- record1=0xcc;
- }
- if(record1 == 0xcd)
- {
- record1=0;
- devide_flag=2;
- speed_end=0x00;
- dir_end=0x00;
- if(uart1_r_buf == 'A') //gps收到数据 且有效
- {
- recv1_step=STAGE_DATA; //跳转到下一步
- }
- else
- {
- sysmode_GPS=0;
- recv1_step=STAGE_SOHE; //无效恢复初始化
- record1=0;
- }
- }
- }
- break;
- case STAGE_DATA: if(rev1_buf_busy == 0x00)
- {
- rev1_buf_busy=0x01;
- record1++;
- if(uart1_r_buf == ',') //判断逗号
- {
- devide_flag++; //逗号次数记录
- record1=0;
- }
- if(devide_flag == 3)
- {
- if((record1 > 0) && (record1 < 5))
- {
- gps_infor_weijing[record1-1]=uart1_r_buf; //存储经纬度 此处为纬度
- }
- if((record1 > 5) && (record1 < 10)) //跳过小数点的存储
- {
- gps_infor_weijing[record1-2]=uart1_r_buf; //存储经纬度 此处为纬度
- }
- }
- if(devide_flag == 4)
- {
- if(record1 > 0)
- {
- ns_flag=uart1_r_buf; //接收纬度NS标志
- }
- }
- if(devide_flag == 5)
- {
- if((record1 > 0) && (record1 < 6))
- {
- gps_infor_weijing[record1+7]=uart1_r_buf; //存储经纬度 此处为纬度
- }
- if((record1 > 6) && (record1 < 11)) //跳过小数点的存储
- {
- gps_infor_weijing[record1+6]=uart1_r_buf; //存储经纬度 此处为经度
- }
- }
- if(devide_flag == 6)
- {
- if(record1 > 0)
- {
- ew_flag=uart1_r_buf; //经度度 EW标志
- }
- }
- if(devide_flag == 7)
- {
- if(speed_end == 0x00)
- {
- if((record1 > 0) && (uart1_r_buf != '.'))
- {
- gps_infor_speed[record1-1]=uart1_r_buf; //接收速率
- }
- else if(uart1_r_buf == '.')
- {
- record1--;
- speed_end=0xff;
- }
- }
- else if(speed_end == 0xff)
- {
- speed_end=0xfe;
- gps_infor_speed[record1-1]=uart1_r_buf;
- gps_infor_speed[3]=gps_infor_speed[record1-1];
- gps_infor_speed[2]=gps_infor_speed[record1-2];
- if(record1 > 2)
- {
- gps_infor_speed[1]=gps_infor_speed[record1-3];
- }
- else
- {
- gps_infor_speed[1]=0x30;
- }
- if(record1 > 3)
- {
- gps_infor_speed[0]=gps_infor_speed[record1-4];
- }
- else
- {
- gps_infor_speed[0]=0x30;
- }
- }
- }
- if(devide_flag == 8)
- {
- if(dir_end == 0x00)
- {
- if((record1 > 0) && (uart1_r_buf != '.'))
- {
- gps_infor_dir[record1-1]=uart1_r_buf; //存储方向
- }
- else if(uart1_r_buf == '.')
- {
- record1--;
- dir_end=0xff;
- }
- }
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
程序.rar
(71.15 KB, 下载次数: 122)
|