p1 ~ p8(约 77 分钟)
这门课在讲什么
全名《FreeRTOS 快速入门与工程实践》,百问网出品,分两部分:
快速入门 API 怎么用——怎么创建任务、怎么用队列工程实践 先摆出场景和问题,再讲用 FreeRTOS 的哪个功能去解决第二部分才是主线。整门课写了 30 多个程序,但它们不是 30 个独立例子,而是三个项目被反复改进的结果:音乐播放、打砖块、汽车游戏。打砖块是核心,最终框架会用到队列、信号量、互斥量、事件组;全课就是一步步提问题、一步步改代码,最后把这个框架搭出来。后两个游戏来自开源项目 nWatch。
讲法上有个特点:理论部分不念 PPT,用绘图板现场画图;实践部分先讲思路,再从第一条指令开始现场写、现场调试,不给现成代码。模块驱动只讲接口怎么调,不讲内部实现——重点是 RTOS,不是 HAL 库开发。
硬件平台
中间是一块 STM32F103C8T6 核心板,外面套一块黑色 12 边形底板,模块都插在底板上,配 ST-Link 下载器。软件是 STM32CubeMX + Keil。
板上的资源大致这几类:
| 类别 | 器件 | 用到哪 |
|---|---|---|
| 显示 | OLED(I2C1,PB6/PB7) | 数字、菜单、游戏画面 |
| 输入 | 红外接收头、旋转编码器、按键 | 游戏手柄 |
| 感知 | 姿态传感器 | 摇晃控制、姿态控制 |
| 输出 | LED(PC13)、无源蜂鸣器、全彩 LED、直流电机 | 状态提示、音乐、动作 |
两个配置上的取舍:
Debug 接口选 SWD,不选 JTAG。 JTAG 会占掉很多引脚,换 SWD 能省出 3 条,底板上正好用它们控制全彩 LED 或直流电机。
时基选 TIM4。 因为 TIM1、TIM2、TIM3 都被模块占用了。
三个项目
音乐播放是第 9 个程序,接无源蜂鸣器,按三角符号播放或停止。
打砖块是核心。挡板可以用三种方式控制:摇晃板子、红外遥控器、旋转编码器。球碰到边缘会发声。
汽车游戏是第 17 个程序,遥控器上 1/2/3 键控制。
自己建一个 FreeRTOS 工程
配套模板能直接用,自己从零建只是给想折腾的人。步骤记下来是因为坑都藏在细节里。
CubeMX 里:
① 新建工程,选 STM32F103C8T6(列表里有两个相近型号,选第一个)② 时钟源使能 HSE 外部晶振;System Core → Debug 选 SWD;时基选 TIM4③ 时钟树填 72,回车④ Middleware → FreeRTOS,接口选 CMSIS_V2 其余保持默认:可抢占开着、tick 频率 1000、heap_4、堆大小默认(3072 字节)⑤ 启动后默认已有一个 defaultTask,名字、栈、优先级都保持默认⑥ Project Manager:工程名 01_FreeRTOS_my,IDE 选 MDK-ARM Code Generator 勾上「把用到的库拷贝进工程」⑦ 生成 → 编译 → 下载第 ④ 步选的是 CMSIS_V2,所以生成出来的是 MX_FREERTOS_Init() + osKernelStart() 和默认任务 defaultTask,不是裸的 xTaskCreate。
第 ⑦ 步下载完什么都不会发生——工程里还没有任何操作硬件的代码,这是正常的。
加 LED 和 OLED
LED 在 PC13。CubeMX 里配成 GPIO_Output、推挽输出、不用内部上下拉,生成后 MX_GPIO_Init 里已经配好了。
驱动文件从模板复制:
driver_led 两个文件,放到工程 driver/ 目录driver_timer driver_led 里用了延时,要一起加工程里新建 group(F2 改名 DShanMCU-F103),把文件加进去。编译报「找不到头文件」就去 Options → C/C++ → Include Paths 加上头文件目录。
然后在 defaultTask 里 #include "driver_led.h",在 USER CODE BEGIN 区调 led_test()。
OLED 走 I2C1、PB6/PB7。重新打开 CubeMX 的办法是双击工程里的 .ioc 文件,把 I2C1 使能,引脚会自动选上,参数保持默认。
驱动要复制三样:driver_oled、driver_lcd,还有字库文件。driver_lcd.c 只是对具体屏幕的封装,以后换屏只改它,上层统一用 driver_lcd.h 的函数。字库被其他文件包含,不需要在工程里手动添加;编译会有一堆警告,能用。
通用流程就四步:CubeMX 加配置 → 拷代码到工程 → 工程里添加文件 → 调用它的测试函数。
Reset and Run 这个坑
第一次烧写 LED 程序后灯不闪。不是程序错,是 Flash Download 里的 Reset and Run 被取消了,芯片下载完没自动复位运行。重新上电就正常。
麻烦的是:每次重新生成代码,这个勾选都会掉一次,要重新去 Debug → Settings → Flash Download 里勾上。不知道这件事,很容易把「没反应」当成程序写错了。
坑
- 模块驱动不能拿来直接用。以 OLED 为例,驱动内部发命令实际是调 I2C1 控制器的发送函数,所以必须先让 CubeMX 把 I2C1 和引脚初始化好。
- 每次重新生成代码后 Reset and Run 会掉,烧写后没反应先查这里。
- 工程放在中文目录里,Keil 退出调试时会报错,挪到非中文路径就好。
MX_FREERTOS_Init()里的 defaultTask 不是摆设,后面第二个任务是在它之外手动建的,别顺手删掉。
请输入编辑凭据,只有站点所有者可以修改文章。