2. STM32CubeMX项目配置:创建基础工程与时钟树配置
说实话,很多初学者拿到开发板第一件事就是写代码。但我个人的习惯是——先花半小时把CubeMX工程配好。你想想看,如果时钟树配错了,后面调试起来简直要命。我在项目中就吃过这个亏,当时一个I2C设备死活不工作,查了两天才发现是时钟分频配错了。
这一章,我们就来把基础工程搭好。包括时钟树、串口调试这些基本功。别嫌简单,基础打牢了,后面做模型移植和推理加速才能稳。
2.1 创建新工程
打开STM32CubeMX,点击"New Project"。在Board Selector里搜索你的板子型号。我用的是STM32H743,主频能跑到480MHz。如果你用F4系列,最高也就180MHz左右。
选好芯片后,点"Start Project"。界面会变成这样:
- 左侧是外设列表(Pinout & Configuration)
- 中间是芯片引脚图
- 右侧是时钟配置(Clock Configuration)
- 下面是项目管理(Project Manager)
嗯,这里要注意:先别急着点生成代码。我们得先把外设和时钟配好。
2.2 配置时钟树——主频200MHz+
时钟树是STM32的命脉。说白了,CPU能跑多快、外设能不能正常工作,全看它。
我一般按这个步骤来:
- 选择时钟源:HSE(外部高速晶振)或HSI(内部RC振荡器)。我建议用HSE,精度高。H7系列通常配25MHz或8MHz晶振。
- 配置PLL:PLL是锁相环,用来倍频。输入频率经过分频→倍频→再分频,得到目标频率。
- 设置系统时钟:把PLL输出接到SYSCLK上。
- 配置AHB/APB分频:给各个总线分配时钟。
关键参数(以STM32H743为例,目标主频400MHz):
- HSE输入:25MHz
- PLL1M(预分频):÷5 → 5MHz
- PLL1N(倍频):×160 → 800MHz
- PLL1P(后分频):÷2 → 400MHz → SYSCLK
- AHB分频:÷1 → 400MHz
- APB1分频:÷2 → 200MHz
- APB2分频:÷2 → 200MHz
为什么这么配?因为H7的PLL输入范围是1-16MHz,所以先÷5降到5MHz。倍频160倍到800MHz,再÷2得到400MHz。这个频率在H7的规格范围内,稳定可靠。
我的经验:别一上来就拉满主频。我曾经把H743配到480MHz,结果跑模型推理时偶尔死机。降到400MHz后稳如老狗。对于模型移植,400MHz完全够用,还能留点余量给散热。
在CubeMX的Clock Configuration界面里,你直接输入目标频率,它会自动帮你算分频系数。但自动算的不一定最优,我建议手动微调一下。
2.3 配置USART串口——调试打印
做嵌入式开发,串口就是你的眼睛。没有串口打印,调试AI模型简直是盲人摸象。
配置步骤:
- 在Pinout & Configuration里,找到Connectivity → USART1(或USART2/3,看你板子)
- Mode选"Asynchronous"(异步模式)
- Parameter Settings里配好波特率:我习惯用115200或921600
- 数据位8、停止位1、无校验——这是标准配置
- 看引脚分配:TX和RX会自动分配到默认引脚。如果冲突,手动改一下
注意:串口的TX/RX引脚不能和别的外设冲突。比如H743的USART1默认在PA9/PA10,但如果你的板子把这两个引脚接给了别的器件,就得换到USART2或3。我在项目里就遇到过,板子设计把PA9接了LED,结果串口和LED打架。
配好之后,记得在NVIC Settings里使能USART1全局中断。虽然轮询也能用,但中断方式更高效,不影响模型推理的实时性。
2.4 项目管理与代码生成
切到Project Manager标签页:
- Project Name:起个有意义的名字,比如"STM32H743_AI_Inference"
- Project Location:选个路径,别放桌面
- Toolchain / IDE:选MDK-ARM V5或STM32CubeIDE
- Minimum Heap Size:建议设大一点,模型推理需要动态内存。我一般设0x2000(8KB)以上
- Minimum Stack Size:0x1000(4KB)起步
点"GENERATE CODE",CubeMX会帮你生成初始化代码。打开工程后,你会看到main.c里已经初始化好了时钟和串口。
2.5 验证——打印"Hello from AI Board"
代码生成后,加几行验证代码:
/* 在main.c的while(1)之前添加 */
#include <stdio.h>
/* 重定向printf到串口 */
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 100);
return ch;
}
/* 在main函数中 */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_USART1_UART_Init();
printf("\r\n====================================\r\n");
printf(" STM32H743 AI Inference Board Ready\r\n");
printf(" System Clock: %lu MHz\r\n", HAL_RCC_GetSysClockFreq() / 1000000);
printf("====================================\r\n");
while(1)
{
/* 你的AI推理代码将写在这里 */
}
}
编译下载,打开串口助手(波特率115200),你应该能看到打印信息。如果看不到,检查:
- 串口线是否接对(TX接RX,RX接TX)
- 波特率是否匹配
- 芯片是否真的跑起来了(用示波器看时钟输出引脚)
2.6 本章知识结构
下面这张图总结了本章的核心流程:
这张图把整个配置流程串起来了。从创建工程开始,到时钟树、串口、项目管理,最后用串口打印验证。每一步都环环相扣。
2.7 常见问题与避坑
| 问题 | 原因 | 解决办法 |
|---|---|---|
| 串口打印乱码 | 波特率不匹配或时钟不准 | 检查串口助手波特率;用示波器测TX引脚波形 |
| 芯片不启动 | 时钟配置超限或PLL锁定失败 | 降低主频;检查HSE晶振是否起振 |
| printf不输出 | 没有重定向fputc | 添加fputc函数;勾选Use MicroLIB |
| 程序跑飞 | 堆栈设置太小 | 增大Heap和Stack;检查是否有数组越界 |
我曾经踩过的坑:有一次配H743的时钟,PLL倍频设了200倍,结果芯片直接不启动。查手册才发现PLL1N最大只能到160倍。所以配时钟前,一定先看芯片参考手册的PLL章节,别凭感觉设。