#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define SIZE 5//用來標識數組元素個數
sbit dht11=P2^1;//dht11為dht模塊數據位
sbit lcden =P3^4;//1602使能
sbit lcdrs =P3^5;//1602數據or命令寫選擇口
sbit dula = P2^6;
sbit wela = P2^7;
uchar code table[]={'0','1','2','3','4','5','6','7','8','9'};
uchar datas[SIZE];//存放值的數組
uchar temp_hvalue,temp_lvalue,humi_hvalue,humi_lvalue,FLAG,RTFLAG;
void delay(uint z)//1ms延時
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void Delay10us() //@11.0592MHz
{
uchar i;
i--;
i--;
i--;
i--;
i--;
i--;
}
uchar dht11_readvalue()//讀一個字節
{
uchar value,temp1,i;
for(i=0;i<8;i++)
{
temp1=0;
FLAG=2;
while((!dht11)&&FLAG++);//等待50us的低電平結束,若超時間,FLAG溢出后自加1,變為1
Delay10us();
Delay10us();
Delay10us(); //延時30us后判斷是高電平還是低電平,以此判斷該位數據是0還是1
if(dht11)
temp1=1; // 如果dht11為1,則代表為高電平,則該位數據為1
while((dht11)&&FLAG++);//等待該次高電平剩余50us結束,變為0后跳出循環,若超時,FLAG變為1
if(FLAG==1)
break;
value<<=1;
value|=temp1;
}
return(value);//八次循環結束后,返回value的八位數據
}
uchar dht11_readtempandhumi()//讀一次的數據,共五個字節,溫濕度和校驗
{
uchar i,temp;//temp用來檢測前四byte之和是否為第五byte
dht11=0;//拉低數據線大于18ms,主機發送開始信號
delay(25);
dht11=1;//釋放數據線,用于檢測之后的從機80us低電平應答信號
Delay10us();
Delay10us();
Delay10us();
Delay10us();//延時40us檢測應答信號
dht11=1;//主機設為輸入,判斷從機響應信號,響應信號為80us低電平
if(!dht11)//檢測到低電平,若沒有,則不執行if
{
FLAG=2;
while((!dht11)&&FLAG++);//判斷從機是否發出 80us 的低電平響應信號是否結束
if(FLAG==1)
return 0;
FLAG=2;
while((dht11)&&FLAG++);//判斷從機是否發出 80us 的高電平信號是否結束
if(FLAG==1)
return 0;
for(i=0;i<SIZE;i++)//數據接收狀態
{
datas[i]=dht11_readvalue();
}
dht11=1; //釋放數據總線,為下一次傳輸做準備
temp=(datas[0]+datas[1]+datas[2]+datas[3]);//temp為檢測
if(temp==datas[4]) //數據校驗
{
RTFLAG=1;
}
if(RTFLAG==1)
{
RTFLAG=0;
humi_hvalue=datas[0];
humi_lvalue=datas[1];
temp_hvalue=datas[2];
temp_lvalue=datas[3];
}
}
}
void write_com(uchar com)//1602寫命令
{
lcdrs=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void write_data(uchar date)//1602寫數據
{
lcdrs=1;
P0=date;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
void init()//1602初始化
{
dula=0;
wela=0;
lcden=0;
write_com(0x38);
delay(1);
write_com(0x0c);
delay(1);
write_com(0x06);
delay(1);
write_com(0x01);
delay(1);
}
void LCD_Display()
{
//液晶顯示第一行:溫度顯示;
write_com(0x0c);
write_com(0x80+0x01);delay(5);
write_data('T');delay(5);
write_data('e');delay(5);
write_data('m');delay(5);
write_data(':');delay(5);
write_com(0x86);delay(5);
write_data(table[(temp_hvalue/10)]);delay(5); //輸出溫度的十位
write_data(table[(temp_hvalue%10)]);delay(5); //輸出溫度的個位
write_data('.');delay(5);
write_data(table[(temp_lvalue/10)]);delay(5);
write_data(table[(temp_lvalue%10)]);delay(5);
write_com(0x8c);delay(5);
write_data(0xdf);delay(5); //輸出℃
write_data(0x43);delay(5);
//液晶第二行:濕度顯示;
write_com(0x80+0x41);delay(5);
write_data('H');delay(5);
write_data('u');delay(5);
write_data('m');delay(5);
write_data(':');delay(5);
write_com(0xc6);delay(5);
write_data(table[(humi_hvalue/10)]);delay(5); //輸出濕度的十位
write_data(table[(humi_hvalue%10)]);delay(5); //輸出濕度的個位
write_data('.');delay(5);
write_data(table[(humi_lvalue/10)]);delay(5);
write_data(table[(humi_lvalue%10)]);delay(5);
write_com(0xcc);delay(5);
write_data('%');delay(5);
}
void main()
{
init();
delay(1000);
while(1)
{
delay(1000);
dht11_readvalue();
dht11_readtempandhumi();
delay(1000);
LCD_Display();
}
}
|