从0到1:基于STM32与FreeRTOS的智能家居中控系统设计实录

一、项目背景:让中控"有大脑"

过去的家居控制器多为单任务设计------一个循环控制灯、温湿度传感器、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等)。


六、项目总结与经验分享

在本项目中,从硬件搭建到软件架构设计,我总结了几点关键经验:

  1. 架构先行:任务划分清晰、接口独立;

  2. 调度有序:FreeRTOS 的优先级规划非常关键;

  3. 日志必备:UART调试输出可快速定位死锁;

  4. 功耗优化:低功耗设计是嵌入式永恒主题;

  5. 模块复用:驱动层通用接口设计可快速移植。


七、未来展望

接下来我计划引入:

  • ✳️ TinyML(Micro speech模型),实现语音命令控制;

  • ✳️ MQTT 协议 接入云端;

  • ✳️ RISC-V 平台移植 实验对比;

  • ✳️ CI/CD 构建脚本 自动化编译固件。

相关推荐
CHY_12843 分钟前
JESD204B 协议解析(4)Subclass2 时序分析
嵌入式硬件·fpga开发·jesd204
恒锐丰小吕4 小时前
屹晶微 EG2163 高集成度三相半桥驱动芯片技术解析
嵌入式硬件·硬件工程
Meraki.Zhang5 小时前
【STM32实践篇】:STM32CubeMX 的使用
stm32·单片机·嵌入式软件
番茄灭世神5 小时前
OTA远程升级STM32固件
stm32
古译汉书7 小时前
嵌入式笔记(个人总结)
数据结构·笔记·stm32·单片机·嵌入式硬件
bai5459368 小时前
STM32 定时器(Timer)
stm32·单片机·嵌入式硬件
沐欣工作室_lvyiyi14 小时前
基于STM32的宠物自动喂食器(论文+源码)
stm32·嵌入式硬件·毕业设计·宠物
学生哥-_-21 小时前
STM32点亮WS2812 RGB灯板展示像素图片(一种较方便的取色值数据的方法)
stm32·单片机·嵌入式硬件
西欧伯爵1 天前
模拟电路入门四
单片机·嵌入式硬件·集成电路
偶像你挑的噻1 天前
12-Linux驱动开发- SPI子系统
linux·驱动开发·stm32·嵌入式硬件