保姆级教程:用STM32F103C8T6驱动DHT11,从接线到串口打印温湿度一气呵成
从零玩转STM32与DHT11手把手实现温湿度监测系统当你第一次拿到STM32开发板和DHT11传感器时那种既兴奋又忐忑的心情我完全理解。本文将带你完成一个完整的温湿度监测项目从硬件连接到代码编写再到数据读取和显示确保你能获得第一次成功的成就感。不同于普通的教程我会分享一些实际项目中容易踩的坑和调试技巧。1. 硬件准备与连接在开始编程之前正确的硬件连接是项目成功的基础。你需要准备以下组件STM32F103C8T6最小系统板蓝色药丸板DHT11温湿度传感器模块USB转TTL串口模块如CH340G杜邦线若干建议使用不同颜色区分功能关键连接步骤电源连接将DHT11的VCC引脚连接到STM32的3.3V电源将DHT11的GND引脚连接到STM32的地线数据线连接将DHT11的DATA引脚连接到STM32的PA1引脚可根据需要更改串口连接用于调试输出连接STM32的PA9(TX)到USB转TTL模块的RX连接STM32的PA10(RX)到USB转TTL模块的TX共地连接GND到GND注意DHT11模块有上拉电阻版本和无上拉电阻版本。如果是无上拉版本需要在DATA线和VCC之间接一个4.7kΩ的上拉电阻。常见连接错误及排查现象可能原因解决方法DHT11完全不响应电源接反或电压不足检查VCC和GND连接确保供电3.3-5V数据不稳定未接上拉电阻添加4.7kΩ上拉电阻串口无输出TX/RX接反交换TX和RX连接2. 开发环境配置工欲善其事必先利其器。我们需要搭建完整的开发环境安装Keil MDK下载并安装Keil MDK-ARM最新版本安装STM32F1系列设备支持包创建新工程Project → New μVision Project → 选择STM32F103C8T6设备配置工程选项在Target选项卡中勾选Use MicroLIB便于使用printf在C/C选项卡的Define中添加USE_STDPERIPH_DRIVER添加必要库文件STM32标准外设库串口通信库系统时钟配置关键配置代码示例system_stm32f10x.cvoid SystemInit(void) { // 设置系统时钟为72MHz RCC-CFGR | RCC_CFGR_PLLMULL9; RCC-CFGR | RCC_CFGR_PLLSRC; RCC-CR | RCC_CR_PLLON; while(!(RCC-CR RCC_CR_PLLRDY)); RCC-CFGR | RCC_CFGR_SW_PLL; while((RCC-CFGR RCC_CFGR_SWS) ! RCC_CFGR_SWS_PLL); }3. DHT11驱动实现DHT11采用单总线协议通信时序是关键。让我们深入理解并实现驱动代码。3.1 理解DHT11通信协议DHT11的通信过程分为几个阶段主机启动信号拉低总线至少18ms然后拉高20-40μs等待DHT11响应DHT11响应拉低总线80μs作为响应信号然后拉高80μs准备发送数据数据传输每位数据以50μs低电平开始高电平持续时间决定数据位值26-28μs表示070μs表示1数据格式40位数据包含16位湿度数据整数小数16位温度数据整数小数8位校验和3.2 关键驱动代码实现GPIO配置函数// 设置PA1为输出模式 void DHT11_IO_OUT(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); } // 设置PA1为输入模式 void DHT11_IO_IN(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU; GPIO_Init(GPIOA, GPIO_InitStructure); }复位和检测函数// 发送复位信号 void DHT11_Rst(void) { DHT11_IO_OUT(); // 设置为输出模式 DHT11_DQ_LOW; // 拉低DQ线 Delay_ms(20); // 保持至少18ms DHT11_DQ_HIGH; // 释放总线 Delay_us(30); // 主机等待20-40μs } // 检测DHT11响应 uint8_t DHT11_Check(void) { uint8_t retry 0; DHT11_IO_IN(); // 设置为输入模式 // 等待DHT11拉低总线 while(DHT11_DQ_READ retry100) { retry; Delay_us(1); } if(retry100) return 1; retry 0; // 等待DHT11拉高总线 while(!DHT11_DQ_READ retry100) { retry; Delay_us(1); } if(retry100) return 1; return 0; }数据读取函数// 读取一个位 uint8_t DHT11_Read_Bit(void) { uint8_t retry 0; while(DHT11_DQ_READ retry100) // 等待低电平 { retry; Delay_us(1); } retry 0; while(!DHT11_DQ_READ retry100) // 等待高电平 { retry; Delay_us(1); } Delay_us(40); // 等待40μs后采样 return DHT11_DQ_READ ? 1 : 0; } // 读取一个字节 uint8_t DHT11_Read_Byte(void) { uint8_t i, dat 0; for(i0; i8; i) { dat 1; dat | DHT11_Read_Bit(); } return dat; } // 读取温湿度数据 uint8_t DHT11_Read_Data(uint8_t *temp, uint8_t *humi) { uint8_t buf[5]; uint8_t i; DHT11_Rst(); if(DHT11_Check() 0) { for(i0; i5; i) { buf[i] DHT11_Read_Byte(); } // 校验数据 if((buf[0] buf[1] buf[2] buf[3]) buf[4]) { *humi buf[0]; *temp buf[2]; return 0; // 成功 } } return 1; // 失败 }4. 系统集成与调试现在我们将所有部分整合起来实现完整的温湿度监测系统。4.1 串口配置与printf重定向为了方便调试和数据查看我们需要配置串口并重定向printf// 串口初始化 void USART1_Init(uint32_t baudrate) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); // 配置TX(PA9)为复用推挽输出 GPIO_InitStructure.GPIO_Pin GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); // 配置RX(PA10)为浮空输入 GPIO_InitStructure.GPIO_Pin GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); USART_InitStructure.USART_BaudRate baudrate; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART1, USART_InitStructure); USART_Cmd(USART1, ENABLE); } // printf重定向 int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while(USART_GetFlagStatus(USART1, USART_FLAG_TC) RESET); return ch; }4.2 主程序实现int main(void) { uint8_t temperature 0; uint8_t humidity 0; // 初始化系统时钟 SystemInit(); // 初始化DHT11 DHT11_Init(); // 初始化串口 USART1_Init(115200); printf(STM32 DHT11温湿度监测系统启动...\r\n); while(1) { if(DHT11_Read_Data(temperature, humidity) 0) { printf(温度: %d℃ 湿度: %d%%\r\n, temperature, humidity); } else { printf(读取DHT11数据失败!\r\n); } Delay_ms(2000); // 每2秒读取一次 } }4.3 常见问题与调试技巧问题1DHT11无响应检查电源连接是否正确确认上拉电阻是否接好如有需要检查DATA线连接是否牢固尝试降低通信速度增加延时问题2数据校验失败确保时序精确特别是延时时间检查电源稳定性电压波动会影响通信尝试缩短DATA线长度最好不超过20cm问题3串口无输出确认TX/RX连接正确检查波特率设置是否匹配验证printf重定向是否正确实现调试技巧使用逻辑分析仪可以直观地观察DHT11的通信时序帮助定位问题。分段调试printf(开始复位DHT11...\r\n); DHT11_Rst(); printf(复位完成等待响应...\r\n); if(DHT11_Check() 0) { printf(DHT11响应成功\r\n); }延时微调不同批次的DHT11可能对时序要求略有不同可以尝试微调延时参数。5. 项目优化与扩展基础功能实现后我们可以考虑以下优化和扩展方向5.1 提高测量精度虽然DHT11的精度有限但我们可以通过软件方法提高稳定性多次测量取平均#define SAMPLE_TIMES 5 uint8_t get_average_temperature() { uint8_t sum 0; uint8_t temp, humi; for(int i0; iSAMPLE_TIMES; i) { if(DHT11_Read_Data(temp, humi) 0) { sum temp; } Delay_ms(100); } return sum / SAMPLE_TIMES; }数据滤波实现滑动平均滤波或中值滤波算法5.2 低功耗优化对于电池供电的应用可以优化功耗间歇工作模式void enter_low_power_mode() { // 关闭不必要的外设 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, DISABLE); // 配置为待机模式 PWR_EnterSTANDBYMode(); }延长测量间隔根据应用需求调整采样频率5.3 添加显示功能除了串口输出可以添加OLED或LCD显示void show_on_oled(uint8_t temp, uint8_t humi) { OLED_Clear(); OLED_ShowString(0, 0, Temperature:); OLED_ShowNum(0, 2, temp, 2, 16); OLED_ShowString(0, 4, Humidity:); OLED_ShowNum(0, 6, humi, 2, 16); }5.4 无线传输扩展通过添加ESP8266或蓝牙模块实现无线数据传输void send_via_wifi(uint8_t temp, uint8_t humi) { char buffer[50]; sprintf(buffer, ATCIPSEND%d, strlen(buffer)); ESP8266_SendCmd(buffer); sprintf(buffer, temp%dhumi%d, temp, humi); ESP8266_SendData(buffer); }6. 实际应用案例让我们看一个将本项目应用于智能家居系统的实际案例智能植物监控系统硬件组成STM32F103C8T6主控DHT11温湿度传感器土壤湿度传感器继电器控制的水泵OLED显示屏系统逻辑void plant_monitor_system() { uint8_t temp, humi; uint16_t soil_moisture; while(1) { // 读取环境数据 DHT11_Read_Data(temp, humi); soil_moisture read_soil_moisture(); // 显示数据 show_on_oled(temp, humi, soil_moisture); // 控制逻辑 if(soil_moisture THRESHOLD) { pump_on(); Delay_ms(5000); // 浇水5秒 pump_off(); } Delay_ms(60000); // 每分钟检查一次 } }扩展功能通过WiFi上传数据到云平台设置手机APP远程监控添加光照传感器优化植物生长环境在完成这个项目后我发现最关键的还是对DHT11时序的精确控制。实际测试中不同环境温度下延时参数可能需要微调才能获得最稳定的数据。建议在正式产品中使用更高精度的传感器如SHT30或BME280但对于学习和原型开发DHT11仍然是一个经济实惠的选择。