GD32F407 + FreeRTOS 智能家居环境监测系统
项目概述
基于 GD32F407 (Cortex-M4F, 168MHz) 与 FreeRTOS 实时操作系统的模块化智能家居与环境监测系统,集成 10+ 种传感器与执行器,通过 USART HMI 串口屏进行人机交互。
核心亮点:
- 获海南省职业技能竞赛嵌入式赛道二等奖和三等奖
- 16个 FreeRTOS 任务并行运行
- 自定义 HMI 二进制协议 + ASCII 命令系统
- 多种滤波算法:卡尔曼滤波、中值滤波、移动平均
| 参数 | 值 |
|---|---|
| MCU | GD32F407 (Cortex-M4F, 168MHz) |
| RTOS | FreeRTOS V202212.01 |
| Tick | 1000Hz (1ms) |
| Heap | 17KB (heap_4.c) |
| 最高优先级 | 5级 |
| 交互终端 | USART2 HMI (9600bps) |
| 调试串口 | USART0 (115200bps) |
系统架构
code
┌─────────────────────────────────────────────┐
│ USART HMI 串口屏 │
│ (USART2, 9600bps) │
└────────────────┬────────────────────────────┘
│ HMI 协议 (FE + ASCII)
┌────────────────┴────────────────────────────┐
│ FreeRTOS 调度器 │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │DHT11 │ │BH1750│ │DS18B │ │HX711 │ │
│ │任务 │ │任务 │ │20任务│ │任务 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │烟雾 │ │酒精 │ │PIR │ │超声 │ │
│ │任务 │ │任务 │ │任务 │ │波任务│ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │步进 │ │舵机 │ │风扇 │ │门锁 │ │
│ │电机 │ │任务 │ │任务 │ │任务 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │蜂鸣 │ │LED │ │Sys │ │MPU │ │
│ │器 │ │控制 │ │Mon │ │6050 │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ │
├─────────────────────────────────────────────┤
│ GD32F407 (Cortex-M4F, 168MHz) │
└─────────────────────────────────────────────┘
硬件资源映射
传感器阵列
| 模块 | 接口 | 引脚 | 说明 |
|---|---|---|---|
| DHT11 | 单总线 | PC7 | 温湿度(含卡尔曼滤波) |
| BH1750 | I2C | SCL:PE5, SDA:PE6 | 光照强度 |
| DS18B20 | 单总线 | PD15 | 高精度温度 |
| HX711 | 串行 | SCK:PC9, DOUT:PA8 | 称重/压力 |
| MQ-2 烟雾 | ADC | PA1 (ADC0_IN1) | 烟雾浓度 |
| MQ-3 酒精 | ADC | PA1 (ADC0_IN1) | 酒精浓度(与烟雾共用) |
| PIR 红外 | GPIO | PC8 | 人体感应 |
| HC-SR04 超声 | GPIO+EXTI | Trig:PA12, Echo:PA11 | 距离测量 |
| MPU6050 | 硬件I2C | SCL:PB10, SDA:PB11 | 六轴姿态 |
| RC522 RFID | 软件I2C | SCL:PA8, SDA:PC9 | 非接触式读卡 |
执行器
| 模块 | 接口 | 引脚 | 说明 |
|---|---|---|---|
| 28BYJ-48 步进电机 | GPIO 4相 | PB2~PB5 | 步进电机 |
| SG90 舵机 | PWM | PA0 (TIM4_CH0, 50Hz) | 角度控制 |
| 直流风扇 | PWM | PD14 (TIM3_CH2, 10kHz) | 调速 |
| 电磁锁 | GPIO | PD13 | 高电平解锁 |
| 蜂鸣器 | GPIO | PC12 | 音乐播放 |
| 4路LED | GPIO | PE12~PE15 | 跑马灯 |
| WS2812B RGB | 单总线 | PD12 | RGB灯珠(GRB) |
| 点阵屏 74HC595 | SPI | PC0~PC3 | 文本/图形滚动 |
FreeRTOS 任务设计
系统采用抢占式调度,共 16 个任务:
| 任务 | 优先级 | 栈(Word) | 周期 | 功能 |
|---|---|---|---|---|
| HMI | 3 | 256 | 事件驱动 | 串口指令解析分发 |
| Buzzer | 3 | 128 | 50ms | 蜂鸣器控制 |
| Ultrasonic | 3 | 512 | 100ms | 超声波测距 |
| StepMotor | 3 | 256 | N/A | 步进电机相位 |
| HX711 | 3 | 256 | 200ms | 重量采集 |
| Smoke | 3 | 256 | N/A | 烟雾监测 |
| Alcohol | 3 | 256 | N/A | 酒精监测 |
| DoorLock | 2 | 256 | N/A | 门锁控制 |
| LED | 2 | 128 | 500ms | 跑马灯 |
| SysMon | 2 | 256 | 1000ms | 系统监控 |
| Servo | 2 | 128 | N/A | 舵机控制 |
| Fan | 2 | 256 | N/A | 风扇调速 |
| DS18B20 | 2 | 512 | ~1000ms | 温度采集 |
| PIR | 2 | 256 | N/A | 人体红外 |
| DHT11 | 2 | 512 | 1000ms | 温湿度采集 |
| BH1750 | 2 | 512 | ~350ms | 光照采集 |
优先级设计原则:
- 优先级 3:外设交互/时间敏感任务(HMI、超声波、蜂鸣器等)
- 优先级 2:常规采集与控制任务
- 优先级 0/1:空闲与后台任务
HMI 通信协议
二进制控制帧
格式:帧头(0xFE) + 指令码(1B) + 数据(NB)
c
// 指令解析示例
switch (cmd) {
case 0x08: ultrasonic_thread_start(); break; // 启动超声波
case 0x09: ultrasonic_thread_stop(); break; // 停止超声波
case 0x10: ds18b20_thread_start(); break; // 启动DS18B20
case 0x19: buzzer_thread_start(); break; // 启动蜂鸣器
case 0x23: step_motor_thread_start(); break; // 启动步进电机
case 0x25: step_motor_set_forward(); break; // 步进电机正转
case 0x26: step_motor_set_reverse(); break; // 步进电机反转
case 0x29: fan_thread_start(); break; // 启动风扇
case 0x46: door_lock_unlock_cmd(); break; // 解锁
case 0x61: smoke_thread_start(); break; // 启动烟雾检测
// ... 共30+条指令
}
ASCII 控制帧
格式:0xFF + ASCII指令
code
slider1=<0..100> → 更新风扇速度
text=<str> → 点阵屏显示文本
ISR 与任务间通信
code
USART2_IRQHandler
→ 以 0xAA 起始, 0x04 结束收包
→ xQueueSendFromISR()
→ uartQueue (8个槽位)
→ HMI Task (xQueueReceive + 解析)
传感器驱动要点
超声波测距(中断模式)
c
void Ultrasonic_Test(void) {
// 发送 10us Trig 脉冲
GPIO_BC(GPIOA) = GPIO_PIN_12; delay_1us(2);
GPIO_BOP(GPIOA) = GPIO_PIN_12; delay_1us(10);
GPIO_BC(GPIOA) = GPIO_PIN_12;
TIMER_CAR(TIMER1) = 0; // 清零计数器
}
// EXTI10_15 ISR 捕获 Echo 下降沿 → 读取 TIMER1 → 计算距离
// Distance = Time * 0.017,累加10次取均值
DHT11 温湿度(临界区保护)
c
// 单总线时序敏感,读数据前进入临界区
taskENTER_CRITICAL();
uint8_t data[5] = {0};
// 逐位读取...
taskEXIT_CRITICAL();
// 一维卡尔曼滤波平滑
kalman1d_update(&kf, value); // Q=0.01, R=4.0
BH1750 光照(软件I2C + 卡尔曼)
c
// 软件模拟 I2C
MY_IIC_Start();
MY_IIC_Send_Byte(BH1750_ADDR);
// 读取16位光照值
// 卡尔曼滤波平滑 Lux
kalman1d_update(&kf, (float)lux);
MPU6050 六轴姿态
c
MPU6050_Init(); // I2C1 (PB10/PB11), 100kHz
MPU_Set_Rate(100); // 100Hz采样率, 25Hz低通
// 循环读取 (100ms)
MPU_Get_Accelerometer(&ax, &ay, &az);
MPU6050_Get_Angle(&x, &y, &z, 1); // 加速度计计算欧拉角
// 中值滤波 (窗口7) 平滑角度
median_update(&mf, angle);
HMI_send_to_slider("X.val", angle);
滤波算法
系统集成了多种信号滤波方法:
| 方法 | 文件 | 用途 |
|---|---|---|
| 卡尔曼滤波 | Utils/src/kalman1d.c | DHT11温度、BH1750光照 |
| 中值滤波 | Utils/src/median_filter.c | MPU6050角度(窗口=7) |
| 移动平均 | 超声波驱动内 | HC-SR04测距(10次均值) |
c
// 一维卡尔曼滤波
typedef struct {
float Q; // 过程噪声
float R; // 测量噪声
float x; // 状态估计
float p; // 估计误差协方差
} Kalman1D;
float kalman1d_update(Kalman1D *kf, float z) {
// 预测
kf->p += kf->Q;
// 更新
float k = kf->p / (kf->p + kf->R);
kf->x += k * (z - kf->x);
kf->p *= (1 - k);
return kf->x;
}
WS2812B RGB LED
单颗灯珠 (GRB 格式),PD12 数据引脚,DWT 精确微秒时序:
c
// 预设颜色闪烁模式
WS2812_BlinkPresetsStart(200); // 200ms 步进,循环预设颜色
// 无极变色模式 (HSV彩虹循环)
WS2812_SmoothStart(60); // 60ms 步进
// 按键2切换模式
if (mode == PRESET) {
WS2812_SmoothStop();
WS2812_BlinkPresetsStart(200);
} else {
WS2812_BlinkPresetsStop();
WS2812_SmoothStart(60);
}
蜂鸣器音乐播放器
独立任务播放谱面数组,支持多曲切换、暂停和提示音:
c
// 谱面数组示例
const uint8_t custom_music[] = { M1,4, M2,4, M3,4, ... };
// 曲目管理
static const uint8_t *s_tracks[] = { custom_music, song2, song3 };
static const uint16_t s_track_sizes[] = {
sizeof(custom_music), sizeof(song2), sizeof(song3)
};
// 控制接口
buzzer_player_start(); // 开始播放
buzzer_player_next(); // 下一曲
buzzer_player_toggle_pause(); // 暂停/继续
buzzer_player_triple_beep_and_stop(); // 三响提示
配套 Windows 端音乐编辑工具(music_editor.py),支持可视化编辑谱面并导出 .cfrag C 数组片段。
Utils 工具库
| 模块 | 功能 |
|---|---|
kalman1d.c | 一维卡尔曼滤波 |
median_filter.c | 窗口中值滤波 (最大窗口9) |
gpio_utils.c | GPIO/PWM统一封装,支持逻辑引脚映射 |
button_events.c | FreeRTOS Tick 按键事件(单击/双击/长按) |
c
// GPIO/PWM 一行初始化
GPIOU_register_pwm_pin("servo", GPIOA, GPIO_PIN_0, TIM4, TIMER_CH_0, AF2);
GPIOU_pwm_setup("servo", 50.0f); // 50Hz
GPIOU_pwm_set_duty("servo", 7.5f); // 1.5ms 中位
// 按键事件
ButtonEvent evt = button_update(&btn);
if (evt == BUTTON_EVENT_SINGLE) { /* 单击 */ }
if (evt == BUTTON_EVENT_DOUBLE) { /* 双击 */ }
if (evt == BUTTON_EVENT_LONG) { /* 长按 */ }
系统启动流程
c
int main(void) {
// 1. 初始化 DWT + SysTick (ms/us延时)
systick_config();
// 2. 读取并缓存时钟频率
uint32_t sysclk = SystemCoreClock;
// 3. 初始化调试串口 (USART0, 115200, printf重定向)
system_monitor_init();
// 4. 创建 HMI 串口任务
hmi_task_create();
// 5. 启动调度器
vTaskStartScheduler();
// 不会执行到这里
while(1);
}
项目结构
code
GD32andFREERTOS/
├── BSP/ # 板级支持包
│ ├── beep/ # 蜂鸣器
│ ├── exti/ # 外部中断
│ ├── iic/ # I2C
│ ├── key/ # 按键驱动
│ ├── led/ # LED驱动
│ ├── oled/ # OLED驱动
│ ├── rs485/ # RS485
│ ├── timer/ # 定时器
│ └── ultrasonic/ # 超声波驱动
├── Firmware/ # GD32固件库
│ ├── CMSIS/GD/
│ ├── GD32F4xx_std_peripheral/
│ └── GD32F4xx_usb_library/
├── FreeRTOS/ # FreeRTOS内核
│ ├── inc/ # 头文件
│ ├── src/ # 源码
│ └── port/ # Cortex-M4F 移植
├── Modules/ # 业务模块
│ ├── inc/ # 头文件
│ └── src/ # 任务实现 + 驱动
├── Utils/ # 工具库
│ ├── inc/
│ └── src/
├── USER/ # 入口 + 中断
│ ├── main.c # 系统入口
│ └── gd32f4xx_it.c # 中断服务
├── Project/ # Keil 工程
│ └── TEST.uvprojx # Keil MDK v5 工程
├── 文档/ # 技术文档
└── 比赛用到的脚本/ # Python 工具
├── music_editor.py # 音乐编辑器
└── pin_configurator.py # 引脚配置工具
开发环境
| 工具 | 版本 |
|---|---|
| IDE | Keil MDK-ARM v5 |
| 编译器 | ARMCC v5.06 |
| 调试器 | ST-Link |
| Flash | 512KB (0x08000000) |
| SRAM | 128KB (0x20000000) |
总结
这是一个完整的嵌入式系统项目,核心技术的体现:
- 多任务调度:16个任务抢占式运行,三级优先级分级
- 自定义通信协议:二进制帧 + ASCII帧,ISR安全队列传递
- 多传感器融合:DHT11/BH1750/DS18B20/HX711/MPU6050/RC522 + 烟雾/酒精/超声/PIR
- 多滤波算法:卡尔曼(Q/R可调)、中值滤波、移动平均
- 外设全覆盖:GPIO/I2C/SPI/ADC/UART/PWM/EXTI/TIMER/单总线
- Python工具链:音乐编辑器、引脚配置可视化工具
- 竞赛获奖:海南省嵌入式开发赛道二等奖和三等奖
评论 (0)