Contributed by WildboarG, organized by Ai-Thinker
Ai-WB2 Reading the DHT11 Temperature and Humidity Sensor
WB2 Reading the DHT11 Temperature and Humidity Sensor
Description
DHT11 can detect both temperature and humidity, but its accuracy and measurement range are lower than those of the DS18B20. Its temperature measurement range is 0~50°C with an error of ±2°C; its humidity measurement range is 20%~90%RH (Relative Humidity — the percentage of water vapor pressure relative to the saturated water vapor pressure in the air), with an error of ±5%RH.
The DHT11 circuit is very simple: you only need to connect the DATA pin to one I/O of the MCU, but this pin requires a 5K pull-up resistor. The DHT11 supply voltage is 3~5.5V.
The data format is: 8bit humidity integer data + 8bit humidity decimal data + 8bit temperature integer data + 8bit temperature decimal data + 8bit checksum, 5 bytes (40bit) in total.
Since the DHT11 resolution is only accurate to single digits, the decimal part is all zeros. The checksum is the sum of the first 4 bytes of data, and its purpose is to ensure the accuracy of data transmission.
The DHT11 only triggers a temperature and humidity measurement after receiving a start signal. If it does not receive the reset signal sent by the host, the DHT11 does not actively measure temperature and humidity. When data acquisition is complete and there is no start signal, the DHT11 automatically switches to low-speed mode.
Note: since the DHT11 timing requirements are very strict, to prevent interrupts from interfering with the bus timing, first disable the global interrupts when handling the timing, and re-enable them after the operation is complete. (One communication takes about 4ms)
Circuit Connection

Communication Timing

Code
Step by step
- Create a new project
dht11
Click to expand: > wb2-cli create
> wb2-cli create
> Create New Project:dht11
> successfuly- Write
main.cin the project directory
Click to expand full code
#
include
<stdio.h>
#
include
<FreeRTOS.h>
#
include
<task.h>
#
include
<bl_gpio.h>
#
include
<bl_timer.h>
#
include
<blog.h>
#
include
<dht11.h>
#
define
GPIO_DHT 4
//定义工作引脚
extern
unsigned
int
rec_data[
4
];
int
main
(
void
)
{
// add your code here
bl_gpio_enable_output(GPIO_DHT,
0
,
0
);
printf
(
"start DTH11\r\n"
);
while
(
1
) {
DHT11_REC_Data();
bl_timer_delay_us(
1000
*
1000
);
printf
(
"Temperature:%d°C Humidity:%d%% \r\n"
, rec_data[
2
], rec_data[
0
]);
}
}- Write
dht11.h
Click to expand full code
#
ifndef
__DHT11_H__
#
define
__DHT11_H__
#
include
"bl_timer.h"
#
include
<bl_gpio.h>
#
define
GPIO_DHT 4
#
define
dht11_high bl_gpio_output_set(GPIO_DHT, 1)
#
define
dht11_low bl_gpio_output_set(GPIO_DHT, 0)
#
define
Read_Data bl_gpio_input_get_value(GPIO_DHT)
void
DHT11_GPIO_Init_OUT
(
void
)
;
void
DHT11_GPIO_Init_IN
(
void
)
;
void
DHT11_Start
(
void
)
;
unsigned
char
DHT11_REC_Byte
(
void
)
;
void
DHT11_REC_Data
(
void
)
;
#
endif- Write the driver functions in
dht11.c
Click to expand full code
#
include
"dht11.h"
// 数据存放
unsigned
int
rec_data[
4
];
// 做为输出
void
DH11_GPIO_Init_OUT
(
void
)
{ bl_gpio_enable_output(GPIO_DHT,
0
,
0
); }
// 做为输入
void
DH11_GPIO_Init_IN
(
void
)
{ bl_gpio_enable_input(GPIO_DHT,
0
,
0
); }
// 主机发送开始信号
void
DHT11_Start
(
void
)
{
DH11_GPIO_Init_OUT();
// 输出模式
dht11_high;
// 先拉高
bl_timer_delay_us(
30
);
dht11_low;
// 拉低电平至少18us
bl_timer_delay_us(
20
*
1000
);
dht11_high;
// 拉高电平20~40us
bl_timer_delay_us(
30
);
DH11_GPIO_Init_IN();
// 输入模式
}
// 获取一个字节
char
DHT11_Rec_Byte
(
void
)
{
unsigned
char
i =
0
;
unsigned
char
data =
0
;
for
(i =
0
; i <
8
; i++)
// 1个数据就是1个字节byte,1个字节byte有8位bit
{
while
(Read_Data ==
0
)
;
// 从1bit开始,低电平变高电平,等待低电平结束
bl_timer_delay_us(
30
);
// 延迟30us是为了区别数据0和数据1,0只有26~28us
data <<=
1
;
// 左移
if
(Read_Data ==
1
)
// 如果过了30us还是高电平的话就是数据1
{
data |=
1
;
// 数据+1
}
while
(Read_Data ==
1
)
;
// 高电平变低电平,等待高电平结束
}
return
data;
}
// 获取数据
void
DHT11_REC_Data
(
void
)
{
unsigned
int
R_H =
0
, R_L =
0
, T_H =
0
, T_L =
0
;
unsigned
char
RH =
0
, RL =
0
, TH =
0
, TL =
0
, CHECK =
0
;
DHT11_Start();
// 主机发送信号
dht11_high;
// 拉高电平
if
(Read_Data ==
0
)
// 判断DHT11是否响应
{
while
(Read_Data ==
0
)
;
// 低电平变高电平,等待低电平结束
while
(Read_Data ==
1
)
;
// 高电平变低电平,等待高电平结束
R_H = DHT11_Rec_Byte();
R_L = DHT11_Rec_Byte();
T_H = DHT11_Rec_Byte();
T_L = DHT11_Rec_Byte();
CHECK = DHT11_Rec_Byte();
// 接收5个数据
dht11_low;
// 当最后一bit数据传送完毕后,DHT11拉低总线 50us
bl_timer_delay_us(
55
);
// 这里延时55us
dht11_high;
// 随后总线由上拉电阻拉高进入空闲状态。
if
(R_H + R_L + T_H + T_L ==
CHECK)
// 和检验位对比,判断校验接收到的数据是否正确
{
RH = R_H;
RL = R_L;
TH = T_H;
TL = T_L;
}
}
rec_data[
0
] = RH;
rec_data[
1
] = RL;
rec_data[
2
] = TH;
rec_data[
3
] = TL;
}- Compile it
Click to expand: make -j32
make -j32- Flash it
Click to expand: make flash
make flashDisplay
Open the serial assistant and check the result

Connection Diagram

Ran two jumper wires with a little helper gadget, and the result is quite good

