介绍
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器,包括一个电阻式感湿元件和一个NTC测温元件,可以用来测量温度和湿度。
硬件连线
本实验使用STM32F103C8T6芯片作为主控,使用DHT11(带上拉电阻)模块作为温湿度采集装置。
接线如下表所示:
名称 |
STM32 |
注释 |
VCC |
3.3V |
供电 3.3V |
OUT |
PB13(任意一个GPIO口即可) |
串行数据 |
GND |
GDN |
接地 |
由于使用了上拉电阻,因此STM32与DHT11的通信类似于软件模拟IIC通信协议。使用开漏输出模式(OD)控制PB13的高低电平。(如果不懂什么是软件模拟IIC的话,请移步软件I2C读写MPU6050_哔哩哔哩_bilibili)
DHT11
本教程使用DHT11模块如下图所示:
DHT11协议
概述
STM32与 DHT11之间的通信,采用单总线数据格式,一次通信时间4ms左右。
总体通信流程为:开始信号->响应信号->数据传输。
STM32发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束。DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。
注:DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。
总体操作时序如下图所示:
开始信号(STM32控制总线)
首先主机拉低总线至少 18ms,然后再拉高总线,延时 20~40us,取中间值 30us,此时复位信号发送完毕。
是拉低总线18毫秒,不是18微秒,搞错的话是不能正常通信的!
响应信号(DHT11控制总线)
DHT11 检测到复位信号后,触发一次采样,并拉低总线 80us 表示响应信号,告诉主机数据已经准备好了;然后 DHT11 拉高总线 80us,之后开始传输数据。
数据传输(DHT11控制总线)
之后,每 1bit 数据都以 50us 低电平时隙开始。
DHT11 以高电平的长短定义数据位是 0 还是 1。当 50us 低电平时隙过后拉高总线,高电平持续 26~28us 表示数据“0”;持续 70us 表示数据“1”。如下表所示:
输出 |
表示方法 |
数字0 |
50us低电平开始后,26-28us的高电平表示0 |
数字1 |
50us低电平开始后,70us的高电平表示1 |
数据传输结束
当最后一bit数据传送完毕后,DHT11拉低总线50us,随后释放总线,由上拉电阻拉高进入空闲状态。
DHT11数据格式
一次完整的数据传输为40bit,高位先出。数据分小数部分和整数部分,数据格式:
- 8bit湿度整数数据
- 8bit湿度小数数据
- 8bit温度整数数据
- 8bit温度小数数据
- 8bit校验和
若数据传送正确,则
校验和数据 = “8bit 湿度整数数据 +8bit 湿度小数数据+8bit温度整数数据 +8bit 温度小数数据”所得结果的末8位。
STM32代码
需要添加delay.h、oled.h等头文件时,还请自行添加。
DHT11驱动代码
头文件
宏定义“使用引脚”和“控制IO输出1和0的函数”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #ifndef __DHT11_H #define __DHT11_H
#define DHT11_GPIO_Port GPIOB #define DHT11_GPIO_Pin GPIO_Pin_13
#define dht11_high GPIO_SetBits(DHT11_GPIO_Port, DHT11_GPIO_Pin) #define dht11_low GPIO_ResetBits(DHT11_GPIO_Port, DHT11_GPIO_Pin) #define DHT11_IN GPIO_ReadInputDataBit(DHT11_GPIO_Port, DHT11_GPIO_Pin)
void DH11_GPIO_Init(void); uint8_t DHT11RstAndCheck(void); uint8_t DHT11ReadByte(void); uint8_t DHT11ReadData(uint8_t *Temp_H,uint8_t *Temp_L,uint8_t *Humi_H,uint8_t *Humi_L);
#endif
|
初始化
初始化DHT11使用引脚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
void DH11_GPIO_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_Pin; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStructure); }
|
复位和检查响应
该函数将“STM32发送开始信号”与“STM32接受响应信号”放置一起
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
uint8_t DHT11RstAndCheck(void) { uint8_t timer = 0;
__set_PRIMASK(1); dht11_low; Delay_ms(20); dht11_high; Delay_us(30); while (!DHT11_IN) { timer++; Delay_us(1); } if (timer>100 || timer<20) { __set_PRIMASK(0); return 0; }
timer = 0; while (DHT11_IN) { timer++; Delay_us(1); } __set_PRIMASK(0); if (timer>100 || timer<20) { return 0; }
return 1; }
|
获取一个字节数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
uint8_t DHT11ReadByte(void) { uint8_t i; uint8_t byt = 0;
__set_PRIMASK(1); for (i=0; i<8; i++) { while (DHT11_IN);
while (!DHT11_IN);
Delay_us(40); byt <<= 1; if (DHT11_IN) { byt |= 0x01; } } __set_PRIMASK(0);
return byt; }
|
获取DHT11全部数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
uint8_t DHT11ReadData(uint8_t *Temp_H,uint8_t *Temp_L,uint8_t *Humi_H,uint8_t *Humi_L) { uint8_t sta = 0; uint8_t i; uint8_t buf[5];
if (DHT11RstAndCheck()) { for(i=0;i<5;i++) { buf[i]=DHT11ReadByte(); } if(buf[0]+buf[1]+buf[2]+buf[3] == buf[4]) { *Humi_H = buf[0]; *Humi_L = buf[1]; *Temp_H = buf[2]; *Temp_L = buf[3]; } sta = 0; } else { *Temp_H = 0; *Temp_L = 0; *Humi_H = 0; *Humi_L = 0; sta = 1; }
return sta; }
|
main函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| int main(void) { DH11_GPIO_Init(); uint8_t Temp_H = 0; uint8_t Temp_L = 0; uint8_t Humi_H = 0; uint8_t Humi_L = 0; while (1) { DHT11ReadData(Temp_H,Temp_L,Humi_H,Humi_L); OLED_ShowNum(1,7,Temp_H,2); OLED_ShowNum(1,10,Temp_L,1); OLED_ShowNum(2,7,Humi_H,2); OLED_ShowNum(2,10,Humi_L,1); } }
|
实验效果
实验效果如下图所示:
参考链接
本实验实现过程中参考:
DHT11详细介绍(内含51和STM32代码)-CSDN博客
STM32外接DHT11显示温湿度_stm32与dht11连接用了什么协议-CSDN博客
如果有什么问题和建议,还请读者指出