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