一、项目背景:让中控"有大脑"
过去的家居控制器多为单任务设计------一个循环控制灯、温湿度传感器、WiFi模块,结构简单但不灵活。
我希望构建一个多任务、可扩展、具实时响应能力的中控系统。
系统目标:
-
以 STM32F407 为核心,运行 FreeRTOS 实时操作系统;
-
管理温湿度、光照、灯光控制模块;
-
支持 ESP8266 WiFi 模块远程通信;
-
具备低功耗与容错机制;
-
提供 OLED 状态显示界面。
✳️ 应用场景:家庭环境监测 + 灯光控制 + 无线云端通信
二、硬件设计与模块选型
1️⃣ 硬件模块清单
| 模块 | 型号 | 接口 | 功能 |
|---|---|---|---|
| 主控芯片 | STM32F407VGT6 | ARM Cortex-M4 | 系统主控 |
| 温湿度传感器 | DHT11 | GPIO | 环境检测 |
| WiFi 模块 | ESP8266 | UART | 无线通信 |
| OLED 显示 | SSD1306 | I2C | 信息显示 |
| 蜂鸣器与按键 | 自制板 | GPIO | 用户交互 |
| 电源 | AMS1117-3.3V | - | 稳压供电 |
2️⃣ 硬件连接结构(简化图)
┌──────────────┐ │ STM32F407 │ │ │ │ I2C → OLED │ │ UART → ESP8266 │ │ GPIO → DHT11 │ │ GPIO → LED/Buzzer │ └──────────────┘
电源统一采用 5V 输入,经 AMS1117 稳压至 3.3V,主控与 WiFi 共用。
三、软件架构与任务划分
系统运行 FreeRTOS v10.4,采用任务 + 队列通信模式。核心结构如下:
+-----------------------+ | FreeRTOS Kernel | |-----------------------| | WifiTask (3) | 高优先级,网络通信任务 | SensorTask (2) | 中优先级,采集DHT11数据 | DisplayTask (1) | 低优先级,OLED刷新 | ControlTask (2) | 按键与输出控制 | PowerTask (0) | 低功耗管理 +-----------------------+
📁 模块划分
/Core/Src
├── main.c
├── freertos.c
├── task_sensor.c
├── task_wifi.c
├── task_display.c
├── driver_dht11.c
├── driver_oled.c
└── utils_log.c
四、主要任务与代码实现
1️⃣ 传感器任务(SensorTask)
负责定时采集温湿度数据并发送到队列中。
#include "dht11.h"
#include "cmsis_os.h"
extern QueueHandle_t xSensorQueue;
void SensorTask(void *argument) {
SensorData_t data;
float t = 0, h = 0;
for (;;) {
if (DHT11_ReadData(&t, &h) == HAL_OK) {
data.temperature = t;
data.humidity = h;
xQueueSend(xSensorQueue, &data, 0);
}
vTaskDelay(pdMS_TO_TICKS(2000)); // 每2秒更新一次
}
}
驱动层(driver_dht11.c):
uint8_t DHT11_ReadData(float *temp, float *humi) {
uint8_t buf[5] = {0};
// 发送起始信号
DHT11_Start();
if (DHT11_CheckResponse() == HAL_OK) {
for (int i = 0; i < 5; i++) buf[i] = DHT11_ReadByte();
*humi = buf[0];
*temp = buf[2];
return HAL_OK;
}
return HAL_ERROR;
}
2️⃣ WiFi任务(WifiTask)
通过 UART 与 ESP8266 通信,实现数据上报与指令接收。
#include "esp8266.h"
void WifiTask(void *argument) {
char payload[64];
SensorData_t rxData;
ESP8266_Init();
ESP8266_ConnectWiFi("MyHome", "12345678");
for (;;) {
if (xQueueReceive(xSensorQueue, &rxData, portMAX_DELAY)) {
sprintf(payload, "{\"temp\":%.1f, \"humi\":%.1f}",
rxData.temperature, rxData.humidity);
ESP8266_SendData(payload);
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
WiFi驱动简化(esp8266.c):
void ESP8266_SendData(char *data) {
char cmd[128];
sprintf(cmd, "AT+CIPSEND=%d\r\n", strlen(data));
HAL_UART_Transmit(&huart1, (uint8_t *)cmd, strlen(cmd), 100);
HAL_UART_Transmit(&huart1, (uint8_t *)data, strlen(data), 100);
}
3️⃣ 显示任务(DisplayTask)
#include "oled.h"
void DisplayTask(void *argument) {
SensorData_t sensor;
char line1[16], line2[16];
OLED_Init();
for (;;) {
if (xQueuePeek(xSensorQueue, &sensor, portMAX_DELAY)) {
sprintf(line1, "Temp: %.1fC", sensor.temperature);
sprintf(line2, "Humi: %.1f%%", sensor.humidity);
OLED_Clear();
OLED_ShowString(0, 0, line1);
OLED_ShowString(0, 16, line2);
}
vTaskDelay(pdMS_TO_TICKS(1500));
}
}
4️⃣ 控制任务与低功耗管理
按键中断触发控制灯光状态;空闲时进入低功耗模式:
volatile uint8_t ledState = 0;
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == KEY_Pin) {
ledState = !ledState;
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, ledState);
}
}
void PowerTask(void *argument) {
for (;;) {
if (ledState == 0) {
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
vTaskDelay(pdMS_TO_TICKS(3000));
}
}
五、系统调试与性能优化
✅ RTOS 调度优化
使用 STM32CubeIDE FreeRTOS Viewer 观察任务切换:
| 任务 | 周期(ms) | CPU占用(%) |
|---|---|---|
| WifiTask | 1000 | 28 |
| SensorTask | 2000 | 15 |
| DisplayTask | 1500 | 10 |
| ControlTask | 异步 | 5 |
| IdleTask | - | 42 |
可见CPU空闲率>40%,系统运行平稳。
通过 vTaskSuspend() 在WiFi空闲时挂起任务,节省能耗约18%。
✅ 串口日志调试系统
增加简单日志模块(utils_log.c):
void Log_Info(const char *fmt, ...) {
char buf[128];
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
strcat(buf, "\r\n");
HAL_UART_Transmit(&huart2, (uint8_t *)buf, strlen(buf), 100);
}
运行输出:
[INFO] FreeRTOS started. [INFO] Sensor: T=25.8 H=49.3 [INFO] WiFi: Send OK
✅ 功耗测试结果
| 模式 | 电流(mA) |
|---|---|
| 全运行模式 | 22.8 |
| WiFi空闲 | 13.4 |
| STOP模式 | 3.2 |
节能策略包括:
-
传感器周期采集;
-
任务空闲挂起;
-
动态时钟调节(降低主频到84MHz);
-
关闭未用外设(ADC、TIM等)。
六、项目总结与经验分享
在本项目中,从硬件搭建到软件架构设计,我总结了几点关键经验:
-
架构先行:任务划分清晰、接口独立;
-
调度有序:FreeRTOS 的优先级规划非常关键;
-
日志必备:UART调试输出可快速定位死锁;
-
功耗优化:低功耗设计是嵌入式永恒主题;
-
模块复用:驱动层通用接口设计可快速移植。
七、未来展望
接下来我计划引入:
-
✳️ TinyML(Micro speech模型),实现语音命令控制;
-
✳️ MQTT 协议 接入云端;
-
✳️ RISC-V 平台移植 实验对比;
-
✳️ CI/CD 构建脚本 自动化编译固件。