什么都不多说,直接看代码:
#include <REG52.H>
#include <stdio.h>
#include <intrins.h>
////////////========================================================================================
/*
1602A(16*2)模拟口线接线方式
连接线图:
---------------------------------------------------
|LCM-----51 | LCM-----51 | LCM------51 |
--------------------------------------------------|
|DB0-----P0.0 | DB4-----P0.4 | RW-------P1.5 |
|DB1-----P0.1 | DB5-----P0.5 | RS-------P1.4 |
|DB2-----P0.2 | DB6-----P0.6 | E--------P1.6 |
|DB3-----P0.3 | DB7-----P0.7 | V0接10K电阻到GND |
---------------------------------------------------
温湿度DHT11接线:模块data接 P3^2
******************/
sbit Data= P3^2; //定义数据线 温湿度传感器DHT11数据接入
unsigned char rec_dat[9]; //用于显示的接收数据数组
unsigned char flag_rec=0;
unsigned char num_rec=0;
unsigned char code kaijihuamian[]="BeiDou_DHT11"; //开机显示
unsigned char code kaijihuamian2[]="AnShan_17-12-01";
unsigned char code receiving[]="Receiving!";
unsigned char code nodata[]="No BD data!";
unsigned char code LCD_161[]="BD_HeGuang Studios";
unsigned char code LCD_162[]="TEL:15117255049";
char code TIME_AREA= 8; //时区
unsigned char flag_data; //数据标志位
//BD数据存储数组
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 time1[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:整句接收完成,相应数据有效。0:缓存数据无效。
unsigned char cmd[5]; //命令类型存储数组
sbit rs = P1^4;
sbit rw = P1^5;
sbit ep = P1^6;
//-----------------------------------------------------------------------------------------------
//延时子程序
void delayms(unsigned char ms)
{
unsigned char i;
while(ms--)
{
for(i = 0; i < 120; i++);
}
}
bit lcd_bz(void)
{ // 测试LCD忙碌状态
bit result;
rs = 0;
rw = 1;
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0 & 0x80);
ep = 0;
return result;
}
void lcd_wcmd(unsigned char cmd)
{ // 写入指令数据到LCD
while(lcd_bz());
rs = 0;
rw = 0;
ep = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
void lcd_pos(unsigned char pos)
{ //设定显示位置
lcd_wcmd(pos | 0x80);
}
void lcd_pos_2(unsigned char pos)
{ //设定显示位置
lcd_wcmd(pos | 0xC0);
}
void lcd_wdat(unsigned char dat)
{ //写入字符显示数据到LCD
while(lcd_bz());
rs = 1;
rw = 0;
ep = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 1;
_nop_();
_nop_();
_nop_();
_nop_();
ep = 0;
}
void lcd_string(unsigned char *ptr,unsigned char pos)
{
unsigned char i;
lcd_pos(pos);
while(*(ptr+i) != '\0')
{ // 显示字符"welcome!"
lcd_wdat(*(ptr+i));
i++;
}
}
lcd_init()
{ //LCD初始化设定
lcd_wcmd(0x38); //
delayms(1);
lcd_wcmd(0x0c); //
delayms(1);
lcd_wcmd(0x06); //
delayms(1);
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(1);
}
//-----------------------------------------------------------------------------------------------
//延时子程序
void delaym(unsigned int ms)
{
unsigned int i,j;
for(i = 0;i < ms ;i++)
{
for(j = 0;j < 125 ;j++)
;
}
}
void DHT11_delay_us(unsigned char n)
{
while(--n);
}
void DHT11_delay_ms(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}
void DHT11_start()
{
Data=1;
DHT11_delay_us(2);
Data=0;
DHT11_delay_ms(20); //延时18ms以上
Data=1;
DHT11_delay_us(30);
}
//----------------------- 温湿度读取 -----------------------------------
unsigned char DHT11_rec_byte() //接收一个字节
{
unsigned char i,dat=0;
for(i=0;i<8;i++) //从高到低依次接收8位数据
{
while(!Data); ////等待50us低电平过去
DHT11_delay_us(8); //延时60us,如果还为高则数据为1,否则为0
dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
if(Data==1) //数据为1时,使dat加1来接收数据1
dat+=1;
while(Data); //等待数据线拉低
}
return dat;
}
void DHT11_receive() //接收40位的数据
{
unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
DHT11_start();
if(Data==0)
{
while(Data==0); //等待拉高
DHT11_delay_us(40); //拉高后延时80us
R_H=DHT11_rec_byte(); //接收湿度高八位
R_L=DHT11_rec_byte(); //接收湿度低八位
T_H=DHT11_rec_byte(); //接收温度高八位
T_L=DHT11_rec_byte(); //接收温度低八位
revise=DHT11_rec_byte(); //接收校正位
DHT11_delay_us(25); //结束
if((R_H+R_L+T_H+T_L)==revise) //校正
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
}
/*数据处理,方便显示*/
rec_dat[0]='0'+(RH/10);
rec_dat[1]='0'+(RH%10);
rec_dat[2]='R';
rec_dat[3]='H';
rec_dat[4]=' ';
rec_dat[5]=' ';
rec_dat[6]='0'+(TH/10);
rec_dat[7]='0'+(TH%10);
rec_dat[8]='C';
}
}
//------------------------- <初始化设置 结束> -------------------------------------
void DHT11_main(unsigned int zxi){
lcd_init(); //初始化1602
lcd_wcmd(0x01); //清除LCD的显示内容
delaym(1);
//============温湿度读取============================================================
DHT11_delay_ms(1500); //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
DHT11_receive();
lcd_pos(3); // 设置显示位置
for(zxi = 0;zxi<6;zxi++)
{
lcd_wdat(kaijihuamian[zxi+6]); // 显示字符dht11
}
zxi = 0;
delayms(100);
lcd_pos_2(2);
while(rec_dat[zxi] != '\0'){
lcd_wdat(rec_dat[zxi]); //显示
zxi++;
}
delaym(1000);
}
//==================================================================================
//发送字节
void sendbyte(unsigned char ptr)
{
SBUF=ptr;
while(TI==0);
TI=0;
}
//---------------------------------------------------------------------------
//发送数据流
void sendstring(unsigned char *ptr,unsigned char len)
{
int i=0;
while(i<len)
{
SBUF=*(ptr+i); //SUBF接受/发送缓冲器
while(TI==0);
TI=0;
i++;
}
num_rec=0;
}
void init_all(void) //9600 11.05926
{
SCON = 0x50; //REN=1允许串行接受状态,串口工作模式1
TMOD|= 0x20; //定时器工作方式2
PCON|= 0x80;
TH1 = 0xFa; //baud*2 /* reload value 9600、数据位8、停止位1。效验位无 (11.0592)
TL1 = 0xF3;
TR1 = 1;
ES = 1; //开串口中断
EA = 1; // 开总中断
lcd_init() ;
}
//将UTC时间转成BJ时间
void trans_time(void)
{
unsigned char temp,hour_shi,hour_ge;
temp=(time[0]-'0')*10+(time[1]-'0');
if(temp<=16)
{
temp=temp+8;
hour_shi=temp/10;
hour_ge=temp%10;
time[0]=hour_shi+'0';
time[1]=hour_ge+'0';
}
else
{
temp=temp+8-24;
time[0]='0';
time[1]=temp%10+'0';
}
}
//判断是否有BD数据 有1,无0
bit BD_data(void)
{
if(buf_full&0x01!=0)
return 1;
else
return 0;
}
//----------------------------------------------------------------------------
void main ()
{
unsigned int X;
unsigned char i;
init_all();
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(10);
i = 0;
X = 0;
lcd_pos(1); // 设置显示位置
while(kaijihuamian[i] != '\0')
{
lcd_wdat(kaijihuamian[i]); // 显示字符时间
i++;
}
delayms(10);
i=0 ;
lcd_pos_2(0); // 设置显示位置
while(kaijihuamian2[i] != '\0')
{
lcd_wdat(kaijihuamian2[i]); // 显示字符时间
i++;
}
i = 0;
delayms(5000);
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(10);
while(1)
{
if(flag_data==0)// 如果没有数据
{
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(10);
i=0 ;
lcd_pos(2); // 设置显示位置
while(nodata[i] != '\0')
{
lcd_wdat(nodata[i]); // 显示字符
i++;
}
delayms(1000);
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(10);
//第三页开始==================================================================
DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
delaym(3000);
i = 0;
lcd_wcmd(0x01);
delaym(1);
//第四页开始==================================================================
lcd_pos(0); // 设置显示位置
while(LCD_161[i] != '\0'){
lcd_wdat(LCD_161[i]); // 显示字符禾灮信息
i++;
}
delayms(1);
i=0 ;
lcd_pos_2(0); // 设置显示位置
while(LCD_162[i] != '\0'){
lcd_wdat(LCD_162[i]); // 显示字符禾灮信息
i++;
}
//结束==================================================================
delayms(5000);
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(1);
}
if(flag_rec==1) //data 解码完毕
{
flag_rec=0; //清数据有效标志位
if (lock==1) //如果已经定位
{
for(X;X <10;X++){
trans_time();//UTC--BJ TIME转换为北京时间
lcd_pos_2(0); // 设置显示位置
lcd_wdat(' '); //显示 北京时间
lcd_wdat(time[5]);
}
delayms(1); //第一页显示完毕======经纬度+北京时间====定位+授时
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(1);
X = 0;
for(X;X <10;X++){
//第二页开始=================================================================================
lcd_pos(0); // 设置显示位置
lcd_wdat('H'); // 显示海拔 卫星个数
delayms(100);
lcd_pos(1);
while(high[i] != '\0'){
lcd_wdat(high[i]); //显示海拔
i++;
}
delayms(100);
while(use_sat[i] != '\0'){
lcd_wdat(use_sat[i]); // // 显示 卫星个数
i++;
}
delayms(100);
i=0 ;
//delayms(5000); //第二页显示完毕======显示海拔+卫星个数===速度+方位
//lcd_wcmd(0x01); //清除LCD的内容
while(angle[i] != '\0'){
lcd_wdat(angle[i]); // // 显示 方位角
i++;
}
i=0 ;
}
delayms(10); //第二页显示完毕======显示海拔+卫星个数===速度+方位
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(1);
X = 0;
//第三页开始==================================================================
DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
delaym(3000);
i = 0;
lcd_wcmd(0x01);
delaym(1);
//第四页开始==================================================================
lcd_pos(0); // 设置显示位置
while(LCD_161[i] != '\0'){
lcd_wdat(LCD_161[i]); // 显示字符禾灮信息
i++;
}
delayms(1);
i=0 ;
lcd_pos_2(0); // 设置显示位置
while(LCD_162[i] != '\0'){
lcd_wdat(LCD_162[i]); // 显示字符禾灮信息
i++;
}
//结束==================================================================
delayms(5000);
delayms(1); //显示完毕======显示禾灮信息
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(1);
}
else if(lock==0)
{ //未定位 //display relative message
lcd_wcmd(0x01); //清除LCD的显示内容
delayms(10);
i=0 ;
lcd_pos(3); // 设置显示位置
while(receiving[i] != '\0')
{
lcd_wdat(receiving[i]); // 显示字符时间
i++;
}
delaym(1000);
lcd_wcmd(0x01); //清除LCD的显示内容
delaym(10);
X = 0;
//第三页开始==================================================================
DHT11_main(i);// 显示字符DHT11 温度 湿度 信息
delaym(3000);
i = 0;
lcd_wcmd(0x01);
delaym(1);
//第四页开始==================================================================
lcd_pos(0); // 设置显示位置
while(LCD_161[i] != '\0'){
lcd_wdat(LCD_161[i]); // 显示字符禾灮信息
i++;
}
delayms(1);
i=0 ;
lcd_pos_2(0); // 设置显示位置
while(LCD_162[i] != '\0'){
lcd_wdat(LCD_162[i]); // 显示字符禾灮信息
i++;
}
//结束==================================================================
delayms(5000);
delayms(1);
}
}
}
}
//--------------------------------------------------------------------
//串口中断程序
void ser_int (void) interrupt 4 using 1
{
unsigned char tmp;
if(RI)
{
RI=0;
tmp=SBUF;
switch(tmp)
{
case '$':
cmd_number=0; //命令类型清空
mode=1; //接收命令模式
byte_count=0; //接收位数清空
flag_data=1;
flag_rec=1; //数据标志位置一
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]=='N')
{
if(cmd[2]=='G')
{
if(cmd[3]=='G')
{
if(cmd[4]=='A')
{
cmd_number=1; //data type
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;
}
}
}
switch (cmd_number)
{
case 1: //类型1数据接收。GNGGA————北斗与GPS组合数据
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;
}
byte_count++; //接收数位加1
break;
}
}
}
相关测试结果:
测试视频地址:点击进入
感谢一直关注着禾灮成长进步的朋友们。你们的信任、支持和鼓励,鞭策着我们一路走到了今天。
感谢所有的合作伙伴,我们相互促进,共同见证了彼此的成长。
感谢所有曾经在禾灮彼此倚靠、相互鼓励、携手同心、砥砺同行的兄弟姐妹。这里承载了我们的青春与热血。
禾灮,感谢有你。
未来,我们将一如既往,砥砺前行。
禾灮·小楊
2018.08.10