构建一个基于 STM32 的房间监控系统
室内空气质量、环境光照和房间占用情况直接影响人类的生产效率、健康状况和能源节约。在嵌入式系统中,同时管理多个实时传感器、响应式用户界面和安全警报,是一项经典的工程难题。
传统的裸机程序依赖于单体式的超循环结构(while(1)),而缓慢的传感器读取(例如 DHT22 的约 20 毫秒单线脉冲握手)会导致处理器卡顿,造成按钮响应迟缓和屏幕闪烁。
在本项目中,我们使用 FreeRTOS 和 STM32Cube 框架,在 STM32 Blue Pill(STM32F103C8T6)上设计并实现了一个完全并发的环境监测系统。通过消除阻塞延迟、确保周期性采样无漂移、使用互斥锁保护共享硬件资源,并实现自动化的睡眠状态机,有效解决了上述问题。
主要特点
• 并行任务架构:6个独立的FreeRTOS任务,采用优先级抢占式调度。
• 多传感器遥测功能:
温度与湿度:通过ARM Cortex-M的DWT周期计数器,使用DHT22单线协议进行采样。
环境光:通过PA0上的12位ADC1采样模拟光敏电阻(LDR)信号。
占用检测:PA3连接数字PIR运动传感器。
• 交互式用户界面:基于400 kHz硬件I2C1运行的SSD1306 128x64 OLED显示屏,通过KY-040旋转编码器实现前后循环导航。
• 超出范围安全报警:当温度低于18.0°C或高于30.0°C时,1 kHz PWM音频蜂鸣器会主动提醒使用者。
• 智能节能状态机:在无运动15秒后自动将OLED面板进入低功耗待机模式,运动或旋转旋钮操作可立即恢复活动模式。
• 无Arduino抽象层:完全基于ST HAL驱动程序和原生FreeRTOS API构建。
硬件引脚连接
• LDR 传感器:PA0(模拟 ADC1_IN0)——环境光强度(0–100%)
• DHT22 传感器:PA1(GPIO 开漏输出)——温度和湿度单线协议
• 活动蜂鸣器:PA2(TIM2_CH3 PWM)——1 kHz 可听报警音
• PIR 传感器:PA3(数字输入带下拉)——人体运动检测
• 旋转编码器 CLK:PA4(EXTI4 下降沿)——正交步进中断
• 旋转编码器 DT:PA5(数字输入带上拉)——正交方向线
• SSD1306 OLED SCL:PB6(硬件 I2C1)——400 kHz 快速模式时钟
• SSD1306 OLED SDA:PB7(硬件 I2C1)——400 kHz 快速模式数据
• 串行终端:PA9 / PA10(USART1)——115200 8N1 诊断遥测
• 状态心跳:PC13(GPIO 输出)——板载 LED 活动脉冲
连接表
FreeRTOS 多任务架构
该应用由 6 个并发任务组成,各任务优先级根据调度紧迫性设定:
•输入任务(优先级 3,高):去抖编码器脉冲、循环显示页面、唤醒休眠系统。
•运动任务(优先级 3,高):每 100 毫秒采样一次 PA3 上的 PIR 传感器,更新事件标志。
•状态任务(优先级 3,高):中央状态机,管理 15 秒的睡眠/唤醒定时器。
•传感器任务(优先级2,中等):每2000毫秒采样一次DHT22和LDR,使用vTaskDelayUntil确保时间漂移为零。
•报警任务(优先级2,中等):评估18°C至30°C的温度范围,并触发蜂鸣器。
•显示任务(优先级1,低):专用于管理SSD1306 OLED显示屏并呈现遥测数据。
软件工程亮点
无漂移周期执行(vTaskDelayUntil):标准延时会累积执行和中断开销,导致时间漂移。使用vTaskDelayUntil可强制实现精确的0.5 Hz采样频率,锚定于绝对时钟计数。
线程安全日志记录(serialMutex):并发任务向USART1输出诊断字符串时,通过FreeRTOS递归互斥锁进行同步。这防止字符交错,确保终端遥测数据清晰准确。
自动化单元测试(100%通过):硬件无关的决策逻辑被解耦为纯C语言模块(logic.c),并在主机PC上使用Unity测试运行器验证(13个单元测试全部通过)。
静态代码分析(0个缺陷):通过PlatformIO Check与cppcheck验证,未发现高、中、低等级缺陷。
挑战与仿真解决方案
在Wokwi虚拟仿真过程中,我们诊断出一个模拟器的限制:标准Cortex-M3异常返回弹栈(通过SVC 0的EXC_RETURN)在任务启动时失败。
我们设计了一个直接的线程模式上下文切换端口(基于Djaver Hassan开源实现改编,致谢:Ni-ear):
• 第一个任务使用prvTaskBootstrap在PSP上以线程模式启动。
• 任务通过vPortYieldDirect()直接让出执行权,无需依赖PendSV。
• 调度程序的时钟由运行频率为20 Hz的硬件定时器TIM3驱动,从而降低了浏览器仿真的开销,同时保持了100%的功能完整性。
本文编译自hackster.io





