2. STM32CubeMX 基础与 AI 项目创建
好,咱们正式开始动手。这一章我会带你走一遍 CubeMX 的完整流程——从新建项目、配时钟、点个灯,到把 X-CUBE-AI 软件包加进来,最后生成能跑的代码。
别小看这些基础操作。我见过不少工程师,AI 模型都训好了,结果卡在工程配置上,时钟配错了,外设没使能,折腾一整天。说白了,地基没打牢,楼盖得再高也得塌。
2.1 新建项目——选对芯片是第一步
打开 CubeMX,点 "New Project"。这时候你会看到芯片选择界面。我个人习惯直接搜型号,比如我们课程用的 STM32L4 系列,低功耗 AI 部署的首选。
为什么选 L4?你看这个表:
| 特性 | STM32L4 | STM32F4 | STM32H7 |
|---|---|---|---|
| 运行功耗 | 极低(~100 µA/MHz) | 中等(~200 µA/MHz) | 较高(~300 µA/MHz) |
| AI 加速 | 可选(STM32L4+ 系列) | 无 | 有(但功耗高) |
| 典型应用 | 电池供电 AI 推理 | 通用控制 | 高性能边缘计算 |
选好芯片后,点 "Start Project"。嗯,这里要注意:项目命名不要用中文,路径不要有空格。我曾经有个同事,项目名叫 "AI_部署_测试",结果编译报错找了一下午,最后发现是路径里的中文搞的鬼。
2.2 配置时钟树——别让 AI 饿着跑
时钟树是 STM32 的灵魂。点开 "Clock Configuration" 标签页,你会看到一张复杂的图。别慌,我们只关心几个关键点:
- HSE(外部高速晶振):我建议用 8 MHz 或 16 MHz,精度高,适合 AI 推理的时序要求。
- PLL 倍频:把 HSE 倍频到芯片最高主频。比如 L4 系列最高 80 MHz,那就设 PLL 输出 80 MHz。
- SYSCLK(系统时钟):直接选 PLLCLK,让 CPU 跑满。
- APB1/APB2 分频:外设总线别分太多,否则 AI 推理时外设响应慢。
配好时钟后,CubeMX 会自动计算各总线频率。检查一下有没有红色警告——有的话说明某个外设时钟超限了,需要调整分频系数。
2.3 配置 GPIO——点个灯,确认工程活着
GPIO 配置很简单,但很重要。我习惯先配一个 LED 引脚,用来指示系统状态。比如 AI 推理完成时闪一下,或者低功耗模式下灭掉。
操作步骤:
- 在 "Pinout & Configuration" 标签页,找到你要用的 GPIO 引脚。
- 右键选择 "GPIO_Output"。
- 在右侧 "GPIO" 配置里,设置输出电平、速度、上下拉。
举个例子,我用 PB13 接 LED:
/* 配置 PB13 为推挽输出,无上下拉,低速 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
2.4 启用 X-CUBE-AI 软件包——AI 部署的钥匙
这一步是关键。X-CUBE-AI 是 ST 官方的 AI 部署工具包,能把训练好的神经网络模型转换成 STM32 能跑的代码。
启用步骤:
- 在 "Software Packs" 标签页,点 "Select Components"。
- 找到 "X-CUBE-AI",勾选 "Core" 和 "Validator"。
- 在 "Pinout & Configuration" 标签页,找到 "X-CUBE-AI" 组件,配置推理引擎参数。
配置界面里有个 "Runtime" 选项,我建议选 "Float32" 或 "Quantized"。Float32 精度高但占内存,Quantized 省内存但精度略降。对于低功耗 AI 部署,我一般选 Quantized,因为内存占用少,推理速度也快。
2.5 生成初始化代码——一键搞定
所有配置完成后,点 "Project" -> "Generate Code"。CubeMX 会生成一个完整的 MDK-ARM 或 IAR 工程,包含所有初始化代码。
生成后的工程结构大概这样:
- Core/:主程序文件,包括 main.c、stm32l4xx_it.c 等。
- Drivers/:HAL 库和外设驱动。
- Middlewares/:X-CUBE-AI 的推理引擎库。
- X-CUBE-AI/:AI 模型转换后的代码(后续章节会用到)。
打开 main.c,你会看到 CubeMX 自动生成的初始化代码:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_X_CUBE_AI_Init();
while (1)
{
/* 用户代码写在这里 */
}
}
嗯,这里要注意:不要手动修改 CubeMX 生成的代码区域。如果你需要加自己的逻辑,写在 "USER CODE BEGIN" 和 "USER CODE END" 之间。否则下次重新生成代码时,你的修改会被覆盖。
2.6 本章知识体系总览
为了让你更直观地理解本章的流程,我画了一张图:
2.7 验证工程——跑起来才算数
代码生成后,打开工程,编译。如果零错误零警告,恭喜你,基础工程搭建成功。如果报错,多半是以下原因:
- X-CUBE-AI 路径没配好:检查工程设置里的头文件路径和库路径。
- 时钟配置冲突:某个外设的时钟超限了,回去调整分频。
- 芯片型号选错:比如选了 L4 但实际用的是 L4+,外设资源不一样。