STM32CubeMX驱动DHT11温湿度传感器:从引脚配置到串口打印的完整流程(附代码)
·
STM32CubeMX驱动DHT11温湿度传感器:从引脚配置到串口打印的完整流程
在嵌入式开发中,温湿度传感器是常见的环境监测组件,而DHT11因其简单易用、成本低廉的特点,成为入门级项目的首选。本文将详细介绍如何利用STM32CubeMX这一强大的图形化配置工具,结合HAL库快速实现DHT11传感器的驱动开发,并通过串口输出温湿度数据。
1. 环境准备与CubeMX基础配置
开始之前,确保已安装STM32CubeMX和对应的IDE(如Keil MDK或IAR)。我们以STM32F103C8T6为例,演示完整的配置流程。
打开CubeMX后,首先进行时钟配置:
- 选择正确的芯片型号
- 在Clock Configuration选项卡中启用外部高速时钟(HSE)
- 配置系统时钟为72MHz(根据具体芯片调整)
接下来配置调试接口:
/* 在SYS选项卡中 */
Debug: Serial Wire
对于串口输出,我们使用USART1:
Mode: Asynchronous
Baud Rate: 115200
Word Length: 8 Bits
Parity: None
Stop Bits: 1
2. GPIO动态配置与DHT11通信实现
DHT11使用单总线协议,同一引脚需要在不同时刻切换输入/输出模式。CubeMX默认不支持动态模式切换,需要手动处理。
2.1 引脚配置技巧
在CubeMX中,我们先将连接DHT11的GPIO(如PB7)配置为输出模式:
GPIO output level: High
GPIO mode: Output Push Pull
Pull-up/Pull-down: No pull-up and no pull-down
Maximum output speed: Low
然后在代码中实现模式切换函数:
void DHT11_GPIO_Mode(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t mode) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_Pin;
GPIO_InitStruct.Mode = mode;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOx, &GPIO_InitStruct);
}
2.2 精确延时实现
DHT11协议要求微秒级延时精度。HAL库的HAL_Delay()只能实现毫秒级延时,我们需要自定义微秒延时:
void delay_us(uint16_t us) {
__HAL_TIM_SET_COUNTER(&htimX, 0);
while(__HAL_TIM_GET_COUNTER(&htimX) < us);
}
注意:需要先配置一个基本定时器(如TIM2),预分频值设为72-1,这样计数器每1MHz计数,即1us计数一次。
3. DHT11协议实现与数据解析
DHT11的通信流程分为三个主要阶段:启动信号、响应检测和数据传输。
3.1 启动信号时序
void DHT11_Start(void) {
// 设置引脚为输出模式
DHT11_GPIO_Mode(DHT11_GPIO_Port, DHT11_Pin, GPIO_MODE_OUTPUT_PP);
// 主机拉低至少18ms
HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_RESET);
HAL_Delay(20);
// 主机拉高20-40us
HAL_GPIO_WritePin(DHT11_GPIO_Port, DHT11_Pin, GPIO_PIN_SET);
delay_us(30);
// 切换为输入模式等待响应
DHT11_GPIO_Mode(DHT11_GPIO_Port, DHT11_Pin, GPIO_MODE_INPUT);
}
3.2 数据位解析
DHT11每个数据位以50us低电平开始,高电平持续时间决定数据值:
- 26-28us表示'0'
- 70us表示'1'
uint8_t DHT11_Read_Bit(void) {
while(HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_RESET);
delay_us(40);
return HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin);
}
uint8_t DHT11_Read_Byte(void) {
uint8_t data = 0;
for(int i=0; i<8; i++) {
data <<= 1;
if(DHT11_Read_Bit()) {
data |= 1;
}
}
return data;
}
4. 数据整合与串口输出
完整的温湿度读取函数如下:
uint8_t DHT11_Read_Data(float *temperature, float *humidity) {
uint8_t data[5] = {0};
DHT11_Start();
// 等待DHT11响应
if(HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_SET) return 1;
while(HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_RESET);
while(HAL_GPIO_ReadPin(DHT11_GPIO_Port, DHT11_Pin) == GPIO_PIN_SET);
// 读取40位数据
for(int i=0; i<5; i++) {
data[i] = DHT11_Read_Byte();
}
// 校验数据
if(data[4] != (data[0] + data[1] + data[2] + data[3])) return 2;
*humidity = data[0] + data[1] * 0.1;
*temperature = data[2] + data[3] * 0.1;
return 0;
}
串口输出格式化函数:
void Print_Sensor_Data(float temp, float hum) {
char buffer[64];
int len = sprintf(buffer, "Temperature: %.1fC\r\nHumidity: %.1f%%\r\n", temp, hum);
HAL_UART_Transmit(&huart1, (uint8_t*)buffer, len, HAL_MAX_DELAY);
}
5. 主程序逻辑与错误处理
在主循环中实现定期读取和错误处理:
while (1) {
float temp, hum;
uint8_t ret = DHT11_Read_Data(&temp, &hum);
switch(ret) {
case 0:
Print_Sensor_Data(temp, hum);
break;
case 1:
printf("DHT11 not responding\r\n");
break;
case 2:
printf("Data checksum error\r\n");
break;
}
HAL_Delay(2000); // 2秒读取一次
}
6. 常见问题排查
在实际项目中可能会遇到以下问题:
-
无响应或数据全零
- 检查电源电压(3.3V-5V)
- 确认上拉电阻(4.7kΩ-10kΩ)
- 检查接线是否正确
-
数据不稳定或校验错误
- 确保延时函数精度
- 缩短传感器与MCU的距离
- 增加读取失败后的重试机制
-
串口无输出
- 检查波特率设置
- 确认TX/RX接线
- 验证串口初始化代码
对于需要更高精度的场景,可以考虑升级到DHT22或SHT系列传感器。DHT11的典型精度为±2℃(温度)和±5%RH(湿度),适合对精度要求不高的场合。
更多推荐


所有评论(0)