主代码,还有个LCD1602的设置代码
#include<reg51.h>
#include<intrins.h>
#include<LCD1602.h>
#define uchar unsigned char
#define uint unsigned int
sbit Data=P3^6; //定义数据线
sbit BUZZER=P2^4;
uchar rec_dat[9]; //用于显示的接收数据数组
int Tmax=40,Tmin=10;//设定最高温度40度,最低温度10度
int Rmax=80,Rmin=40;//设定最高湿度80%,最低湿度40%
bit fg=1;
//初始化函数
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,RH,RL,TH,TL,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;
}
/*数据处理,方便显示*/
rec_dat[0]='0'+(RH/10);
rec_dat[1]='0'+(RH%10);
rec_dat[2]='R';
rec_dat[3]='H';
rec_dat[4]=' ';
rec_dat[5]=' ';
rec_dat[6]='0'+(TH/10);
rec_dat[7]='0'+(TH%10);
rec_dat[8]='C';
}
}
void Alarm()//警报函数
{
uchar R_H,R_L,T_H,T_L,RH,RL,TH,TL,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;
}
if(TH+TL<=Tmin||TH+TL>=Tmax||RH+RL<=Rmin||RH+RL>=Rmax)//低于下限,高于上限就会触发警报
BUZZER=0;
else
BUZZER=1;
}
}
void main()
{
LCD_init();
LCD_send(1,0,"Temperature:",12);
DHT11_delay_ms(100); //DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令
while(1)
{
DHT11_receive();
LCD_send(2,0,rec_dat,9);
Alarm();//警报函数
}
}
LCD1602的代码
#include <LCD1602.h>
#include "reg51.h"
sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;
void LCD_send(unsigned char i,unsigned char j,unsigned char str[],unsigned char n)
{
//输入:显示行数i,列数j,输出字符,输出字符长度n
unsigned char x=0;
if(i==1)
{write_com(0x80+j);}
else
{write_com(0x80+0x40+j);}
for(x=0;x<n;x++)
{
write_date(str[x]);
delay(150);
}
}
int LCD_init()//初始化函数体
{
EN = 0;
write_com(0X38);//设置16*2显示,5*7点阵,8位数据接口
write_com(0X0C);//设置开显示,不显示光标
write_com(0X06);//写一个字符时,整屏右移
write_com(0X01);//显示清零
return 0;
}
int write_com(unsigned char com)//写命令的函数体
{
RS = 0;
RW = 0;
P0 = com;
delay(5);
EN = 1;
delay(5);
EN = 0;
return 0;
}
int write_date(unsigned char data1)//写数据的函数体
{
RS = 1;
RW = 0;
P0 = data1;
delay(5);
EN = 1;
delay(5);
EN = 0;
return 0;
}
int delay(unsigned char xms)
{
unsigned char x,y;
for(x=xms;x>0;x--)
for(y=110;y>0;y--);
return 0;
}
仿真效果图如下