2. 开发环境搭建:Keil/IAR环境配置、STM32CubeMX生成RTOS工程、工程模板建立
好,咱们正式开始动手了。
这一章,说白了就是“磨刀”。刀磨快了,后面砍柴才不费劲。我见过不少新手,上来就写代码,结果环境配了一整天,最后发现是编译器版本不对,白白浪费时间。所以,咱们先把工具收拾利索。
2.1 编译器选择:Keil 还是 IAR?
这是个老生常谈的问题。我个人习惯用 Keil,因为它的生态在国内太成熟了,遇到问题随便一搜就有答案。但 IAR 的编译优化确实更狠,代码能小一圈。
我的建议是:初学者用 Keil MDK-ARM。为什么?
- 界面友好,上手快
- 调试器(ST-Link/J-Link)支持好
- 网上教程最多,遇到坑好填
如果你以后做产品,追求极致代码密度,再切 IAR 也不迟。我在项目中遇到过用 IAR 编译后,Flash 省了 15% 的情况,但那是后话了。
2.2 Keil 环境配置要点
安装过程我就不啰嗦了,一路 Next 就行。但有几个关键点,你得留意:
- 安装路径不要有中文——这是铁律。我见过有人装在“D:\开发工具\Keil_v5”,结果编译报一堆莫名其妙的错。
- Pack 包要装对。打开 Pack Installer,找到你的芯片型号,比如 STM32F407VG,把对应的 Device Family Pack 装上。
- License 要激活。这个不用我多说了吧?
配置完成后,咱们验证一下。新建一个空工程,随便写个 main 函数,点编译。如果能通过,说明环境没问题。
// 验证代码,就这个意思
int main(void)
{
while(1);
}
嗯,这里要注意:如果编译报错“找不到 core_cm4.h”,那就是 Pack 没装全。回去重新装一下。
2.3 STM32CubeMX 生成 RTOS 工程
这才是今天的重头戏。STM32CubeMX 是个好东西,它能帮我们把 HAL 库、时钟树、外设初始化全部自动生成。咱们要做的,就是告诉它:我要用 FreeRTOS。
操作步骤:
- 打开 CubeMX,新建工程,选你的芯片型号。
- 配置时钟树。我一般先选外部晶振(HSE),然后让软件自动算 PLL 参数。比如 STM32F407,我习惯跑到 168MHz。
- 在 Pinout & Configuration 里,找到 Middleware → FREERTOS,勾选上。
- Interface 选 CMSIS_V2。为什么?因为这是 ARM 官方标准接口,代码可移植性好。
配置完 FreeRTOS 后,CubeMX 会自动生成一个默认的任务。你可以在这里修改任务名、栈大小、优先级。我个人习惯先保留默认配置,等工程跑通了再调。
// CubeMX 生成的默认任务代码片段
void StartDefaultTask(void *argument)
{
for(;;)
{
osDelay(1000);
}
}
你看,就这么简单。一个 RTOS 任务就出来了。
2.4 生成代码并导入 Keil
在 CubeMX 里点 Project → Generate Code,选择你的 IDE 是 MDK-ARM。然后它会生成一个 .uvprojx 文件。
双击打开,你就能看到完整的工程结构了:
- Application/User:你的用户代码放这里
- Middlewares/FreeRTOS:RTOS 源码
- Drivers:HAL 库驱动
我第一次用 CubeMX 生成工程时,看到这么多文件夹有点懵。其实你不用管那么多,只需要关注 main.c 和 freertos.c 这两个文件就行。
/* USER CODE BEGIN */ 和 /* USER CODE END */ 之间写你的代码。这些区域不会被覆盖。
2.5 工程模板建立
好,现在咱们有了一个能跑的 RTOS 工程。但每次新建项目都从头配一遍 CubeMX,太累了。所以,我建议你建立一个工程模板。
我的做法是这样的:
- 把 CubeMX 生成的那个工程文件夹整个复制一份,改名为
Template_STM32F4_FreeRTOS。 - 删掉里面所有
/* USER CODE BEGIN */区域里我写的测试代码,只保留空框架。 - 把
main.c里的默认任务改成通用的AppTaskCreate结构。
以后每开一个新项目,直接复制这个模板文件夹,改个名就能开工。省时省力。
// 模板中的 main.c 框架
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_FREERTOS_Init(); // 初始化 FreeRTOS
osKernelStart(); // 启动内核
while(1)
{
// 正常情况下不会跑到这里
}
}
你看,结构清晰,一目了然。
2.6 验证模板是否可用
模板建好了,得验证一下。我一般会写一个简单的 LED 闪烁任务:
void LedTask(void *argument)
{
for(;;)
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
osDelay(500);
}
}
下载到板子上,如果 LED 以 0.5 秒间隔闪烁,说明环境搭建成功,RTOS 跑起来了。
嗯,这里有个小细节:osDelay 的参数单位是毫秒。500 就是 0.5 秒。别搞错了。
2.7 总结一下
这一章咱们干了三件事:
- 配好了 Keil 编译环境
- 用 CubeMX 生成了带 FreeRTOS 的工程
- 建立了可复用的工程模板
说白了,就是搭了个台子。后面咱们要在这个台子上唱戏——写电力监控系统的各种功能模块。
下一章,咱们开始讲任务管理。到时候我会分享一个我在项目中遇到的优先级反转案例,挺有意思的。