智能家居DIY:用STM32F103和DHT11搭建本地温湿度监控站(附串口/OLED多方案)

张开发
2026/4/20 18:53:47 15 分钟阅读

分享文章

智能家居DIY:用STM32F103和DHT11搭建本地温湿度监控站(附串口/OLED多方案)
智能家居DIY用STM32F103和DHT11搭建本地温湿度监控站附串口/OLED多方案在智能家居的浪潮中环境监测是最基础却最实用的功能之一。想象一下当你需要监控书房古籍的保存环境、花房植物的生长条件或是地下室储物间的防潮情况时一个不依赖网络的本地温湿度监测站就显得尤为重要。本文将带你用STM32F103和DHT11传感器打造一个成本低廉但功能完善的解决方案。与常见的教程不同我们不仅会实现基础功能还会探讨多种数据显示方案串口、OLED等并设计可扩展的代码架构为后续添加光照、空气质量等传感器预留接口。这个项目特别适合电子爱好者、创客以及对物联网DIY感兴趣的初学者。1. 硬件选型与电路设计1.1 核心元件介绍STM32F103C8T6俗称蓝莓板是本次项目的主控芯片选择原因有三价格亲民约10-15元丰富的GPIO和外设资源强大的社区支持和完善的库函数DHT11温湿度传感器则是环境监测的经济之选测量范围温度0-50℃±2℃精度湿度20-90%RH±5%RH精度单总线通信仅需一个GPIO引脚典型响应时间2秒适合低频次监测场景提示若需要更高精度可考虑DHT22或SHT3x系列传感器但成本会相应提高。1.2 电路连接方案基础接线非常简单只需3根导线引脚连接目标备注VCC3.3V电源建议加装0.1μF去耦电容GND地线确保共地DATAPA11需配置4.7K上拉电阻对于需要显示数据的场景我们提供两种扩展方案方案A0.96寸OLED显示// I2C初始化代码示例 void OLED_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; I2C_InitTypeDef I2C_InitStructure; // 初始化I2C时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // 配置I2C引脚 GPIO_InitStructure.GPIO_Pin GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOB, GPIO_InitStructure); // I2C参数配置 I2C_InitStructure.I2C_Mode I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle I2C_DutyCycle_2; I2C_InitStructure.I2C_OwnAddress1 0x00; I2C_InitStructure.I2C_Ack I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress I2C_AcknowledgedAddress_7bit; I2C_InitStructure.I2C_ClockSpeed 400000; I2C_Init(I2C1, I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); }方案B串口输出到电脑# Python端接收代码示例 import serial from time import sleep ser serial.Serial(COM3, 115200, timeout1) while True: data ser.readline().decode(ascii).strip() if data: temp, humi data.split(,) print(f温度: {temp}℃ 湿度: {humi}%) sleep(2)2. 软件架构设计2.1 驱动程序开发DHT11的通信协议需要精确的时序控制。我们采用模块化设计将传感器驱动独立封装// dht11.h 头文件定义 typedef struct { uint8_t temp_int; // 温度整数部分 uint8_t temp_frac; // 温度小数部分 uint8_t humi_int; // 湿度整数部分 uint8_t humi_frac; // 湿度小数部分 uint8_t checksum; // 校验和 } DHT11_Data; uint8_t DHT11_Init(void); uint8_t DHT11_Read(DHT11_Data *data);关键时序实现要点主机拉低至少18ms后拉高20-40μs传感器响应信号为80μs低电平80μs高电平每位数据以50μs低电平开始高电平持续时间决定数据位26-28μs为070μs为12.2 多显示方案适配采用策略模式实现显示输出的灵活切换// display.h 抽象接口 typedef struct { void (*init)(void); void (*show)(DHT11_Data data); } DisplayDriver; // 注册当前使用的显示驱动 void Display_RegisterDriver(DisplayDriver *driver); // 具体实现示例OLED驱动 const DisplayDriver OLED_Display { .init OLED_Init, .show OLED_ShowData }; // 串口显示实现 void UART_ShowData(DHT11_Data data) { printf(%d.%d,%d.%d\r\n, data.temp_int, data.temp_frac, data.humi_int, data.humi_frac); }这种设计允许运行时动态切换显示方式也便于后续扩展其他显示设备。3. 系统优化与扩展3.1 低功耗设计对于电池供电场景可采取以下优化措施间歇工作模式每5分钟唤醒一次采集数据其余时间进入STOP模式硬件优化选用低功耗LDO如HT7333关闭未使用的外设时钟// 进入低功耗模式示例 void Enter_LowPowerMode(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); SystemInit(); // 唤醒后需重新初始化时钟 }3.2 数据记录与分析添加SD卡模块可实现长期数据记录// FATFS文件系统记录示例 FRESULT Log_Data(DHT11_Data data) { FIL file; char buffer[64]; FRESULT res; res f_open(file, datalog.txt, FA_OPEN_APPEND | FA_WRITE); if (res ! FR_OK) return res; sprintf(buffer, %lu,%d.%d,%d.%d\r\n, get_timestamp(), data.temp_int, data.temp_frac, data.humi_int, data.humi_frac); UINT bw; res f_write(file, buffer, strlen(buffer), bw); f_close(file); return res; }3.3 多传感器集成框架预留的扩展接口可以方便地添加新传感器// sensor_interface.h typedef struct { uint8_t (*init)(void); uint8_t (*read)(void *data); uint32_t interval; // 采样间隔(ms) } Sensor; // 传感器管理器 void SensorMgr_Add(Sensor *sensor); void SensorMgr_Run(void); // 使用示例 Sensor dht11_sensor { .init DHT11_Init, .read DHT11_Read, .interval 2000 };4. 实际应用案例4.1 书房环境监测站配置建议使用OLED显示实时数据每30分钟记录一次数据到SD卡当湿度超过70%时触发蜂鸣器报警// 报警条件检测 void Check_Alarm(DHT11_Data data) { static uint8_t alarm_on 0; if (data.humi_int 70 || data.temp_int 35) { if (!alarm_on) { Buzzer_On(); alarm_on 1; } } else if (alarm_on) { Buzzer_Off(); alarm_on 0; } }4.2 花房监控系统特殊需求处理增加土壤湿度传感器如电容式传感器集成光照强度检测BH1750通过继电器控制补光灯和喷雾装置硬件连接示意图[STM32F103] -I2C- [OLED] | | v v [DHT11] [BH1750] | v [Soil Moisture] | v [Relay Board]4.3 低成本方案实现对于预算特别有限的场景省略显示模块仅通过串口输出用内置Flash替代SD卡存储约可存储7天数据采用18650电池供电// 内部Flash存储实现 #define DATA_ADDR 0x0801F000 void Save_To_Flash(DHT11_Data data) { FLASH_Unlock(); FLASH_ErasePage(DATA_ADDR); uint32_t temp (data.temp_int 24) | (data.temp_frac 16) | (data.humi_int 8) | data.humi_frac; FLASH_ProgramWord(DATA_ADDR, temp); FLASH_Lock(); }在完成基础功能后我发现在实际部署中最常遇到的问题是电源干扰导致的传感器读数异常。通过增加10μF钽电容和0.1μF陶瓷电容并联到传感器电源端同时缩短连接线长度能显著提高系统稳定性。

更多文章