STM32环境监测系统:温湿度与雨滴传感器集成TFT显示实战 简介本资源是一套基于STM32F103RCT6的嵌入式环境监测系统完整工程面向嵌入式初学者与课程设计者解决温湿度及降雨状态实时采集与TFT可视化显示的核心问题适用于气象监测、智慧农业与智能家居等实践场景。压缩包共139个文件含37个头文件.h定义硬件接口与功能模块、35个源文件.c实现DHT11协议解析、雨滴信号判读及LCD驱动逻辑另有编译中间文件.o/.d/.crf、可执行镜像.hex/.axf及Keil工程配置.uvprojx/.uvoptx整体大小为3.31MB。已有1788人学习下载。资源提供开箱即用的Keil工程结构包含SYSTEM、CORE、HARDWARE等标准分层目录集成stm32f10x固件库与自定义LCD显示函数附带keilkilll.bat清理脚本便于快速编译调试代码注释清晰传感器时序处理与TFT刷新机制均有典型实现是掌握STM32外设协同开发的优质实操范例。1. 项目概述与核心价值最近在整理手头的几个嵌入式小项目翻到了一个挺有意思的旧作——“温湿度雨滴检测——TFT液晶显示”。这个项目名字听起来就挺“全活儿”的集成了环境感知、数据显示和用户交互是很多物联网终端设备或者智能家居传感器的经典雏形。说白了它就是做一个能实时监测周围温湿度、判断是否下雨并且把所有信息直观地显示在一块彩色屏幕上的小装置。你可能觉得温湿度传感器比如DHT11、DHT22和雨滴传感器满大街都是教程一抓一大把做个显示也没什么稀奇。确实单个模块的驱动网上资料很多但真正把多个传感器、显示模块和主控芯片有机整合形成一个稳定、可靠、美观且便于二次开发的系统这里面的门道就多了。比如如何安排有限的主控资源IO口、定时器、ADC多个传感器数据采集如何避免相互干扰TFT屏刷新数据时怎样避免屏幕闪烁这些都是在实际动手时才会遇到的“坑”。这个项目的核心价值在于它提供了一个完整的、可复现的嵌入式系统集成案例。它不仅仅教你如何点亮一块屏或者读取一个传感器更重要的是展示了如何架构一个多任务、实时性要求不高的嵌入式应用软件框架。无论你是刚学完STM32基础想找个综合项目练手还是工作中需要快速搭建一个环境监测终端原型这个项目都能给你提供清晰的思路和可直接借鉴的代码。接下来我就把这个项目的设计思路、硬件选型、软件架构以及调试过程中积累的经验毫无保留地拆解一遍。2. 硬件系统设计与核心器件选型做一个项目硬件是骨架选型决定了项目的成本、复杂度和最终性能的上限。这个项目硬件结构清晰主要包含四大部分主控制器、环境传感器、雨滴传感器和人机交互界面TFT屏。我的设计原则是在满足功能、保证稳定性的前提下尽量选择常见、易获取、资料丰富的模块降低学习和复现的门槛。2.1 主控芯片为何选择STM32系列主控是整个系统的大脑负责协调所有外设、执行逻辑、处理数据。在这个项目中我选择了STM32F103C8T6也就是大家常说的“蓝色小药丸”或者“最小系统板”的核心。选择它基于以下几点考量性能与资源足够基于Cortex-M3内核主频72MHz对于读取传感器毫秒级、驱动SPI接口的TFT屏MHz级以及运行一些简单的逻辑判断和UI刷新绰绰有余。它拥有足够的GPIO、多个SPI/I2C接口、ADC和定时器能轻松应对本项目的多外设需求。生态与社区强大STM32的生态在国内是首屈一指的。无论是标准外设库Standard Peripheral Library、硬件抽象层库HAL库还是Low-Layer库都有完善的文档和丰富的示例。遇到任何问题几乎都能在论坛、博客中找到解决方案。这对于学习和快速开发至关重要。成本与易用性平衡STM32F103系列价格亲民开发板核心板种类繁多自带调试器如ST-Link或兼容性强支持J-Link、DAP-Link等调试非常方便。相比一些更简单的8位单片机它提供了更现代的开发体验如基于Keil MDK或STM32CubeIDE的工程管理、调试相比更高端的M4/M7芯片它又避免了资源过剩和成本上升。注意如果你手头有ESP32之类的Wi-Fi/蓝牙芯片当然也可以做并且能轻松添加联网功能。但本项目聚焦于本地传感与显示的集成STM32在纯粹的实时控制、低功耗管理虽然本项目未深入和硬件接口驱动的稳定性上依然有其优势。选择STM32能让代码更专注于业务逻辑而非网络协议栈。2.2 传感器模块稳定与精度的取舍温湿度传感器DHT11我选择了DHT11原因就两个字够用、简单。它的测量范围湿度20-90%RH温度0-50℃和精度湿度±5%RH温度±2℃对于室内环境监测或者一般的天气预报应用是完全足够的。其单总线通信协议只需要一个GPIO口就能读取数据极大地节省了主控资源。虽然DHT22AM2302精度更高、范围更广但对于大多数入门和中等要求的应用DHT11的性价比更高且驱动程序几乎通用。雨滴传感器模拟量输出模块雨滴检测模块通常是一个带有裸露平行导线的印刷电路板。其原理是当雨滴落在板子上会改变导线间的电阻从而影响其输出的电压。我选择的是输出模拟电压信号的模块通常还有数字开关量输出版本。模拟输出可以更细腻地反映“雨量”的大小虽然很粗略而不仅仅是“有雨”或“无雨”的二元判断。模块一般会有一个电位器用于调节灵敏度即比较器阈值。在本项目中我们使用STM32的ADC来读取这个模拟电压值。2.3 显示模块TFT液晶屏的选择与驱动显示部分是本项目的亮点也是调试的重点。我选择了一块1.44寸或1.8寸的SPI接口TFT彩屏驱动芯片通常是ST7735S或ILI9341具体看屏的型号。为什么是SPI接口的TFT节省IO口相对于并口屏需要8位或16位数据线若干控制线SPI屏通常只需要4根线SCK, MOSI, DC, CS复位RST和背光BL可单独控制这对IO紧张的主控非常友好。驱动简单SPI通信协议标准有成熟的硬件SPI外设支持软件模拟SPI也容易。市面上针对ST7735/ILI9341的驱动代码如Adafruit GFX库的移植版非常丰富。性能足够对于显示温湿度数值、简单的图标和进度条比如表示雨量SPI接口的刷新率完全够用不会感到明显卡顿。关键点屏幕的初始化与驱动库不同的屏幕即使驱动芯片相同其初始化序列一堆配置命令也可能有细微差别。这部分代码通常由屏幕厂商提供或者可以从开源社区找到匹配的驱动。我们需要一个基本的图形库来画点、线、矩形、显示字符和图片。通常我们会移植一个轻量级的库比如u8g2但更常用于OLED或者针对特定屏优化的TFT_eSPI来自Arduino社区但可以移植到STM32或者自己编写最基础的画点函数然后构建显示字符的功能。3. 软件架构与核心逻辑设计硬件连接好后软件才是让整个系统“活”起来的关键。一个好的软件架构能让代码清晰、易于维护和扩展。本项目虽然不复杂但我依然采用了模块化、分层的思想来组织代码。3.1 系统工作流程与任务划分整个系统的工作流程可以看作一个简单的超级循环Super Loop配合定时中断来实现准实时的数据采集和显示更新。上电初始化配置系统时钟、GPIO、SPI、ADC、定时器等硬件外设。初始化TFT屏幕发送初始化命令序列清屏设置显示方向等。初始化传感器对于DHT11就是设置好GPIO模式。主循环Main Loop定时触发利用一个硬件定时器产生一个固定的中断例如每2秒一次。在中断服务函数中设置一个标志位如data_update_flag 1。数据采集在主循环中不断检查data_update_flag。当标志位为1时依次执行 a. 读取DHT11的温湿度数据。 b. 读取雨滴传感器的ADC值。 c. 清除data_update_flag。数据处理与判断将ADC原始值转换为电压再根据实验标定映射为“无雨”、“小雨”、“中雨”、“大雨”等状态或一个0-100%的雨量强度值。对DHT11的数据进行校验。用户界面更新将处理好的温湿度数值、雨量状态/值通过图形函数绘制到TFT屏幕上。为了优化体验可以采用局部刷新策略只更新数值变化的区域而不是全屏刷新。异常处理在主循环中加入对传感器通信失败、数据校验错误的处理比如在屏幕上显示“传感器错误”或使用上一次的有效数据。这种架构简单有效避免了使用实时操作系统RTOS的复杂性同时通过定时中断保证了数据采集的周期性。3.2 关键驱动代码解析DHT11驱动要点DHT11的通信时序要求比较严格微秒级的延时必须准确。通常我们会用定时器或精准的空循环来实现延时。通信流程是主机STM32拉低总线至少18ms启动信号→ 释放总线等待DHT11响应 → DHT11拉低80us后拉高80us作为应答 → 随后连续输出40位数据湿度整数、湿度小数、温度整数、温度小数、校验和。每一位数据都以50us的低电平开始高电平的持续时间决定是026-28us还是170us。代码的关键在于高电平持续时间的测量通常使用输入捕获功能或精确查询GPIO电平。实操心得很多初学者读取DHT11失败问题就出在延时函数不准确上。在STM32中直接使用for循环做微秒延时受编译器优化和系统时钟影响很大。推荐的做法是使用系统滴答定时器SysTick来实现微秒延时函数或者使用一个基本定时器来产生精确的延时。另一个常见问题是读取数据后没有检查校验和导致显示乱码。务必在代码中加入校验和判断。ADC读取雨滴传感器这部分相对简单。配置一个ADC通道例如ADC1的通道0设置为单次转换模式。需要读取时启动转换等待转换完成读取数据寄存器DR的值。这个值是一个0-409512位ADC的数字对应0-3.3V的电压。关键计算电压值 (V) (ADC原始值 / 4095) * 3.3V然后你需要根据传感器特性来解读这个电压。干燥时传感器输出可能接近3.3V或VCC雨滴越多导电性越好输出电压越低。你需要通过实验来标定记录完全干燥时的ADC值ADC_dry和洒上水模拟下雨后的ADC值ADC_wet。然后可以计算一个粗略的“湿度”或“雨量”百分比雨量百分比 [(ADC_dry - ADC当前值) / (ADC_dry - ADC_wet)] * 100%将这个百分比限制在0%~100%之间。你也可以设置几个阈值来划分等级。TFT显示驱动与GUI这是代码量较大的部分。首先需要实现底层的SPI_SendByte()函数硬件SPI或软件模拟。然后实现针对屏幕驱动芯片如ST7735S的写命令Write_Cmd和写数据Write_Data函数。接着是屏幕初始化函数里面包含一长串厂家提供的初始化命令序列。在此基础上实现最基础的DrawPixel(x, y, color)画点函数。有了画点就可以构建出画线、画矩形、画圆等函数。对于显示文字通常我们会使用字模提取工具将需要的汉字和ASCII字符生成一个数组字库然后编写一个ShowString(x, y, *str, font, color, bg_color)函数该函数根据字符编码从字库中取出点阵数据调用画点函数逐个像素绘制。注意事项TFT屏幕的坐标系原点0,0可能在不同旋转方向下位于屏幕的不同角落左上、右上、左下、右下。在初始化时通过MADCTL命令设置好显示方向后你的所有绘图函数逻辑都必须基于这个设定的坐标系。否则会出现上下颠倒、左右颠倒的情况。在编写图形函数时务必考虑边界检查避免画到屏幕外面去。4. 系统集成与调试过程实录把各个模块的代码单独调通只是第一步把它们整合在一起稳定工作才是真正的挑战。下面记录几个关键的集成与调试环节。4.1 硬件连接与电源管理接线清单示例STM32F103C8T6-TFT屏 (SPI):PA5-SCK(时钟)PA7-MOSI(主出从入)PA4-CS(片选低电平有效)PA2-DC(数据/命令选择高电平为数据低电平为命令)PA1-RST(复位低电平复位)3.3V-VCCGND-GNDPA0-BL(背光控制可通过PWM调光)STM32-DHT11:PB0-DATA(单总线需接上拉电阻如4.7KΩ到3.3V)3.3V-VCCGND-GNDSTM32-雨滴传感器:PA3-AO(模拟输出接STM32的ADC引脚如ADC1_IN3)3.3V或5V-VCC(注意模块工作电压)GND-GND重要提示务必确认所有模块的供电电压一致。DHT11和很多TFT屏是3.3V逻辑电平雨滴传感器模块可能兼容5V。如果STM32是3.3V系统建议所有模块都使用3.3V供电避免电平不匹配损坏IO口。如果雨滴传感器必须5V供电其模拟输出AO可能也是5V范围则不能直接接入STM32的ADC承受电压通常为3.3V中间需要分压电路。4.2 软件模块整合与资源冲突规避当所有驱动函数就绪在main.c中整合时要注意资源冲突和时序问题。SPI与GPIO配置确保SPI引脚SCK, MOSI的复用功能已正确映射和使能。TFT的DC和CS引脚配置为推挽输出。DHT11的数据引脚配置为开漏输出模式在发送起始信号时和浮空输入模式在接收数据时并且硬件上要有上拉电阻。ADC配置配置为单次转换对齐方式为右对齐。注意ADC的时钟分频确保其不超过芯片允许的最大频率通常14MHz。定时器配置配置一个基本定时器如TIM2用于产生2秒的中断。在中断服务例程ISR中只做最简单的事情——设置标志位。绝对不要在ISR中进行复杂计算、调用printf或执行冗长的屏幕操作。主循环逻辑优化数据采集DHT11、ADC和屏幕刷新是相对耗时的操作。尤其是DHT11一次完整的读取过程需要几十毫秒。如果屏幕刷新也是全屏刷新时间更长。因此必须确保这些操作不会阻塞系统太久。我的策略是在定时中断中只设标志。主循环检测到标志后先读取传感器数据这个过程是必须的且耗时固定。屏幕刷新采用“脏矩形”技术。即在内存中维护一个“上一帧”的显示缓冲区可以是简化的重要数据只有当新数据与旧数据不同时才调用绘图函数去更新屏幕上对应的那一小块区域。例如温度从“25.1”变成“25.2”只重绘最后一位数字的区域。这能极大减少屏幕刷新时间避免闪烁。4.3 界面布局与用户体验设计一个直观的UI能极大提升项目质感。我在1.44寸屏上做了如下布局顶部区域显示项目标题如“Env Monitor”静态显示。中部左侧用一个大字体显示温度值如“25.3℃”下方用较小字体显示“Temperature”。中部右侧同样用大字体显示湿度值如“60.5%”下方显示“Humidity”。底部区域用于显示雨量信息。可以设计一个进度条长度随雨量百分比变化旁边用文字标注状态“Dry”, “Light Rain”, “Heavy Rain”或具体百分比。绘制这些元素需要用到画线、填充矩形、显示字符串等函数。注意颜色搭配确保在屏幕上有良好的对比度。可以定义一些颜色常量如BLACK,WHITE,RED,GREEN,BLUE,YELLOW等。5. 常见问题排查与深度优化技巧在实际制作和调试过程中我遇到了不少典型问题这里总结出来希望能帮你绕过这些坑。5.1 传感器数据读取异常问题1DHT11始终读取失败返回全是0或255。检查接线确认DATA线连接正确上拉电阻4.7KΩ-10KΩ已接上。检查时序这是最常见的原因。用逻辑分析仪或示波器抓取DATA线上的波形与DHT11数据手册的时序图对比。重点检查起始信号的低电平时间18ms、等待响应的时间、以及每一位数据中高电平的持续时间。确保你的微秒延时函数是准确的。如果使用查询方式在等待DHT11拉高或拉低时一定要设置超时机制避免程序死等。电源问题DHT11对电源纹波比较敏感。确保供电稳定可以在VCC和GND之间加一个0.1uF的滤波电容。代码逻辑确保在读取数据前已将GPIO模式从输出切换到输入。读取完40位后务必校验数据和前4个字节之和的低8位等于校验和字节。问题2雨滴传感器ADC值不稳定跳动很大。电源噪声模拟电路对电源噪声非常敏感。确保给传感器模块的供电是干净的。可以使用线性稳压器如AMS1117-3.3单独供电并在模块的VCC和GND之间并联一个10uF的电解电容和一个0.1uF的陶瓷电容。信号滤波在软件上对ADC采样值进行滤波。最简单的是多次采样取平均值例如连续采样10次去掉最大最小值后求平均。更高级的可以用一阶低通滤波软件实现filtered_value α * current_adc (1-α) * filtered_value其中α是滤波系数0α1值越小滤波效果越强响应越慢。参考电压确保STM32的ADC参考电压通常是VDDA连接到3.3V稳定。如果系统中有大功率器件如电机、继电器频繁开关可能会引起电源波动影响ADC精度。5.2 TFT显示相关问题问题1屏幕白屏、花屏或显示错乱。初始化序列错误这是首要怀疑对象。不同厂家、不同批次的屏幕初始化命令序列可能有细微差别。务必使用卖家提供的或经过验证的针对你手中这块屏的初始化代码。初始化命令的顺序、参数都不能错。SPI时序问题检查SPI的时钟极性CPOL和相位CPHA设置。ST7735S通常模式是CPOL0, CPHA0。如果不对数据就无法正确锁存。可以尝试另外三种模式组合。速度问题SPI时钟速度太快可能导致屏幕驱动芯片无法响应。尝试降低SPI的波特率分频如从PCLK/2降到PCLK/8。复位与电源确保上电时序正确。有些屏幕要求复位信号RST在电源稳定后保持一段时间的低电平。检查背光BL是否使能。问题2屏幕刷新慢有闪烁感。全屏刷新这是导致闪烁的根本原因。每次更新数据都清屏重画全部内容在刷新过程中屏幕会呈现撕裂或闪烁状态。解决方案实施局部刷新。如前所述只更新数据变化的区域。例如温度数字有4位从“25.1”变到“25.2”只有最后一位变了。那么就在绘制新数字“2”之前先用背景色把旧数字“1”的区域覆盖掉画一个实心矩形再画上新数字“2”。这样操作只影响屏幕上很小一块区域速度极快人眼几乎感知不到。双缓冲对于更复杂的图形界面可以考虑双缓冲技术。即在内存中开辟一块和屏幕分辨率一样大的缓冲区Frame Buffer所有的绘图操作都在这个缓冲区中进行。完成一帧的绘制后一次性将整个缓冲区的内容通过SPI发送到屏幕。这能完全消除撕裂但需要大量内存对于130x130的16位色屏幕需要至少33.8KB的RAMSTM32F103C8T6只有20KB RAM可能无法承受。因此局部刷新是本项目更可行的优化方案。5.3 系统稳定性与抗干扰问题系统运行一段时间后死机或数据明显异常。看门狗启用独立看门狗IWDG或窗口看门狗WWDG。在主循环中定期“喂狗”。如果程序跑飞或陷入死循环看门狗会在超时后复位系统提高设备的自恢复能力。中断冲突检查是否有中断服务程序执行时间过长或者中断嵌套导致栈溢出。确保中断优先级设置合理关键时序中断如SysTick用于延时的优先级最高。电源完整性使用示波器观察3.3V电源轨在系统运行时尤其是屏幕刷新瞬间是否有大的毛刺或跌落。如有必要增加电源部分的电容容值。6. 项目扩展与进阶思路这个基础项目就像一个乐高底座可以在上面添加很多有趣的模块演变成功能更丰富的设备。添加实时时钟RTC接入DS1302或DS3231模块在屏幕上显示当前时间、日期并可以实现数据定时记录的功能。增加数据存储加入SPI Flash如W25Q64或SD卡模块将历史温湿度、雨量数据以文件形式存储便于后续分析。实现无线传输这是最热门的扩展方向。可以替换或增加一个ESP8266/ESP32模块通过Wi-Fi将数据上传到云平台如阿里云、腾讯云IoT、Home Assistant或者发送到手机APP。这样你就可以远程监控环境了。添加更多传感器例如接入大气压强传感器BMP280、空气质量传感器PMS5003、光照强度传感器等打造一个多功能环境监测站。优化人机交互增加一个旋转编码器或按键配合TFT屏幕实现菜单系统可以切换显示页面、设置报警阈值、查看历史数据等。低功耗设计如果采用电池供电就需要考虑低功耗。可以让MCU大部分时间处于睡眠模式Stop或Standby定时被RTC闹钟或外部中断如雨滴传感器达到阈值唤醒采集一次数据并刷新屏幕然后继续睡眠。这能极大地延长续航时间。在实现这些扩展时软件架构可能需要升级。例如引入一个简单的状态机来管理不同的显示页面或者使用一个轻量级的RTOS如FreeRTOS来管理传感器读取、数据显示、网络通信等多个任务。但无论如何当前这个项目的实践为你打下了坚实的硬件驱动和系统集成基础。本文还有配套的精品资源点击获取