|
#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;
}
}
|
|