使用 FreeRTOS 实现简单多任务调度(初识 RTOS)
🚦使用 FreeRTOS 实现简单多任务调度(初识 RTOS)
“裸机是手动挡,RTOS是自动挡。程序员也要学会偷懒!”
——《从延时到调度:嵌入式人的进阶之路》
🧠 一、什么是 RTOS?为啥你迟早会用上它?
RTOS,全名 Real-Time Operating System(实时操作系统)。
简单理解,它是为 MCU 打工的“调度大脑”,能帮你搞定这些烦人的事:
- 多个任务如何“分时共享 CPU”
- 谁先执行谁后执行
- 哪个任务被中断了怎么回来
- 延时不靠
HAL_Delay()
,而是靠“时间片” - ……
你说你裸机写得也挺好?
当你项目越来越复杂,一手管理 3 个传感器 + OLED + 蓝牙 + ADC + 一堆中断后,你会感叹:“RTOS,它不香吗?”
🏗️ 二、FreeRTOS 是啥?能干嘛?
FreeRTOS 是一个轻量级、开源、适用于嵌入式设备的 RTOS。它小到能塞进几 KB 的 Flash,大到能跑在 Cortex-M33 的 MCU 上。
它能做什么?
能力 | 说明 |
---|---|
任务管理 | 你写的任务能自动轮流运行(任务调度) |
延时控制 | 再也不用 while(1) 和 HAL_Delay() |
队列通信 | 多个任务之间可以“发消息” |
互斥量 | 防止多个任务抢一个资源打架 |
中断支持 | 和 ISR 合作,能即时响应硬件事件 |
🧪 三、我们来写一个:两个任务轮流打印信息
场景设定
我们用两个任务,一个负责打印 “任务1运行中”,另一个打印 “任务2运行中”,每个任务运行后都延时 1 秒钟。
🛠️ 四、搭建 FreeRTOS 工程(以 STM32 为例)
- 打开 STM32CubeMX
- 选择芯片或开发板,如 STM32F103C8T6
- 开启 SYS > Timebase Source 为 “SysTick”
- Middleware 中勾选 FreeRTOS
- 配置两个任务 Task1 和 Task2
- 生成工程并打开 Keil / STM32CubeIDE
📦 五、FreeRTOS 示例代码
#include "cmsis_os.h"
#include "stdio.h"// 任务句柄
osThreadId_t Task1Handle;
osThreadId_t Task2Handle;// 任务1函数
void Task1(void *argument)
{for(;;){printf("任务1运行中\r\n");osDelay(1000); // 延时1秒}
}// 任务2函数
void Task2(void *argument)
{for(;;){printf("任务2运行中\r\n");osDelay(1000); // 延时1秒}
}int main(void)
{HAL_Init();SystemClock_Config();MX_USART2_UART_Init(); // 你用哪个串口就初始化哪个// 创建任务const osThreadAttr_t task1_attr = {.name = "Task1",.priority = (osPriority_t) osPriorityNormal,.stack_size = 128 * 4};Task1Handle = osThreadNew(Task1, NULL, &task1_attr);const osThreadAttr_t task2_attr = {.name = "Task2",.priority = (osPriority_t) osPriorityNormal,.stack_size = 128 * 4};Task2Handle = osThreadNew(Task2, NULL, &task2_attr);// 启动调度器osKernelInitialize();osKernelStart();while (1){// 永远不会执行到这里}
}
🔍 六、代码解析
osThreadNew()
:创建一个任务,传入函数和属性osDelay(ms)
:让当前任务“睡一觉”,让别人有机会运行osKernelStart()
:启动 RTOS 的调度器,之后就进入任务世界啦- 多个任务根据优先级和时间片轮流运行,实现并发
🧯 七、常见问题
问题 | 原因 | 解决方式 |
---|---|---|
程序卡在 while(1) 不执行任务 | 没调用 osKernelStart() | 加上它! |
任务运行顺序不一致 | 优先级或调度抢占机制影响 | 调整 priority 或加调试日志 |
串口不打印 | 没初始化串口或 printf 重定向没做好 | 检查 HAL_UART_Init 与重定向 |
🎨 八、初学者的小贴士
- 每个任务用死循环
for(;;)
是套路 - 延时用
osDelay()
替代HAL_Delay()
- 任务不能太占 CPU,可以
osDelay(1)
礼貌让位 - 不要滥用全局变量,多用队列或信号量通信
📚 九、FreeRTOS 术语小科普(别被吓住)
术语 | 中文 | 初学者理解 |
---|---|---|
Task | 任务 | 一个功能单位 |
Tick | 时钟节拍 | RTOS内部的时间粒度 |
Scheduler | 调度器 | 决定谁先运行 |
Priority | 优先级 | 谁更重要谁先上 |
Delay | 延时 | 任务主动让出 CPU |
Mutex/Semaphore | 互斥量/信号量 | 防止资源抢占、任务同步 |
✅ 十、总结一句话
FreeRTOS 就像是给你的 MCU 安了个“多线程操作系统”,让它不再只是一个死循环。
只需几行代码,你就可以轻松实现多个功能并发运行,代码结构更清晰,扩展性更强!
📥 点个赞收藏这篇“RTOS第一课”,学会 FreeRTOS,打开嵌入式开发新大门!
💬 评论区欢迎分享你用 RTOS 踩过的坑,或你想实现的小项目,我来教你用 RTOS 玩起来!