STM32智能家居毕业设计入门指南:从零搭建低功耗可可扩展系统
摘要:许多电子/物联网专业学生在完成STM32智能家居毕业设计时,常陷入硬件选型混乱、通信协议不统一、代码结构混乱等困境。本文面向新手,系统讲解如何基于STM32F1/F4系列MCU,结合FreeRTOS与MQTT协议,构建一个模块化、低功耗且具备基础安全机制的智能家居原型。读者将掌握传感器集成、Wi-Fi模组驱动、任务调度设计等核心技能,并获得可复用的工程模板,显著降低开发门槛与调试成本。
一、新手常见痛点速览
外设冲突
定时器、串口、ADC、I²C 引脚复用规则不熟,导致“一上电就死机”。电源管理缺失
直接忽略 STOP 模式,整机 80 mA 跑到底,移动电源带不动,答辩现场尴尬。协议栈混乱
裸机里塞了 HTTP、TCP、JSON 解析,全部放中断回调,逻辑交错,调试靠“printf 大法”。代码耦合高
传感器驱动、网络驱动、业务逻辑写在同一个 main.c,一改全崩。调试信息淹没
串口 115200 bps 打印全速日志,上位机卡死,逻辑分析仪抓不到有效帧。
二、方案对比:选对不选贵
| 维度 | 裸机 | FreeRTOS | 说明 |
|---|---|---|---|
| 实时性 | 中断硬实时 | 任务+中断 | RTOS 可降低中断负载 |
| 扩展性 | 差 | 好 | 后期加 OTA、网关容易 |
| 学习成本 | 低 | 中 | 本文给出模板,成本可控 |
| 协议 | HTTP | MQTT | 说明 |
|---|---|---|---|
| 头部开销 | 数百字节 | 2~4 B | 低带宽场景 MQTT 优势明显 |
| 发布/订阅 | 无 | 原生 | 多设备联动时 MQTT 更简洁 |
| 库体积 | 40 kB+ | <10 kB | STM32F103CB 能剩空间给 OTA |
| Wi-Fi 模组 | ESP8266 | ESP32 | 说明 |
|---|---|---|---|
| 单价 | 15 RMB | 25 RMB | 毕业设计预算敏感 |
| 二次开发 | 需 AT | 可 ESP-IDF | 本文用 AT 固件,主控仍是 STM32 |
| 低功耗 | 无 | 有 10 µA 深睡 | 但智能家居常供电,ESP8266 够用 |
结论:
“STM32 + FreeRTOS + MQTT + ESP8266(AT)” 在成本、易用、资料丰富度三方面最平衡。
三、系统架构与初始化流程
硬件拓扑
- MCU:STM32F103CBT6(128 kB Flash,20 kB RAM)
- 传感器:DHT11(温湿度)
- 执行器:继电器模块(光耦隔离,低电平有效)
- 通信:ESP8266(AT 固件 1.7.4)
- 电源:AMS1117-3.3 + MP1584 双路 DCDC,5 V 适配器输入
软件分层
- Board Support:时钟、GPIO、USART、ADC 初始化
- FreeRTOS 层:任务创建、消息队列、信号量
- 中间件:MQTT-C(轻量级开源库)、cJSON
- 应用:sensor_task、actuator_task、net_mqtt_task、ota_task(预留)
上电初始化序列(保证时序正确)
- HAL 初始化 → 时钟 → 滴答 1 kHz
- 创建“系统日志队列” xSystemLogQueue(长度 256)
- 创建 vTask:
- task_cli:负责串口命令行,优先级 2
- task_sensor:DHT11 采样,优先级 3
- task_actuator:继电器控制,优先级 3
- task_net:ESP8266 驱动 + MQTT,优先级 4
- 启动调度器 vTaskStartScheduler()
四、任务划分与消息队列设计
传感器任务
- 周期 5 s 读取 DHT11
- 失败重试 3 次,仍失败发布 error 码
- 数据封装为 JSON:{"id":"temp","val":26.3,"ts":1683xxx}
执行器任务
- 等待队列 xActuatorQueue(结构体含 cmd、duration_ms)
- 支持指令:ON、OFF、TOGGLE
- 收到指令后回写“ack”到 xSystemLogQueue,供串口 CLI 打印
网络任务
- 状态机:WIFI_INIT → MQTT_CONNECT → MQTT_YIELD
- 断开重连使用指数退避:1 s → 2 s → 4 s … 最大 64 s
- 订阅 Topic:/home/ctrl/<device_id>
- 发布 Topic:/home/status/<device_id>
消息队列定义(代码片段)
/* FreeRTOS 包含 */ #include "FreeRTOS.h" #include "queue.h" typedef struct { uint8_t cmd; /* 0=ON,1=OFF,2=TOGGLE */ uint16_t duration_ms; /* 持续时间,0 表示常开 */ } actuator_msg_t; static QueueHandle_t xActuatorQueue; void vActuatorTask(void *pv) { actuator_msg_t rxMsg; for (;;) { if (xQueueReceive(xActuatorQueue, &rxMsg, portMAX_DELAY) == pd) { switch (rxMsg.cmd) { case 0: HAL_GPIO_WritePin(RELAY_GPIO_Port, GPIO_PIN_RESET); break; case 1: HAL_GPIO_WritePin(RELAY_GPIO_Port, GPIO_PIN_SET); break; case 2: HAL_GPIO_TogglePin(RELAY_GPIO_Port); break; } if (rxMsg.duration_ms) { vTaskDelay(pdMS_TO_TICKS(rxMsg.duration_ms)); HAL_GPIO_WritePin(RELAY_GPIO_Port, GPIO_PIN_SET); /* 自动关闭 */ } } } }五、关键代码片段:MQTT 重连与传感器读数
- MQTT 连接与重试(Clean Code 原则:单一职责、错误码集中处理)
static int mqttReconnect(void) /* 指数退避重连,返回 0 表示成功 */ { static uint8_t retryCnt = 0; const uint32_t backoff[] = {1000,2000,4000,8000,16000,32000,64000}; MQTTClient client = {0}; int rc = -1; while (retryCny < ARRAY_SIZE(backoff)) { rc = MQTTConnect(&client, &broker); if (rc == MQTT_SUCCESS) { retryCny = 0; /* 成功后清零 */ return 0; } vTaskDelay(pdMS_TO_TICKS(backoff[retryCny])); retryCny++; } return -1; /* 仍失败,通知系统重启 */ }- DHT11 驱动(注意 18 ms 起始信号 + 40 µs 采样窗口)
static int dhtRead(float *temp, float *humi) { uint8_t bits[5]0]; DHT_Start(); if (DHT_CheckResponse() != OK) return -1; for (int i = 0; i < 40; i++) bits[i/8] <<= 1; if (DHT_Crc8(bits, 4) != bits[4]) return -2; /* CRC 校验 */ *humi = bits[0] + bits[1] * 0.1f; *temp = bits[2] + bits[3] * 0.1f; return 0; }六、低功耗优化策略
策略
- 采样间隔 5 s,MCU 空闲即进入 STOP 模式(<0.5 mA)
- ESP8266 在 MQTT 保持心跳 60 s,无数据时关闭射频;需要发送时 AT+CWJAP 重连(约 3 s)
- 继电器采用“开-定时-关”模式,避免长时间吸合发热
实测
5 V 输入,整机平均 12 mA,峰值 80 mA(Wi-Fi 发射瞬间),1000 mAh 移动电源可续航 3 天,满足毕设演示。
七、基础安全措施
固件完整性
在 Bootloader 计算 APP 区 CRC32,与末尾 4 B 对比,错误即锁死并串口告警。Topic 权限
- 设备仅可发布 /home/status/<device_id>+
- 服务器 ACL 禁止设备订阅他人主题,防止横向控制。
通信加密
若路由器支持,ESP8266 使能 WPA2-PSK;MQTT 层可升级至 TLS,但 STM32 RAM 紧张,建议留到后续 ESP32 方案。
八、生产环境避坑指南
串口调试干扰
打印与 AT 口复用 USART1,导致“+++”被误判为透明传输。解决:调试口改用 USART2,或打印前关中断。看门狗配置失误
IWDG 一旦启用,STOP 模式也会计数;忘记喂狗导致休眠即复位。解决:进入低功耗前暂停 IWDG,或改用窗口看门狗 WWDG。Wi-Fi 冷启动失败
上电 0.5 s 内发 AT,ESP8266 固件尚未就绪,返回 ERROR。解决:在 vTaskNet 里等待 2 s 再发第一条 AT。DHT11 长导线读 0
大于 5 m 排线时,信号被电容糊掉。解决:改用单总线 DS18B20 或加 74HC04 驱动。
九、下一步可扩展
- 温控联动:把温度阈值也做成 Topic,/home/config/<device_id>/targetTemp,当 val>target+1 时自动开继电器风扇。
- OTA:STM32 端实现 YModem over MQTT,服务器推送 .bin,Bootloader 接收后 CRC 校验并跳转。
- 多节点:复制同一固件,修改 device_id 宏即可在局域网组成星型网络,毕业答辩秒变“小型物联网展厅”。
全文代码与 CubeMX 工程模板已开源在 Gitee,拿到板子后 30 分钟就能跑通第一包 MQTT。
别再把时间花在“找资料”上,把省下的精力拿去扩展温控联动或 OTA,毕业设计自然脱颖而出。祝调试顺利,答辩一次过!