STM32+ESP8266+DHT11 WiFi无线温湿度监控系统实战教程

发布时间:2026/9/8 16:26:54
STM32+ESP8266+DHT11 WiFi无线温湿度监控系统实战教程 1. 项目背景与需求分析1.1 为什么做这个WiFi无线温湿度监控项目前阵子帮朋友搞了一个小型仓库的温湿度监测需求仓库面积不大但有几个死角平时根本没人去等到发现潮湿发霉的时候已经晚了。传统做法是放个温湿度计每天人工去抄一次数据费时费力不说数据还不连续半夜的变化根本记录不到。后来我给他做了一个基于STM32ESP8266DHT11OLED的WiFi无线温湿度监控设备成本低、功耗可控、代码量也不大最关键的是把传感数据接到了WiFi网络上手机随时能看历史数据也能存。做完之后朋友又让我帮他朋友做了一台我觉得这套组合确实值得写一篇完整的教程分享出来。这套方案的核心架构很简单DHT11负责采集温湿度STM32做主控读取传感器数据并驱动OLED显示ESP8266通过串口与STM32通信把数据通过WiFi上传到云端或本地服务器。整个链路清晰非常适合单片机入门到进阶这个阶段的开发者练手也能直接改造成实际可用的产品原型。1.2 这套组合的适用人群与场景先说说这套方案适合谁来搞。如果你已经学过STM32的基础外设GPIO、定时器、串口、I2C但对WiFi通信、传感器时序、嵌入式联网这套还比较懵那这个项目就是很好的跳板。它的难度不在某个单点而在于把几个模块串起来这恰恰是实际工程中最常遇到的情况。适用场景我认为有三类环境监测类的原型验证比如机房、仓储、种植大棚的温湿度监控智能家居的小型节点作为温湿度采集终端接入更大的物联网系统教学实验和毕业设计这个组合在课程设计和毕设里出现频率非常高需要实话实说DHT11本身精度一般温度±2°C、湿度±5%RH做精度要求高的科研项目它不够格。但做环境趋势监测、阈值告警、物联网原型验证它的性价比是碾压级的。想要更高精度可以换DHT22或SHT30代码改动成本也不大后面我会提到怎么改。2. 硬件选型与模块拆解2.1 STM32主控选型建议主控我选的是STM32F103C8T6也就是大家常说的“蓝丸”核心板。说实话这个芯片已经被各路教程写烂了但正是因为它资料多、例程全、踩坑记录丰富才适合作为这个项目的起点。选型逻辑很简单价格便宜几块钱到十几块钱一片炸了不心疼外设资源够用USART、I2C、GPIO、定时器全都有3.3V供电和ESP8266、OLED的电压域匹配不需要额外电平转换CubeMXHAL库的开发方式已经非常成熟新手照着配置就能跑如果你手上是其他型号的STM32也没关系代码的移植成本主要集中在引脚定义和时钟配置上核心逻辑完全通用。后面我会把和硬件强相关的部分单独标注出来。2.2 DHT11传感器的通信原理详解DHT11这块传感器很有意思它用的是单总线协议数据线和时钟线复用一根线。这也就意味着时序要求比较严格尤其是起始信号和应答信号的拉低时间搞不好就读出全0或者全1的数据。通信时序大致是这样的主机拉低数据线至少18ms然后释放这是起始信号DHT11响应拉低80us再拉高80us表示准备发送数据之后连续发送40bit数据8bit湿度整数、8bit湿度小数、8bit温度整数、8bit温度小数、8bit校验和每bit的表示方式是用高电平持续时间来区分的。高电平持续26~28us表示0持续70us左右表示1。这部分的读取代码用HAL库的延时函数做不太靠谱因为HAL_Delay最小精度是1ms根本卡不了微秒级的时间。我试过用空循环做微秒延时但这依赖主频和编译优化级别换一个优化选项时序就崩了后面会给出我认为最稳的做法。2.3 ESP8266、OLED的选型与分工ESP8266我用的ESP-01S这个模块体积小、价格低GPIO只有两个但够用反正它在项目里只负责串口透传数据到WiFi不需要额外的引脚控制。如果你想要后续扩展更多功能可以换ESP-12F或NodeMCU开发板引脚多很多烧录也方便。需要注意ESP-01S的工作电流峰值能到300mA左右配合WiFi发射时的瞬态电流更高。如果直接用STM32核心板上的3.3V稳压芯片给ESP8266供电很容易出现电压跌落导致模块反复重启。我一开始就吃过这个亏后来老老实实给ESP8266单独供电才稳定下来。OLED屏用的是0.96寸I2C接口的SSD1306驱动方案4个引脚VCC、GND、SCL、SDA。I2C的方式只用两根线就能驱动焊接和接线都省事。这个屏功耗低、刷新也够用显示温湿度数据绰绰有余。2.4 整体系统框图与数据流向整个系统的工作流程可以这样理解DHT11采集温湿度 → STM32读取并解析数据 → 数据同时送入两个方向——OLED本地显示、ESP8266串口发送。ESP8266通过WiFi连接路由器再把数据以HTTP请求或TCP方式上报到云端服务器或局域网内的接收端。这里面有一个关键设计传感数据采样的频率不需要太高。DHT11本身的采样周期推荐在1秒以上太快反而读不到有效数据。WiFi上报也可以设置一个合理间隔比如5秒或10秒上报一次既满足监控需求又不会因为上报过于频繁导致ESP8266数据拥塞。3. 开发环境搭建与工具准备3.1 STM32开发环境配置注意点STM32的开发环境现在主流的搭配是STM32CubeMX生成初始化代码再用Keil MDK或者其他IDE编译下载。我推荐用CubeMX的原因很简单这个项目涉及GPIO、USART、I2C、定时器多个外设的初始化手写寄存器级别的配置代码对新手不友好CubeMX图形化点选生成省时省力。具体配置项后面实操部分会详细展开。Keil这边记得选对Device型号——STM32F103C8然后在Target标签页里把晶振频率改成8MHz这个不设置后面串口波特率容易算错。还有一个很常见的坑Keil5兼容C51和STM32的安装问题。如果你之前装过C51版的Keil再装MDK版可能会遇到编译器路径冲突最典型的症状是编译时找不到ARMCC编译器。解决办法是把两个版本安装到不同目录并且先装MDK再装C51或者直接用纯净的MDK环境来开发STM32。3.2 ESP8266固件初始化与验证ESP-01S出厂默认固件通常是支持AT指令的但不同批次可能版本不一样稳妥起见建议先擦除再烧录一个统一版本的固件。烧录固件需要USB转TTL模块接线是ESP8266的RX接TTL的TX、TX接RXVCC接3.3VGND共地EN引脚要拉高。烧录时有个坑ESP-01S必须让GPIO0接地才能进入UART下载模式。如果GPIO0悬空或拉高模块会直接进入运行模式烧录工具会报连接失败。固件烧好后用串口助手发送“AT”返回“OK”基本就说明模块没问题了。再依次测试ATCWMODE设置模式、ATCWJAP连接WiFi确认联网正常这一步跑通了再往下进行。3.3 手头常用的调试工具清单嵌入式开发调试工具非常关键我推荐以下几个USB转TTL模块我用的是CH340芯片方案的驱动稳定逻辑分析仪对于调试DHT11这种时序敏感型传感器非常有用能直接看波形几十块钱的24MHz采样率的就够用串口助手SSCOM或XCOM都行用于ESP8266调试和查看STM32的调试输出万用表检查供电电压和接线导通排查硬件问题必备逻辑分析仪在这个项目里我建议有条件就备一个。DHT11读不到数据的时候靠猜是猜不出问题在哪里的用逻辑分析仪抓一下波形马上就能判断是传感器没响应还是时序不对排查效率提升好几个量级。4. 电路连接与硬件组装实操4.1 接线表与引脚定义下面是我在实际焊接中最终确定的接线方案模块引脚接STM32引脚备注DHT11VCC3.3VDHT11供电范围3.3V~5VDHT11GNDGND共地DHT11DATAPA6需接4.7kΩ上拉电阻OLEDVCC3.3VOLED供电OLEDGNDGND共地OLEDSCLPB6I2C1时钟线OLEDSDAPB7I2C1数据线ESP8266VCC外部3.3V电源不能直接接核心板3.3VESP8266GNDGND与STM32共地ESP8266RXPA2USART2_TXESP8266TXPA3USART2_RXESP8266EN3.3V使能引脚拉高DHT11的数据线接PA6这个引脚是STM32的普通GPIO配置为开漏输出并外接上拉电阻。开漏输出的好处是引脚既能拉低也能释放由外部上拉电阻拉高刚好符合单总线“线与”的逻辑。关于DHT11的上拉电阻我直接用的4.7kΩ这是常见的I2C和单总线标准值。实测稳定如果你用10kΩ也可以响应时间会稍慢但在这个低速场景没有问题。4.2 供电方案的关键设计供电是这套系统最容易被忽略的坑。ESP8266在WiFi发射瞬间的电流尖峰可能超过300mA如果这时供电电压被拉低到3.3V以下模块就重启了表现就是你看到串口里不断输出乱码或者AT指令没响应。我实际用的供电方案是整体用USB 5V输入通过一个AMS1117-3.3稳压模块给ESP8266单独供电STM32核心板上的3.3V只给STM32和OLED、DHT11供电。两个3.3V电源在GND端共地这样通信引脚的电平参考是一致的。如果你手头有5V转3.3V的DC-DC模块那就更稳了效率比LDO高。但AMS1117对这个场景够用成本也低。4.3 面包板原型搭建到焊接固化的过程我建议先面包板搭原型验证逻辑再焊接到洞洞板或做PCB。面包板的好处是改线方便出了问题可以快速排查缺点是接触不良是常态尤其是DHT11这种单总线一旦接触不良读出来的数据就很诡异。原型跑通之后我把模块转移到了洞洞板上。这里有几个经验排针和排母结合使用模块可以插拔方便拆下来单独调试电源线和地线用粗一点的线至少0.5mm²降低线阻DHT11和ESP8266的天线区域不要靠太近以免WiFi射频信号干扰传感器数据PCB定制是更进一步的做法嘉立创免费打样就够用了。画原理图和PCB时注意DHT11旁边的退耦电容要靠近传感器放置ESP8266下方的地平面要完整天线区域下方净空。网上搜“DHT11原理图嘉立创画图”能出来一堆参考照着画就行。4.4 上电前必须做的检查清单焊接完通电之前按照下面清单逐项检查一遍电源正负极有没有接反最简单也最容易犯的错误各模块的VCC电压是否在规格范围内共地是否接好3.3V和GND环路是否完整GPIO引脚有没有互相短接的可能DHT11的DATA线上有没有上拉电阻ESP8266的EN是否有上拉电平我上电前都会用万用表的二极管档测一下电源和地之间的阻值如果不正常先别通电。曾经有人直接把ESP8266和STM32核心板的3.3V接在一起导致整片发烫排查半天才发现是核心板上的稳压芯片过载。5. STM32端核心代码实现5.1 CubeMX工程配置逐项说明CubeMX配置这个项目有几个重点区域需要仔细设置RCC设置HSE选择Crystal/Ceramic Resonator这是外部8MHz晶振。SYS设置Debug选择Serial Wire否则下载一次程序后第二次就无法连接了这是新手的常见问题。GPIO配置PA6配置为Output Push Pull或Open Drain都行。我习惯配置为开漏输出模式初始电平High配合外部上拉电阻。I2C1配置PB6和PB7作为I2C1的SCL和SDA速率标准模式100KHz或者快速模式400KHz都可以OLED屏驱动SSD1306在400KHz下工作正常。USART2配置异步模式波特率1152008位数据位1停止位无校验。这个串口用于与ESP8266通信。USART1配置也开一个异步模式波特率115200用于打印调试信息到PC。时钟树HCLK配置到72MHz这个项目CPU频率足够用。I2C的时钟源选择系统时钟72MHz分频。5.2 DHT11读取驱动代码解析——从时序到实现DHT11驱动是整个代码里最讲究时序的部分。用HAL库的延时函数HAL_Delay做不了微秒级延时我的方案是用SysTick或者DWT计数器来做。这里给出的是我在STM32F103上稳定运行的DHT11读取代码。/* dht11.h */ #ifndef __DHT11_H #define __DHT11_H #include main.h #define DHT11_PORT GPIOA #define DHT11_PIN GPIO_PIN_6 #define DHT11_OUT_L() HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_RESET) #define DHT11_OUT_H() HAL_GPIO_WritePin(DHT11_PORT, DHT11_PIN, GPIO_PIN_SET) #define DHT11_IN_READ() HAL_GPIO_ReadPin(DHT11_PORT, DHT11_PIN) #define DHT11_DATA_PORT_ENABLE_IN() do{ \ GPIO_InitTypeDef GPIO_InitStruct {0}; \ GPIO_InitStruct.Pin DHT11_PIN; \ GPIO_InitStruct.Mode GPIO_MODE_INPUT; \ GPIO_InitStruct.Pull GPIO_NOPULL; \ HAL_GPIO_Init(DHT11_PORT, GPIO_InitStruct); \ }while(0) #define DHT11_DATA_PORT_ENABLE_OUT() do{ \ GPIO_InitTypeDef GPIO_InitStruct {0}; \ GPIO_InitStruct.Pin DHT11_PIN; \ GPIO_InitStruct.Mode GPIO_MODE_OUTPUT_OD; \ GPIO_InitStruct.Pull GPIO_NOPULL; \ GPIO_InitStruct.Speed GPIO_SPEED_FREQ_LOW; \ HAL_GPIO_Init(DHT11_PORT, GPIO_InitStruct); \ }while(0) uint8_t DHT11_ReadData(float *temperature, float *humidity); #endif/* dht11.c */ #include dht11.h static void DHT11_DelayUs(uint32_t us) { uint32_t count us * 72; // 72MHz时钟下1us约72个周期 while(count--) { __NOP(); } } static uint8_t DHT11_ReadByte(void) { uint8_t value 0; for(int i 0; i 8; i) { while(DHT11_IN_READ() GPIO_PIN_RESET); // 等待低电平结束 DHT11_DelayUs(40); // 高电平持续40us后判断 if(DHT11_IN_READ() GPIO_PIN_SET) { value | (0x80 i); } while(DHT11_IN_READ() GPIO_PIN_SET); // 等待高电平结束 } return value; } uint8_t DHT11_ReadData(float *temperature, float *humidity) { uint8_t data[5] {0}; // 主机起始信号 DHT11_DATA_PORT_ENABLE_OUT(); DHT11_OUT_L(); HAL_Delay(20); // 拉低至少18ms DHT11_OUT_H(); DHT11_DelayUs(30); // 释放并延时30us DHT11_DATA_PORT_ENABLE_IN(); // 切换到输入模式 // 等待应答信号 if(DHT11_IN_READ() GPIO_PIN_RESET) { while(DHT11_IN_READ() GPIO_PIN_RESET); // 等待80us低电平结束 while(DHT11_IN_READ() GPIO_PIN_SET); // 等待80us高电平结束 } else { return 1; // 无应答 } // 读取40bit数据 for(int i 0; i 5; i) { data[i] DHT11_ReadByte(); } // 校验 if((data[0] data[1] data[2] data[3]) ! data[4]) { return 2; // 校验错误 } *humidity (float)(data[0] data[1] * 0.1); *temperature (float)(data[2] data[3] * 0.1); return 0; }关于延时函数我上面用的方法是基于CPU主频做空循环这种方法有一个前提编译器不能把空循环优化掉。STM32F103在72MHz下的空循环延时实测在这个项目里是够用的。更稳的做法是用DWT计数器系统滴答的精度更高但代码复杂度上去了新手容易搞懵。在DHT11这个场景下40us级别的判断误差容忍度还算可以所以空循环方案完全够用。这里有一个很重要的设计DHT11的数据引脚需要能够在输入和输出两种模式下切换。主机发完起始信号后必须切换到输入模式否则总线一直被主机拉高传感器的应答信号就发不出来。5.3 OLED显示驱动——HAL库I2C读写SSD1306OLED这块我用的是SSD1306驱动芯片的0.96寸屏。驱动OLED的核心是把显存RAM准备好然后通过I2C发送到SSD1306。SSD1306内部有128×64位的显存每个 bit 对应一个像素点。所以实际操作是维护一个128×8字节的buffer修改buffer内容然后把整个buffer发给屏幕。关于热词里有人搜“OLED屏的像素点由几层组成”这里补充一下这不是指物理结构而是指显示驱动方式。SSD1306的显存按页Page组织共8页每页8行像素写数据时先设置页地址和列地址然后连续写数据。理解这个组织结构对驱动代码很关键。汉字显示这里我多说一句OLED显示汉字需要自己取模生成字库。取模软件可以选PCtoLCD2002取模方式选择逐列式、阴码、逆向。我一开始取模方向设错了显示的汉字镜像了后来调了“逆向”选项才好。中文显示本质就是把16x16的点阵数据填到显存对应位置理解了就很顺。一个通用I2C函数就搞定OLED初始化配置完整I2C起始地址后写入控制字节和命令。OLED驱动代码我用的标准的SSD1306 HAL库驱动网上资源很多核心是把初始化序列发送给SSD1306配置显示时钟分频、复用率、偏移量、起始行、电荷泵等寄存器。这里我只列我的初始化序列供参考static void OLED_WriteCmd(uint8_t cmd) { uint8_t buf[2]; buf[0] 0x00; // 控制字节Co0, D/C#0表示后面跟的是命令 buf[1] cmd; HAL_I2C_Master_Transmit(hi2c1, 0x78, buf, 2, 100); } static void OLED_WriteData(uint8_t data) { uint8_t buf[2]; buf[0] 0x40; // 控制字节Co0, D/C#1表示后面跟的是数据 buf[1] data; HAL_I2C_Master_Transmit(hi2c1, 0x78, buf, 2, 100); } void OLED_Init(void) { HAL_Delay(100); OLED_WriteCmd(0xAE); // 关闭显示 OLED_WriteCmd(0x20); // 设置内存寻址模式 OLED_WriteCmd(0x02); // 页寻址模式 OLED_WriteCmd(0xB0); // 设置页起始地址 OLED_WriteCmd(0xC8); // 设置COM扫描方向 OLED_WriteCmd(0x00); // 设置列地址低四位 OLED_WriteCmd(0x10); // 设置列地址高四位 OLED_WriteCmd(0x40); // 设置显示起始行 OLED_WriteCmd(0x81); // 设置对比度 OLED_WriteCmd(0x7F); OLED_WriteCmd(0xA1); // 设置段重映射 OLED_WriteCmd(0xA6); // 正常显示非反显 OLED_WriteCmd(0xA8); // 设置多路复用比率 OLED_WriteCmd(0x3F); OLED_WriteCmd(0xA4); // 显示使用RAM内容 OLED_WriteCmd(0xD3); // 设置显示偏移 OLED_WriteCmd(0x00); OLED_WriteCmd(0xD5); // 设置时钟分频因子 OLED_WriteCmd(0x80); OLED_WriteCmd(0xD9); // 设置预充电周期 OLED_WriteCmd(0xF1); OLED_WriteCmd(0xDA); // 设置COM引脚硬件配置 OLED_WriteCmd(0x12); OLED_WriteCmd(0xDB); // 设置VCOMH电压 OLED_WriteCmd(0x30); OLED_WriteCmd(0x8D); // 设置电荷泵 OLED_WriteCmd(0x14); // 使能电荷泵 OLED_WriteCmd(0xAF); // 开启显示 }5.4 主循环逻辑与数据调度主循环的逻辑比较简单但有一个点要特别注意DHT11的读取周期不能太短。我实测连续读取间隔低于1秒时DHT11偶尔会无应答这是传感器本身的限制。所以我在主循环里做了一个简单的调度1秒采集一次5秒在OLED上刷新一次10秒通过ESP8266上报一次。uint64_t lastReadTime 0; uint64_t lastSendTime 0; while(1) { if(HAL_GetTick() - lastReadTime 1000) { lastReadTime HAL_GetTick(); if(DHT11_ReadData(temp, humi) 0) { // 显示到OLED OLED_ShowTemperature(temp, humi); } else { OLED_ShowError(); } } if(HAL_GetTick() - lastSendTime 10000) { lastSendTime HAL_GetTick(); ESP8266_SendData(temp, humi); } }6. ESP8266联网与数据上报6.1 AT指令还是MQTT固件我的选择ESP8266的使用方案主要有两条路线用出厂AT固件或者刷NodeMCU固件做二次开发。我做这个项目选择的是AT固件方案原因很简单STM32主控已经很成熟ESP8266只需要充当一个串口转WiFi的透明传输通道用AT指令就能完成任务不需要在ESP8266端写任何额外代码。AT指令方案的经典流程AT // 测试模块是否正常 ATCWMODE1 // 设为Station模式 ATCWJAPSSID,密码 // 连接WiFi ATCIPSTARTTCP,xxx.xxx.xxx.xxx,8080 // 建立TCP连接 ATCIPSEND数据长度 // 发送数据热词里有人搜“esp8266连接onenet失败”我估计大概率是上报格式和OneNET要求的报文不匹配或者接入鉴权参数没配置对。调试思路很简单先用串口助手手动发AT指令测试连接再用ESP8266的透传模式发送报文一步步排查别一上来就全链路联调。6.2 STM32与ESP8266的串口通信实现STM32的USART2用于和ESP8266通信PA2是TXPA3是RX。我使用HAL库的串口中断接收配合一个接收缓冲区这样可以处理ESP8266返回的异步消息。这里常遇到的问题是很多人直接用阻塞式HAL_UART_Transmit发送AT指令然后用HAL_UART_Receive阻塞等待响应。但因为AT指令响应时间不固定有些指令需要几秒钟才能返回阻塞等待会把主循环卡死DHT11的采样周期就会乱掉。我的做法是定义一组状态机。typedef enum { ESP_STATE_IDLE, ESP_STATE_WAIT_OK, ESP_STATE_WAIT_DATA, } ESP_State; static uint8_t esp_rx_buffer[256]; static uint16_t esp_rx_len 0; static volatile uint8_t esp_rx_ready 0; void ESP8266_Init(void) { ESP8266_SendCommand(AT\r\n, OK); ESP8266_SendCommand(ATCWMODE1\r\n, OK); ESP8266_SendCommand(ATCWJAP\YourSSID\,\YourPassword\\r\n, OK); } uint8_t ESP8266_SendCommand(char *cmd, char *expected) { // 清空接收缓冲区 esp_rx_len 0; esp_rx_ready 0; // 发送命令 HAL_UART_Transmit(huart2, (uint8_t *)cmd, strlen(cmd), 1000); // 等待期望的响应 uint32_t timeout HAL_GetTick() 3000; while(HAL_GetTick() timeout) { if(esp_rx_ready) { if(strstr((char *)esp_rx_buffer, expected) ! NULL) { return 1; // 收到期望响应 } // 重新等待因为AT响应可能分多条消息到达 esp_rx_len 0; esp_rx_ready 0; } } return 0; }还有一个优化过的技巧把“ATCIPSTART”的连接建立和“ATCIPSEND”的发送逻辑做成一个独立的函数这个函数先检测ESP8266是否已经连接没有连接先建立连接连接存在就直接发送避免每次上报都重复建连。TCP连接的建立是有开销的频繁建立释放不仅慢还可能导致服务端资源泄漏。6.3 数据上报的封装格式设计上报数据格式我设计的是简单的JSON因为接收端解析方便也方便对接后续的云平台void ESP8266_ReportData(float temp, float humi) { char payload[128]; snprintf(payload, sizeof(payload), {\device_id\:\dev_001\,\temp\:%.1f,\humi\:%.1f}\r\n, temp, humi); char cmd[160]; snprintf(cmd, sizeof(cmd), ATCIPSEND%d\r\n, strlen(payload)); ESP8266_SendCommand(cmd, OK); HAL_UART_Transmit(huart2, (uint8_t *)payload, strlen(payload), 1000); ESP8266_SendCommand(ATCIPCLOSE\r\n, OK); }接收端如果只是验证用可以自己在电脑上开一个TCP Server或者用Node-RED、MQTT Broker之类更完整的方案。如果不想自己搭服务器也可以直接把数据推到巴法云、点灯科技这类的物联网平台他们有现成的App和接口改造成本极低。7. 系统联调与问题排查实录7.1 上电后OLED不亮的排查这是我自己做的时候第一次上电遇到的问题。检查思路按顺序走一遍万用表量OLED的VCC和GND之间的电压是否为3.3V检查SCL和SDA是否接反经常把PB6/PB7接反屏幕就完全不亮检查I2C地址是否正确SSD1306的7位地址通常是0x3C左移一位后就是0x78。我之前用过一块地址是0x3D的屏刚开始一直没显示后来才发现地址不对如果这些都查过还是不行用逻辑分析仪抓I2C波形看有没有ACK信号。如果没有ACK大概率是屏的I2C地址不对或者接线问题。7.2 DHT11读取失败的几种典型情况DHT11读取失败的表现通常是返回1无应答或者返回2校验错误。无应答的排查重点上拉电阻是否漏焊DHT11数据线是开漏的没上拉肯定不行起始信号拉低时间是否足够我程序里是20ms够用切换到输入模式的时机是否对释放总线后要等传感器应答校验错误的排查重点时序延时是否准确。空循环延时和主频强相关确认系统主频是72MHz而不是8MHz传感器距离MCU的线过长我试过超过20cm的杜邦线就容易读到错误数据改用短线和双绞方式有改善DHT11本身可能损坏换一块试一下还有一个很多人忽略的点CubeMX生成的GPIO初始化默认是推挽输出但DHT11的时序要求总线能被外部拉低如果保持推挽输出会导致电平冲突。所以CubeMX里要把PB6配成开漏输出我上面代码里在切模式时也做了处理。7.3 ESP8266连接不上WiFi的排查思路如果你遇到ESP8266连不上WiFi不要急着怀疑模块坏了按顺序排查确认供电。用万用表测模块VCC引脚在连接WiFi瞬间的电压如果低于3.3V就是供电不足换独立电源确认SSID和密码没错。有人密码里带特殊字符AT指令里需要转义处理确认路由器是2.4G频段。ESP8266不支持5G WiFi这个坑很常见确认路由器DHCP正常工作或者手动设置静态IP连接成功后还需要确认一件事路由器是否做了客户端隔离。有些路由器开了“AP隔离”设备之间无法通信这种情况下ESP8266能连接路由器但上不了网、也访问不了局域网服务器。7.4 常见问题速查表问题现象可能原因解决方法OLED不亮I2C地址错误或接错线检查地址0x3C/0x3D对照接线表检查OLED花屏电源纹波过大或I2C速率过高加退耦电容速率降到100KHzDHT11无应答上拉缺失或供电异常加4.7k上拉确认VCC电压DHT11校验错误时序不准或线路过长检查主频时钟配置缩短传感器线ESP8266不断重启供电不足独立供电确保峰值电流满足ESP8266连不上WiFi5G频段或AP隔离切到2.4G频段关闭AP隔离ESP8266发送乱码波特率不匹配确认STM32与ESP8266通信波特率一致8. 从原型到可用产品的扩展方向8.1 功能增强与传感器升级这套系统跑通之后可以往几个方向扩展。传感器升级是最容易的一步。DHT11换成DHT22精度从±2°C提升到±0.5°C湿度的精度提升也明显。代码改动只需要在数值处理上稍微调整时序部分和工作流程基本不用动。换成SHT30则走I2C接口和OLED挂了同一个总线连GPIO都不用多占用。也可以增加光照传感器BH1750或者土壤湿度传感器扩展成一个完整的环境监测节点。STM32的外设资源足够加传感器只是增加I2C设备地址和读取逻辑的事。8.2 数据可视化与云端接入当前的方案只是把数据上报到TCP Server数据展示还需要自己处理。如果想让手机随时看数据有几个成熟的方案接巴法云或点灯科技直接用他们提供的App做一个可视化界面操作简便适合快速验证自建EMQX等MQTT Broker用ESP8266的MQTT库直接发布消息Node-RED订阅数据并展示到Dashboard使用OneNET或阿里云物联网平台功能强大支持数据存储和告警规则适合做正式产品做可视化的时候有几个经验数据存储要保留时间和设备ID这样方便后续查询和分析。告警规则不要只设置阈值建议增加“持续时间”判断比如连续5分钟超过温度上限才告警避免瞬时波动引起误报。8.3 低功耗优化方向如果你想做电池供电版本这套系统有几个明显的功耗大户可以针对性优化DHT11可以做到1次/分钟采样中间间隔完全不需要供电可以用MOS管直接切断电源OLED在不需要刷新时进入睡眠模式功耗能降很多ESP8266用Modem-sleep或者DTIM模式或者改成定时唤醒上报功耗可以再降一到两个数量级实测过如果不做任何功耗优化这个系统的工作电流大约在80mA左右做电池供电续航很差。做了定时唤醒和深度睡眠之后平均电流可以降到几十mA甚至更低看具体的上报频率。8.4 我在这类项目里反复踩过的坑做这个项目前后其实花了不少时间回头总结几个比较典型的坑。第一个坑是供电问题。一开始直接用STM32核心板的3.3V给ESP8266供电结果模块反复重启调试信息乱飞。后来测量才发现WiFi发射的瞬间电压跌到了2.8V。从那以后我凡是带ESP8266的项目都单独给它设计供电这已经成了我的习惯。第二个坑是DHT11的时序问题。我用过多种延时方案包括DWT精确延时、定时器延时、空循环延时。空循环虽然简单但一旦开了编译器的优化选项延时时间就可能不对导致校验错误。后来我干脆在DHT11读取的代码文件里对延时函数做了常规优化限制再没出过时序问题。第三个坑是调试手段。刚开始我疯狂加串口打印每个函数都打日志结果日志太乱根本找不到重点。后来我养成了一个习惯先确认硬件供电和波形再用逻辑分析仪看时序最后才看软件逻辑。硬件不过关的时候软件怎么调都没用。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询