这次我们来看一个基于STM32的温湿度检测系统。这个项目不是什么新概念,但关键在于如何从零开始,把DHT11传感器、STM32微控制器和Proteus仿真环境串起来,做出一个能实际跑通、能验证、能扩展的完整系统。如果你正在学习嵌入式,或者想做一个课程设计、毕业设计,这篇文章会带你走完全流程:从核心器件选型、电路设计、代码编写,一直到Proteus仿真验证和常见问题排查。
整个系统的核心很简单:用STM32读取DHT11传感器的温湿度数据,然后通过串口发送到电脑显示,或者在液晶屏上实时查看。硬件门槛极低,一块STM32F103C8T6核心板、一个DHT11模块、几条杜邦线就能搭建实物。如果暂时没有硬件,用Proteus进行软件仿真同样可以验证整个逻辑,这对学习和前期调试非常友好。
本文将重点解决几个实际问题:DHT11那套独特的单总线通信协议怎么用代码实现?STM32的工程该如何搭建?Proteus里怎么画原理图并加载程序进行仿真?仿真通过了,但烧录到实物板子却没反应,又该怎么排查?我们会按照“核心器件与协议解析 -> 硬件电路设计 -> 软件代码编写 -> Proteus仿真验证 -> 实物调试与问题排查”的顺序,一步步拆解,确保你看完就能动手做出来。
1. 核心能力速览
在动手之前,我们先快速了解这个系统的关键信息,判断它是否适合你的需求。
| 能力项 | 说明 |
|---|---|
| 核心控制器 | STM32F103C8T6(其他STM32F1系列型号也可) |
| 温湿度传感器 | DHT11(数字输出,单总线协议) |
| 开发环境 | Keil MDK-ARM / STM32CubeIDE / VSCode + PlatformIO |
| 仿真工具 | Proteus 8 Professional(用于电路与程序联合仿真) |
| 显示方式 | 串口调试助手(USART)或 LCD1602/OLED显示屏 |
| 通信协议 | 单总线协议(DHT11)、USART(串口) |
| 主要功能 | 实时采集环境温湿度,并通过串口输出或屏幕显示 |
| 适合场景 | 嵌入式入门学习、课程设计、毕业设计、环境监测原型开发 |
| 硬件成本 | 极低(主控核心板+传感器模块约30-50元) |
| 代码复杂度 | 中等,需理解GPIO输入输出、延时、串口通信 |
这个方案的优势在于器件常见、资料丰富、仿真环境成熟。无论你是想快速验证想法,还是深入学习STM32外设驱动和传感器协议,它都是一个非常经典的起点。
2. 适用场景与使用边界
这个温湿度检测系统虽然简单,但能覆盖从基础到进阶的多个学习与实践场景。
它非常适合:
- 嵌入式初学者:通过一个完整项目,学习STM32的GPIO操作、延时函数、串口通信等核心外设使用。
- 协议学习:DHT11的单总线协议是学习时序通信的经典案例,比I2C/SPI更直观,有助于理解底层硬件时序。
- 仿真验证:在Proteus中搭建虚拟电路并加载固件进行仿真,可以在没有物理硬件的情况下完成整个开发调试流程,极大降低学习门槛和成本。
- 课程/毕业设计:作为一个功能明确、有输入有输出的系统,易于扩展(如增加报警、无线传输、上位机),是常见的课题选择。
- 环境监测原型:快速搭建一个用于室内温湿度监测的原型装置。
它的能力边界与注意事项:
- 精度与范围:DHT11的测量精度相对一般(温度±2℃,湿度±5%RH),响应较慢,适用于对精度要求不高的普通场合,不适用于精密工业或科研测量。
- 实时性:单总线协议在读取数据时需独占MCU资源(几十毫秒),在高实时性多任务系统中需谨慎使用或采用中断方式优化。
- 通信距离:单总线通信距离短,通常不超过20米,且易受干扰。长距离传输建议改用其他通信方式(如RS485转接)。
- 仿真与实物的差异:Proteus仿真中的DHT11模型行为是理想的,但实物传感器会受电源质量、布线、环境干扰影响。仿真成功是第一步,实物调试是必须的环节。
- 仅供学习与原型设计:本系统实现的是核心检测功能,若用于实际产品,需考虑电源管理、长期稳定性、外壳防护、数据校准等因素。
3. 环境准备与前置条件
开始之前,请确保你的电脑上已经安装好必要的软件环境。这里我们以最常用的组合为例。
1. 软件开发环境:
- 选项A(推荐初学者):Keil MDK-ARM (uVision5) + STM32标准外设库或HAL库。Keil的生态完善,调试方便。
- 选项B(官方工具):STM32CubeIDE。这是ST官方推出的免费集成开发环境,集成了CubeMX配置工具和调试器,基于Eclipse,适合习惯HAL库的开发者。
- 选项C(轻量灵活):VSCode + PlatformIO插件。适合喜欢现代编辑器和跨平台开发的用户。
2. 电路仿真环境:
- Proteus 8 Professional:用于绘制原理图和进行单片机仿真。确保已安装并授权,且元件库中包含
STM32F103C6/C8和DHT11模型。
3. 硬件驱动与工具:
- ST-Link/V2驱动:如果你有ST-Link调试器,需要在电脑上安装其USB驱动。
- 串口调试助手:如
SSCOM、XCOM、Putty等,用于接收STM32串口发送的数据。 - STM32CubeProgrammer或ST-Link Utility:用于将编译好的程序文件(.hex或.bin)烧录到单片机中。
4. 知识准备:
- 基础的C语言编程知识。
- 对STM32的GPIO、USART等基本概念有初步了解。
- 知道如何创建一个简单的STM32工程(点灯、串口打印)。
如果你的环境还没准备好,建议先完成Keil和Proteus的安装与破解(如有需要),并尝试创建一个STM32的“Hello World”(串口打印)工程,确保开发链路是通的。
4. 硬件电路设计详解
硬件是系统的基础。我们分实物连接和仿真原理图两部分来说明。
4.1 实物连接(基于STM32F103C8T6核心板)
实物连接非常简单,通常使用杜邦线连接即可。以下是典型的连接方式:
| STM32F103C8T6引脚 | DHT11模块引脚 | 说明 |
|---|---|---|
| 3.3V | VCC | 电源正极,DHT11工作电压为3.3V-5.5V,接3.3V即可 |
| GND | GND | 电源地 |
| PA1 (或其他任意GPIO) | DATA | 单总线数据线,需接一个4.7K-10K的上拉电阻到3.3V |
关键点:
- 上拉电阻:这是必须的!单总线协议要求数据线在空闲时保持高电平。通常DHT11模块内部已经集成了这个上拉电阻,如果你的模块没有,必须在DATA线和3.3V之间外接一个4.7KΩ的电阻。
- GPIO选择:理论上任何具有输入输出功能的GPIO都可以。在代码中需要将该引脚配置为开漏输出(Open-Drain)或推挽输出(Push-Pull)模式来驱动总线,并在读取时切换为浮空输入(Floating Input)或上拉输入(Pull-up Input)模式来读取数据。开漏模式更符合总线规范,但推挽模式在短距离、单一主机情况下也常用。
4.2 Proteus仿真原理图设计
在Proteus中设计原理图,可以让你在没有硬件的情况下验证逻辑。
- 新建工程:打开Proteus,新建一个原理图设计。
- 放置元件:
- 在元件库中搜索并放置
STM32F103C6(Proteus中常使用C6模型,其Flash/RAM与C8T6相近,仿真通用)。 - 搜索并放置
DHT11。 - 放置
RES(电阻,选择4.7k)作为上拉电阻。 - 放置
POWER和GROUND。 - 放置
VIRTUAL TERMINAL(虚拟终端),用于模拟串口输出。
- 在元件库中搜索并放置
- 连接电路:
- 将
POWER(+3.3V)连接到STM32的VDD/VSSA等电源引脚、DHT11的VCC引脚,以及上拉电阻的一端。 - 将
GROUND连接到STM32的VSS、DHT11的GND。 - 连接一个GPIO口(例如PA1)到DHT11的DATA引脚,同时通过上拉电阻连接到+3.3V。
- 连接STM32的USART1_TX (PA9) 引脚到
VIRTUAL TERMINAL的RXD引脚。 - 为STM32芯片右键选择“Edit Properties”,在
Program File一栏留空,后续加载编译生成的.hex文件。
- 将
- 最终检查:确保电源、地、信号线连接正确,无虚接。原理图应清晰简洁。
5. 软件代码编写与解析
代码是实现功能的核心。我们以STM32标准库为例,分步骤解析DHT11驱动和主程序逻辑。
5.1 DHT11单总线协议时序解析
DHT11采用单总线通信,一次通信大约4ms,包含40位数据。时序是编程的关键,必须严格遵循传感器数据手册。
一次完整的数据读取流程:
- MCU发送开始信号:主机(STM32)将数据线拉低至少18ms,然后拉高20-40us,随后释放总线(设置为输入模式),等待从机(DHT11)响应。
- DHT11响应信号:DHT11检测到开始信号后,会先将总线拉低80us,再拉高80us,作为响应。
- 数据传输:随后DHT11开始发送40位数据。每一位数据都以一个50us的低电平起始位开始,随后的高电平持续时间决定数据位是0还是1:
- 数据‘0’:高电平持续26-28us。
- 数据‘1’:高电平持续70us。
- 数据格式:40位数据包含:8位湿度整数 + 8位湿度小数 + 8位温度整数 + 8位温度小数 + 8位校验和。校验和 = 湿度高8位 + 湿度低8位 + 温度高8位 + 温度低8位。DHT11通常小数部分为0。
5.2 代码实现(基于标准库)
首先,创建dht11.c和dht11.h文件。
dht11.h头文件定义:
#ifndef __DHT11_H #define __DHT11_H #include "stm32f10x.h" // 定义DHT11连接的GPIO端口和引脚,根据你的电路修改 #define DHT11_GPIO_PORT GPIOA #define DHT11_GPIO_PIN GPIO_Pin_1 #define DHT11_GPIO_CLK RCC_APB2Periph_GPIOA // 函数声明 void DHT11_GPIO_Config(void); void DHT11_GPIO_Out(void); void DHT11_GPIO_In(void); uint8_t DHT11_ReadByte(void); uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi); #endif /* __DHT11_H */dht11.c源文件实现:
#include "dht11.h" #include "delay.h" // 你需要一个微秒级延时函数,如SysTick实现 // 配置DATA引脚为推挽输出 void DHT11_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(DHT11_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN); // 初始置高 } // 设置DATA引脚为输出模式 void DHT11_GPIO_Out(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure); } // 设置DATA引脚为浮空输入模式 void DHT11_GPIO_In(void) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = DHT11_GPIO_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入 GPIO_Init(DHT11_GPIO_PORT, &GPIO_InitStructure); } // 读取一个字节(8位)数据 uint8_t DHT11_ReadByte(void) { uint8_t i, data = 0; for (i = 0; i < 8; i++) { // 等待低电平起始位结束(50us) while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 0); delay_us(40); // 延时40us,避开起始位的50us低电平后,判断高电平时间 // 判断高电平持续时间 if (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 1) { data |= (0x80 >> i); // 高电平持续超过40us,认为是‘1’ // 等待高电平结束 while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 1); } // 如果是‘0’,高电平持续时间短,此时已经变为低电平(下一位的起始位) } return data; } // 读取温湿度数据,成功返回1,失败返回0 uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi) { uint8_t buf[5] = {0}; uint8_t i; uint8_t checksum; // 1. 主机发送开始信号 DHT11_GPIO_Out(); GPIO_ResetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN); // 拉低 delay_ms(20); // 拉低至少18ms GPIO_SetBits(DHT11_GPIO_PORT, DHT11_GPIO_PIN); // 拉高 delay_us(30); // 拉高20-40us // 2. 主机设为输入,等待DHT11响应 DHT11_GPIO_In(); // 等待DHT11拉低响应(80us) if (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 1) return 0; while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 0); // 等待低电平结束 // 等待DHT11拉高响应(80us) while (GPIO_ReadInputDataBit(DHT11_GPIO_PORT, DHT11_GPIO_PIN) == 1); // 等待高电平结束 // 3. 开始接收40位数据 for (i = 0; i < 5; i++) { buf[i] = DHT11_ReadByte(); } // 4. 校验数据 checksum = buf[0] + buf[1] + buf[2] + buf[3]; if (checksum != buf[4]) { return 0; // 校验失败 } *humi = buf[0]; // 湿度整数 *temp = buf[2]; // 温度整数 // DHT11小数部分通常为0,可根据需要读取buf[1]和buf[3] return 1; // 读取成功 }main.c主程序示例(包含串口初始化与打印):
#include "stm32f10x.h" #include "usart.h" // 假设你已有串口初始化文件 #include "dht11.h" #include "delay.h" #include <stdio.h> // 重定向printf到串口1 int fputc(int ch, FILE *f) { USART_SendData(USART1, (uint8_t)ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); return ch; } int main(void) { uint8_t temperature = 0; uint8_t humidity = 0; uint8_t ret = 0; // 初始化系统时钟、延时函数、串口、DHT11 GPIO SystemInit(); Delay_Init(); USART1_Config(); DHT11_GPIO_Config(); printf("STM32 DHT11 Test Program Start...\r\n"); while (1) { ret = DHT11_ReadData(&temperature, &humidity); if (ret == 1) { printf("Temperature: %d C, Humidity: %d %%RH\r\n", temperature, humidity); } else { printf("DHT11 Read Failed!\r\n"); } Delay_ms(2000); // 每2秒读取一次,DHT11两次读取间隔需大于1秒 } }代码关键点解析:
- 延时精度:
delay_us()和delay_ms()的精度直接影响时序,进而决定通信成败。建议使用SysTick定时器实现高精度延时。 - 引脚模式切换:
DHT11_GPIO_Out()和DHT11_GPIO_In()函数实现了输出和输入模式的动态切换,这是单总线协议编程的典型操作。 - 数据读取逻辑:
DHT11_ReadByte()中,延时40us后判断引脚电平是关键。这个时间点需要根据MCU主频和传感器特性微调。 - 校验和:校验是保证数据可靠性的重要一环,不要省略。
6. Proteus仿真验证流程
代码编写完成后,先在Proteus中仿真,可以快速验证逻辑是否正确,无需担心硬件损坏。
- 编译工程生成HEX文件:在Keil中编译上述代码,确保0错误,0警告。在工程输出设置中,勾选“Create HEX File”。编译成功后,在工程目录的
Objects文件夹下找到生成的.hex文件。 - 加载HEX文件到Proteus:
- 在Proteus原理图中,双击STM32芯片,打开属性对话框。
- 在
Program File一栏,点击右侧文件夹图标,浏览并选择刚才生成的.hex文件。 Clock Frequency设置为你的系统时钟频率,例如8MHz或72MHz(需与代码中SystemInit()配置一致)。- 点击确定。
- 运行仿真:
- 点击Proteus左下角的“运行”按钮(三角形)。
- 如果电路和代码正确,虚拟终端(Virtual Terminal)窗口会自动弹出。
- 你应该能看到终端里不断打印出温湿度数据,例如:
Temperature: 25 C, Humidity: 50 %RH。 - DHT11元件上也会显示当前的温湿度值(可双击DHT11,在属性中设置显示)。
- 仿真调试:
- 如果虚拟终端没有输出,或输出乱码,首先检查串口波特率设置。在虚拟终端属性中,
Baud Rate需要与代码中串口初始化的波特率一致(如115200)。 - 如果输出“Read Failed”,可能是DHT11时序问题。可以在代码中增加调试信息,或者使用Proteus的电压探针、逻辑分析仪功能,观察DATA引脚的实际波形,与DHT11数据手册的时序图进行对比。
- 如果虚拟终端没有输出,或输出乱码,首先检查串口波特率设置。在虚拟终端属性中,
仿真成功标准:虚拟终端稳定、正确地显示变化的温湿度数值(可以通过双击DHT11元件,手动改变其温湿度值来测试)。
7. 实物调试与问题排查
仿真通过后,就可以将程序烧录到真实的STM32开发板进行测试了。这是最容易出问题的环节。
7.1 烧录与连接
- 使用ST-Link、J-Link或串口工具(需要Boot0跳线)将编译好的程序(.hex或.bin)烧录到STM32芯片中。
- 按照4.1节的表格,用杜邦线连接STM32核心板与DHT11模块。务必检查VCC、GND是否接反,DATA线是否接对,上拉电阻是否已接(或模块已集成)。
- 将STM32的串口TX引脚(如PA9)连接到USB转TTL模块的RX引脚,USB转TTL模块接入电脑。
- 打开电脑上的串口调试助手,选择正确的COM口,设置波特率(与代码一致,如115200)、数据位8、停止位1、无校验位。
7.2 常见问题与排查方法
实物调试时,你可能会遇到以下问题:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 串口无任何输出 | 1. 电源未接通或电压不足。 2. 串口线接错(TX/RX反接)。 3. 单片机未正常运行(程序未烧录或启动模式错误)。 4. 串口助手参数设置错误。 | 1. 检查核心板和模块的电源指示灯是否亮。 2. 交换TX和RX线序试试。 3. 烧录一个简单的LED闪烁程序,测试MCU是否工作。 4. 核对波特率、COM口号。 | 1. 确保供电稳定。 2. 确认接线:MCU的TX接USB转TTL的RX。 3. 检查Boot0/Boot1引脚是否为正常启动模式(通常都接地)。 4. 重启串口助手,更换COM口。 |
| 串口输出乱码 | 1. 波特率不匹配。 2. 系统时钟配置错误,导致串口定时器时钟不准。 | 1. 核对代码中串口初始化波特率与串口助手设置是否完全一致。 2. 检查 SystemInit()中的时钟树配置,特别是外部晶振频率(HSE_VALUE)是否与实际板载晶振一致(常用8MHz)。 | 1. 统一调整为常用波特率,如9600或115200。 2. 在 system_stm32f10x.c中修改HSE_VALUE定义,并确保代码中系统时钟配置正确。 |
| 始终输出“DHT11 Read Failed!” | 1. DHT11接线错误或接触不良。 2. 上拉电阻缺失或阻值不对。 3. 延时函数不准确,时序不符合DHT11要求。 4. DHT11传感器损坏。 | 1. 用万用表测量VCC、GND电压是否为3.3V,DATA线电平是否正常。 2. 检查DATA线是否有4.7K-10K上拉到3.3V。 3. 用逻辑分析仪或示波器抓取DATA引脚波形,对比DHT11时序图。 4. 更换一个DHT11模块测试。 | 1. 重新插拔、焊接连接线。 2. 确保上拉电阻正确连接。 3.重点调整 delay_us(40)这个值,可以尝试30-50us之间的不同值。优化延时函数精度(使用定时器)。4. 更换传感器。 |
| 数据偶尔失败,不稳定 | 1. 电源噪声干扰。 2. 接线过长或接触电阻大。 3. 环境干扰。 4. 两次读取间隔太短(DHT11需>1秒)。 | 1. 在VCC和GND之间并联一个100nF的电容。 2. 缩短连接线,使用质量好的杜邦线。 3. 检查代码中两次调用 DHT11_ReadData的间隔是否大于1秒。4. 在 DHT11_ReadData函数开头增加Delay_ms(1000)。 | 1. 加强电源滤波。 2. 优化布线。 3. 确保读取间隔,并可在失败时加入重试机制(如连续读取3次,取成功的结果)。 |
| 温度或湿度值明显不准 | 1. DHT11本身精度限制。 2. 传感器靠近热源(如MCU、LDO)。 3. 代码中只读取了整数部分。 | 1. 与一个已知准确的温湿度计对比。 2. 将传感器远离板载热源。 3. 检查代码是否处理了小数部分(虽然DHT11通常小数位为0)。 | 1. 理解并接受DHT11的精度范围,或换用精度更高的传感器如DHT22、SHT30。 2. 调整传感器位置。 3. 如需更高精度,可读取并计算小数部分。 |
7.3 调试技巧
- 分段调试:不要一次性调试整个系统。先确保串口打印“Hello World”正常,再单独测试DHT11读取函数,将读到的原始数据打印出来检查。
- 利用指示灯:在代码中不同阶段(如开始信号发送后、响应信号收到后)控制一个LED亮灭,可以直观判断程序执行到哪一步卡住了。
- 示波器/逻辑分析仪:这是分析时序问题的终极武器。直接测量DATA线的波形,可以清晰看到开始信号、响应信号、每一位数据的高低电平持续时间,与数据手册逐位对比。
8. 功能扩展与进阶思路
基础功能实现后,你可以考虑以下扩展方向,让项目更具实用性或挑战性。
增加显示模块:将串口输出改为在LCD1602或OLED屏幕上实时显示温湿度,制作成一个独立的检测装置。
- 连接:使用I2C或SPI接口的OLED,只需2-4根线即可驱动。
- 代码:集成OLED显示驱动库,在主循环中将温湿度数值格式化为字符串后显示。
增加报警功能:当温度或湿度超过设定的阈值时,通过蜂鸣器报警或LED闪烁提示。
- 实现:在
main.c的循环中,加入if判断,条件触发后控制一个GPIO口输出高低电平驱动蜂鸣器或LED。
- 实现:在
增加无线传输:通过ESP8266/ESP01S WiFi模块或HC-05蓝牙模块,将数据发送到手机APP或云平台。
- 思路:STM32通过串口与无线模块通信,使用AT指令配置模块并发送数据。这需要学习无线模块的AT指令集和通信协议。
使用RTOS(如RT-Thread):将温湿度读取、显示更新、网络通信等任务放在不同的线程中管理,提高系统的可扩展性和实时性。
- 挑战:需要学习RTOS的基本概念,如线程、信号量、消息队列等。
上位机软件开发:使用Python(Tkinter/PyQt)、C#或LabVIEW编写一个简单的上位机,通过串口接收数据,并绘制温湿度随时间变化的曲线图。
- 价值:完成一个完整的“下位机-上位机”系统,更具产品雏形。
9. 项目总结与最佳实践
这个基于STM32和DHT11的温湿度检测系统,虽然硬件和核心代码相对简单,但它完整地覆盖了嵌入式开发的核心流程:需求分析、器件选型、电路设计(实物/仿真)、驱动编写、功能调试、问题排查。成功实现它的关键,在于对DHT11单总线协议时序的精确把控,以及对STM32 GPIO操作模式的灵活运用。
最佳实践建议:
- 仿真先行:充分利用Proteus仿真,在烧录硬件前验证大部分逻辑,节省时间和物料成本。
- 代码模块化:将DHT11驱动、串口操作、延时函数等封装成独立的
.c/.h文件,方便移植和复用。 - 重视延时:微秒级延时函数的准确性是DHT11驱动的生命线。务必使用定时器(如SysTick)实现高精度延时,避免使用空循环。
- 添加重试机制:在
DHT11_ReadData函数外部包裹一个重试循环(例如最多尝试3次),提高系统在干扰环境下的鲁棒性。 - 做好注释与调试信息:在关键步骤(如发送开始信号、等待响应)后,通过串口打印状态信息,或者用LED指示,这对后期排查问题至关重要。
- 电源与布线:实物制作时,给DHT11的电源引脚就近增加一个0.1uF的滤波电容,并使用尽量短的导线连接DATA线,可以有效减少干扰。
当你成功在实物上看到串口稳定输出温湿度数据时,这个项目就完成了从理论到实践的关键一步。接下来,无论是添加显示屏做成桌面摆件,还是连接物联网模块实现远程监控,都有了坚实的基础。建议你把整个工程代码和原理图备份好,这不仅是你的学习成果,也是未来更多项目可以参考的宝贵资料。