#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dat=P2^2; //收集DHT11的數據
sbit RS=P1^0; //1602顯示
sbit RW=P1^1;
sbit EN=P2^5;
sbit PWM=P2^0;
sbit IN3=P2^3;
sbit IN4=P2^4;
uchar DHT11[5],RTflag=0;
uchar FLAG; //超時標志位
unsigned char timer1;
unsigned char CYCLE; //定義周期,如果是20,則周期是20*0.5ms
unsigned char PWMON; //定義高電平時間
void Delay_t(uint j)
{ uchar i;
for(;j>0;j--)
{
for(i=0;i<27;i++);
}
}
void Delay_10us(void) //10us延時函數
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
void delay(uint z)//1毫秒延時函數
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void lcd_write_com(uchar com) //1602寫指令
{
RS=0;
RW=0;
EN=1;
P0=com;
delay(5);
EN=0;
}
void lcd_init() //1602初始化
{
lcd_write_com(0x38);
delay(1);
lcd_write_com(0x08);
delay(1);
lcd_write_com(0x01);//1602清屏
delay(1);
lcd_write_com(0x06);
delay(1);
lcd_write_com(0x0c);//設置開顯示
delay(1);
}
void lcd_write_data(uchar date)//1602寫數據
{
RS=1;
RW=0;
EN=1;
P0=date;
delay(1);
EN=0;
}
void write_str(uchar x,uchar y,uchar *s)//在任意地址寫符號
{
if(y==0)
lcd_write_com(0x80+x);
else
lcd_write_com(0xc0+x);
while(*s)
{
lcd_write_data(*s);
s++;
}
}
void write_shu(uchar x,uchar y,uchar num)//數據顯示函數
{
uchar s,g;
if(y==0)
lcd_write_com(0x80+x);
else
lcd_write_com(0xc0+x);
s=num/10; // 數據分離顯示
lcd_write_data(0x30+s);
g=num%10; //數據分離顯示
lcd_write_data(0x30+g);
}
uchar write_byte1() //讀一個字節
{
uchar i,comdata,temp1;
for(i=0;i<8;i++)
{
FLAG=2;
while((!dat)&&FLAG++);//判斷數據位是1還是0
Delay_10us();
Delay_10us();
Delay_10us();
temp1=0;
if(dat==1)
temp1=1;
FLAG=2;
while((dat)&&FLAG++)
if(FLAG==1)
break;
comdata<<=1;
comdata|=temp1;
}
return (comdata);
}
void DHT11_5() //dht11讀5個字節
{
uchar i,temp; //主機拉低18MS
dat=0;
Delay_t(150);
dat=1; //總線由上拉電阻拉高,主機延時20us
Delay_10us();
Delay_10us();
Delay_10us();
Delay_10us();
dat=1;
if(!dat)
{
FLAG=2;
while((!dat)&&FLAG++);
FLAG=2;
while((dat)&&FLAG++);
for(i=0;i<5;i++)
{
DHT11[i]=write_byte1();
}
dat=1;
temp=(DHT11[0]+DHT11[1]+DHT11[2]+DHT11[3]);
if(temp==DHT11[4]) //數據校驗位
{
RTflag=1;
}
if(RTflag==1) //如果RTflag=1說明讀到的數據正確
{
RTflag=0;
write_str(0,0,"RH:");//第一行顯示字符
write_shu(3,0,DHT11[0]);//顯示濕度
write_str(5,0,"%");
write_str(0,1,"TP:");//顯示溫度
write_shu(3,1,DHT11[2]);//顯示溫度
write_str(5,1,"^C");
}
}
}
void kongzhi() //溫度控制
{
if(DHT11[0]<=69)
{
IN3=1;
IN4=1;
}
if(DHT11[0]>=70&&DHT11[0]<=79)
{
IN3=1;
IN4=0;
PWMON=15;
}
if(DHT11[0]>=80&&DHT11[0]<=89)
{
IN3=1;
IN4=0;
PWMON=10;
}
if(DHT11[0]>=90&&DHT11[0]<=95)
{
IN3=1;
IN4=0;
PWMON=3;
}
}
void main()
{
TMOD=0x01;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256;
EA=0x82;
ET0=1;
TR0=1;
CYCLE=20;
lcd_init(); //1602初始化
delay(10); //等待DHT11傳感器數據穩定開始激活DHT11
while(1)
{
kongzhi();
delay(5);//等待DHT11傳感器數據穩定開始激活DHT11
write_byte1();//讀一個字節
DHT11_5(); //讀數據
delay(10); //延時等待
}
}
void Time1(void) interrupt 3 //3 為定時器1的中斷號 1 定時器0的中斷號 0 外部中斷1 2 外部中斷2 4 串口中斷
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
timer1++;
}
void time(void) interrupt 1 using 1
{
static unsigned char count;
TH0=(65536-1000)/256;
TL0=(65536-1000)%256; //定時0.5秒
if(count==PWMON)
{
PWM=1; //PWM輸出
}
if(count==CYCLE)
{
count=0;
if(PWMON!=0) //如果左右時間是0保持原來狀態
PWM=0;
}
count++;
}
|