|
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit Data=P3^6; //定义数据线
uchar rec_dat[20]; //用于显示的接收数据数组
int RH,RL,TH,TL,i;
sbit lcdrs=P2^5;
sbit lcdrw=P2^6;
sbit lcden=P2^7;
sbit K1=P3^2;
sbit K2=P3^3;
sbit K3=P1^1;
sbit K4=P1^2;
sbit beep=P1^0;
int W,S;
uint menu=0;//(定义变量)
uchar flat=0;
uchar WenDu=0x0f,ShiDu=30;//报警的温度和湿度
void delay(uint n)
{ uint x,y;
for(x=n;x>0;x--)
for(y=110;y>0;y--);
}
void delay1ms()
{
unsigned char i,j;
for(i=0;i<10;i++)
for(j=0;j<33;j++);
}
void write_com(uchar com)
{
lcdrs=0; //rs=0时输入指令
P0=com;
delay(5);
lcden=1; //en=1时读取信息
delay(5);
lcden=0; //1 -> 0 执行指令
}
void write_dat(uchar dat)
{
lcdrs=1; //rs=1时输入数据
P0=dat;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init_lcd()
{
lcden=0;
lcdrw=0;
write_com(0x38); //8位数据,双列,5*7字形
write_com(0x0c); //开启显示屏,关光标,光标不闪烁
write_com(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
write_com(0x01);
}
void DHT11_delay_us(uchar n)
{
while(--n);
}
void DHT11_delay_ms(uint z)
{
uint 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(30); //延时18ms以上
Data=1;
DHT11_delay_us(30);
}
uchar DHT11_rec_byte() //接收一个字节
{
uchar 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位的数据
{
uchar R_H,R_L,T_H,T_L,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;
}
}
}
/*这里使用lcd1602来显示采集到的数据,lcd1602驱动程序在博主的51单片机系列博文中有详细讲解*/
void main()
{
EA=1;
EX0=1;
IT0=1;
EX1=1;
IT0=1;
TMOD=0X01; //设置T0为方式1 GATE=0;
ET0=1;
TH0=0;
TL0=0;
init_lcd(); //lcd1602初始化
while(1)
{
DHT11_delay_ms(100); //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
DHT11_receive();
if(TH>=WenDu||RH>=ShiDu){
beep=~beep;
}else{
beep=0;
}
switch(menu){
case 0:
write_com(0x80); //从lcd1602第一行第一个位置开始显示
write_dat('H');
write_dat('H'); //显示数据
write_dat('U');
write_dat('M');
write_dat('I');
write_dat(':');
write_dat(RH/10+0X30);
write_dat(RH%10+0X30);
write_dat(' ');
write_dat('H');
write_dat('M');
write_dat(':');
write_dat(ShiDu/10+0x30);
write_dat(ShiDu%10+0x30);
write_com(0x80+0x40);
write_dat('T');
write_dat('E');
write_dat('M');
write_dat('P');
write_dat(':');
write_dat(TH/10+0X30);
write_dat(TH%10+0X30);
write_dat(' ');
write_dat('T');
write_dat('M');
write_dat(':');
write_dat(WenDu/10+0x30);
write_dat(WenDu%10+0x30);
break;
case 1:
if(!K3){
ShiDu++;
}
if(!K4){
ShiDu--;
}
write_com(0x80); //从lcd1602第一行第一个位置开始显示
for(i=0;i<15;i++){
write_dat(0x01);
}
write_com(0x80);
write_dat('H'); //显示数据
write_dat('U');
write_dat('M');
write_dat('I');
write_dat(':');
write_dat(RH/10+0X30);
write_dat(RH%10+0X30);
write_dat(' ');
write_dat('H');
write_dat('M');
write_dat(':');
write_dat(ShiDu/10+0x30);
write_dat(ShiDu%10+0x30);
write_dat(' ');
write_com(0x80+0x40);
for(i=0;i<15;i++){
write_dat(0x01);
}
break;
case 2:
if(!K3){
WenDu++;
}
if(!K4){
WenDu--;
}
write_com(0x80); //从lcd1602第一行第一个位置开始显示
for(i=0;i<15;i++){
write_dat(0x01);
}
write_com(0x80);
write_dat('T');
write_dat('E');
write_dat('M');
write_dat('P');
write_dat(':');
write_dat(TH/10+0X30);
write_dat(TH%10+0X30);
write_dat(' ');
write_dat('T');
write_dat('M');
write_dat(':');
write_dat(WenDu/10+0x30);
write_dat(WenDu%10+0x30);
write_com(0x80+0x40);
for(i=0;i<15;i++){
write_dat(0x01);
}
break;
}
}
}
int0() interrupt 0 //按键程序 选择菜单模式
{
menu++;
delay(10);
if(menu>=3)
{
menu=0;
}
}
|
|