一.DHT11介绍
型号 | 测量范围 | 测湿精度 | 测温精度 |
DHT11 | 20-90%RH 0-50摄氏度°C | 士5%RH | 士2℃ |
二.DHT11接口说明
1.建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。
2.VCC接单片机的5v,GND接GND,DAT接单片机的IO口。
三.电源引脚
DHT11的供电电压为3-5.5V。传感器上电后,要等待1s以越过不稳定状态在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF的电容,用以去耦滤波。
四.DHT11时序图
DHT11初始化从图2开始,一开始先给高电平,然后在给低电平(至少18ms),之后高电平持续20-40us,不确定是多少us,可以用while卡着,定义DAT为dht,dht此时是1,则卡着while(dht),直到跳过while循环以后,DHT11开始响应,此时dht为0,我们也可以卡着,while(!dht),之后过了while循环以后,变成了高电平1,dht=1,此时接着卡,while(dht),当卡过以后开始传输数据(红线部分),如果传的是1则是图4,如果是0则图5,此时只要等待红线部分过去就有数据,此时接着卡,while(!dht),之后给40us延迟,如果40us延迟以后还是高电平则是数据1,数据1一共要维持70us高电平,此时才维持40us,我们要卡着高电平等待过去到下一bit开始,所以while(dht),如果是低电平则数据0,此时不需要卡着,已经来到了下一bit开始的位置。
五.传输数据
一次完整的数据传输为40bit,高位先出。
数据格式:8bit湿度整数数据+8 bit湿度小数数据+8bi温度整数数据+8 bit温度小数数据+8bit校验和
数据传送正确时校验和数据=“8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据”所得结果的末8位。
六.DHT11测温湿度发送到串口助手的代码
补充知识:下面代码的value=value<<1,value |= flag;在是因为DHT11传的数据高位先出,,要循环8次,所以最后一开始的第一位就到了二级制的最高位。
#include
#include
sbit led4 = P2^3; //led小灯用来判断模块是否测量
sbit dht = P1^0; //温湿度传感器信号线
sbit AUXR=0x8E;
char datas[5]; //数组分别代表,湿度,湿度小数,温度,温度小数,校验
void Delay20ms() //@11.0592MHz
{
unsigned char i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay40us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 15;
while (--i);
}
void Uart_Init()
{
AUXR = 0x01;
SCON = 0x40;
PCON &= 0x7F;
TMOD &= 0x0F; //清除定时器1模式位
TMOD |= 0x20; //设定定时器1为8位自动重装方式
TL1 = 0xFD; //设定定时初值
TH1 = 0xFD; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
void Uart_Sendchar(char Char)
{
SBUF=Char;
while(TI==0);
TI=0;
}
void Uart_Sendstring(char*string)
{
while(*string!='\0')
{
Uart_Sendchar(*string);
string++;
}
}
//初始化模块(检测模块是否存在)每次传输数据都要初始化
void DHT_Start()
{
//根据时序进行高低电平变化
led4 = 1;
dht = 1; //对应初始化时序start
dht = 0;
Delay20ms();
dht=1;
while(dht);
while(!dht);
while(dht);
led4 = 0;
}
void DHT11_Read()
{
char value = 0;
char flag;
char i = 0;
char j = 0;
DHT_Start();
for(j = 0;j<5;j++)//分别读取五组数据
{
for(i=0;i<8;i++)//每组八位分别处理
{
while(!dht); //高电平开始计时
Delay40us();
if(dht == 1) //如果还为高则是“1”
{
flag = 1;
while(dht);
}
else //否则“0”
{
flag = 0;
}
value = value << 1; //移位
value |= flag; //赋值
}
datas[j] = value; //赋值
}
}
void main()
{
Delay1000ms();Delay1000ms();
Uart_Init();
while(1)
{
Delay1000ms();
DHT11_Read();
Uart_Sendstring("H:");//湿度整数
Uart_Sendchar(datas[0]/10+0x30);//十位
Uart_Sendchar(datas[0]%10+0x30);//个位
Uart_Sendchar('.');//湿度小数
Uart_Sendchar(datas[1]/10+0x30);
Uart_Sendchar(datas[1]%10+0x30);
Uart_Sendstring("\r\n");
Uart_Sendstring("T:");//温度整数
Uart_Sendchar(datas[2]/10+0x30);
Uart_Sendchar(datas[2]%10+0x30);
Uart_Sendchar('.');//温度小数
Uart_Sendchar(datas[3]/10+0x30);
Uart_Sendchar(datas[3]%10+0x30);
Uart_Sendstring("\r\n");
}
}
七.DHT11测温湿度发送到LCD1602上的代码
#include
#include
#define LCE_Dataport P0
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
sbit led4 = P2^3; //led小灯用来方便判断DHT11有没有在测量
sbit dht = P1^0; //温湿度传感器信号线
sbit AUXR=0x8E;
char datas[5]; //数组分别代表,湿度,湿度小数,温度,温度小数,校验
void Delay1ms() //@11.0592MHz
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 11;
j = 190;
do
{
while (--j);
} while (--i);
}
void Delay20ms() //@11.0592MHz
{
unsigned char i, j;
i = 36;
j = 217;
do
{
while (--j);
} while (--i);
}
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
i = 8;
j = 1;
k = 243;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Delay40us() //@11.0592MHz
{
unsigned char i;
_nop_();
i = 15;
while (--i);
}
void LCD_WriteCommand(unsigned char Command)//写指令
{
LCD_RS=0;
LCD_RW=0;
LCE_Dataport=Command;
LCD_EN=1;
Delay1ms();
LCD_EN=0;
Delay1ms();
}
void LCD_WriteData(unsigned char Data)//写数据
{
LCD_RS=1;
LCD_RW=0;
LCE_Dataport=Data;
LCD_EN=1;
Delay1ms();
LCD_EN=0;
Delay1ms();
}
void LCD_Init()//初始化
{
LCD_WriteCommand(0x38);
LCD_WriteCommand(0x0C);
LCD_WriteCommand(0x06);
LCD_WriteCommand(0x01);
}
void LCD_Setcursor(unsigned char line,unsigned char column)
{
if(line==1)//设置光标位置
{
//第一列是数字1,但是位置是0x00,要把数字1转换0x00,就把数字1-1就0,所以转十六进制就是0x00
LCD_WriteCommand(0x80|(column-1));
}
else
{
//第二行的第一列是从0x40开始,第二列是0x41,相当于0x40+0x01,0x01就是与上面一致
LCD_WriteCommand(0x80|(column-1)+0x40);
}
}
void LCD_Showchar(unsigned char line,unsigned char column,unsigned char Char)//line行,column列,Char字符
{//显示一个字符
LCD_Setcursor(line,column);
LCD_WriteData(Char);
}
void LCD_Showstring(unsigned char line,unsigned char column,unsigned char *string)//line行,column列,string字符串
{//显示字符串,字符串直接等于指针,不用数组形式等于字符串,在等于指针形式,那传给指针的就是字符串的第一个字符的地址,然后string【i】一直往下就可以知道字符串,数组是连续的,如果baby的b在第一行第一列,那a就会在第一行,第二列。
unsigned char i;
LCD_Setcursor(line,column);
for(i=0;string[i]!='\0';i++)
{
LCD_WriteData(string[i]);//字符串本身就是地址,所以传进来的字符串用指针string来接
}
}
//初始化模块(检测模块是否存在)每次传输数据都要初始化
void DHT_Start()
{
//根据时序进行高低电平变化
led4 = 1;
dht = 1; //对应初始化时序start
dht = 0;
Delay20ms();
dht=1;
while(dht);
while(!dht);
while(dht);
led4=0;
}
void DHT11_Read()
{
char value = 0;
char flag;
char i = 0;
char j = 0;
DHT_Start();
for(j = 0;j<5;j++)//分别读取五组数据
{
for(i=0;i<8;i++)//每组八位分别处理
{
while(!dht); //高电平开始计时
Delay40us();
if(dht == 1) //如果还为高则是“1”
{
flag = 1;
while(dht);
}
else //否则“0”
{
flag = 0;
}
value = value << 1; //移位
value |= flag; //赋值
}
datas[j] = value; //赋值
}
}
void main()
{
Delay1000ms();Delay1000ms();
LCD_Init();
while(1)
{
Delay1000ms();
DHT11_Read();
LCD_Showstring(1,1,"H:");//湿度整数
LCD_Showchar(1,3,datas[0]/10+0x30);//十位
LCD_Showchar(1,4,datas[0]%10+0x30);//个位
LCD_Showchar(1,5,'.');//湿度小数
LCD_Showchar(1,6,datas[1]/10+0x30);
LCD_Showchar(1,7,datas[1]%10+0x30);
LCD_Showstring(2,1,"T:");//温度整数
LCD_Showchar(2,3,datas[2]/10+0x30);
LCD_Showchar(2,4,datas[2]%10+0x30);
LCD_Showchar(2,5,'.');//温度小数
LCD_Showchar(2,6,datas[3]/10+0x30);
LCD_Showchar(2,7,datas[3]%10+0x30);
}
}
八.现象
DHT11模块不要碰底下,不然会卡住不测量了,led4用来判断有没有一直在测量,闪一次就代表正测量一次