2、STM32CubeAI基础回顾:CubeMX与CubeAI工作流,支持的模型格式,部署流程快速演示
2.1 为什么还要回顾基础?
说实话,很多同学一上来就问我剪枝、量化这些高级话题。但我发现,不少人连CubeMX和CubeAI的基本配合都没搞明白。这就好比你要学跑车改装,结果连方向盘怎么握都不知道——那肯定不行。
我个人习惯,每接手一个新项目,第一件事就是重新捋一遍工具链。别嫌烦,这一步能帮你省下后面80%的调试时间。我记得有一次,一个团队折腾了两周模型部署不上,最后发现是CubeMX的时钟配置错了——嗯,这种低级错误,咱们尽量避免。
2.2 CubeMX与CubeAI:一对黄金搭档
说白了,CubeMX负责硬件初始化,CubeAI负责AI推理引擎。它们俩的关系,就像发动机和变速箱——必须匹配好才能跑起来。
2.2.1 CubeMX的工作流
你打开CubeMX,第一件事就是选芯片。我建议你直接搜STM32H743或者STM32F769这类带硬件加速的型号。选好后,配置时钟、外设、内存——这些是AI推理的基础设施。
举个例子,如果你要用摄像头做图像识别,那DCMI接口、DMA、FMC都得配好。我曾经在项目里漏配了DMA,结果模型跑起来卡得像幻灯片——后来才发现,数据搬运全靠CPU硬扛,那肯定不行。
关键点:CubeMX生成的初始化代码,是CubeAI推理引擎的「地基」。地基不稳,上面盖什么都白搭。
2.2.2 CubeAI的工作流
CubeAI更像一个「模型翻译官」。它把你训练好的模型(比如TensorFlow的.h5文件)转成STM32能理解的C代码。流程大致是这样:
- 导入模型:支持Keras、TensorFlow Lite、ONNX等格式
- 分析模型:自动检查算子兼容性,告诉你哪些层不支持
- 优化配置:选择量化方式(8位还是16位),分配内存池
- 生成代码:输出一个包含网络结构和权重的C文件
- 集成到CubeMX:把生成的代码塞进你的工程里
你想想看,如果没有CubeAI,你要手写这些推理代码——那得写到猴年马月去?
2.3 支持的模型格式:别选错了
很多新手在这里翻车。CubeAI不是所有模型格式都吃,它有自己的「口味偏好」。我整理了一张表,你直接照着看:
| 模型格式 | 支持版本 | 注意事项 |
|---|---|---|
| Keras (.h5) | TensorFlow 2.x | 最推荐,兼容性最好 |
| TensorFlow Lite (.tflite) | 2.x | 量化模型首选,体积小 |
| ONNX | 1.7+ | 跨框架迁移时用,但算子支持有限 |
| PyTorch (通过ONNX) | 间接支持 | 先转ONNX再导入,注意算子映射 |
我的建议:如果你刚开始接触,直接用Keras的.h5格式。我在项目里试过ONNX转过来的模型,有些自定义算子会报错——排查起来特别头疼。
2.4 部署流程快速演示:5分钟跑通一个例子
光说不练假把式。咱们快速走一遍部署流程,你跟着做就行。
2.4.1 准备模型
假设你有一个训练好的手写数字识别模型(MNIST),文件名叫mnist_model.h5。打开CubeAI,点击「Import Model」,选这个文件。
# 如果你还没有模型,可以用这个简单代码生成一个
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten
model = Sequential([
Flatten(input_shape=(28, 28, 1)),
Dense(128, activation='relu'),
Dense(10, activation='softmax')
])
model.save('mnist_model.h5')
2.4.2 分析并优化
导入后,CubeAI会显示模型结构。你注意看右边面板的「Memory Estimation」——它会告诉你模型占多少RAM和Flash。如果超标,就得考虑剪枝或量化了。
我一般先选「8-bit Quantization」,这样模型体积能缩小4倍,推理速度也快不少。但要注意,精度可能会掉1-2个百分点——这就是咱们后面要讲的「精度平衡」问题。
2.4.3 生成代码并集成
点击「Generate Code」,CubeAI会生成一个network.c和network.h。然后你打开CubeMX,在「Software Packs」里勾选CubeAI组件,把这两个文件加进去。
注意:生成代码后,记得检查一下main.c里的初始化顺序。我曾经遇到过CubeAI初始化在CubeMX之前,结果模型加载失败——因为内存还没配好呢。
2.4.4 调用推理接口
在代码里调用推理,其实就三步:
// 1. 初始化AI模型
ai_handle handle = AI_HANDLE_NULL;
ai_mnist_model_create(&handle, NULL);
// 2. 准备输入数据(比如摄像头采集的图像)
ai_i8 input_data[784]; // 28x28=784个像素
// ... 填充数据 ...
// 3. 运行推理
ai_mnist_model_run(handle, input_data, output_data);
// 4. 获取结果
// output_data[0] 就是预测的数字
你看,核心代码就这么几行。但实际项目中,数据采集、预处理、后处理往往比推理本身还复杂。比如图像要归一化到0-1之间,输出要解析成类别标签——这些细节,咱们后面章节会细讲。
2.5 快速验证:跑通第一个Demo
代码写完后,编译下载到开发板。打开串口助手,你应该能看到类似这样的输出:
AI Inference Started...
Input: [0.1, 0.2, ..., 0.8]
Output: [0.01, 0.02, ..., 0.85]
Predicted Class: 7
Confidence: 85.3%
如果看到这个,恭喜你——部署成功了!如果没看到,别慌。先检查串口波特率对不对,再确认CubeAI初始化有没有报错。我遇到过最奇葩的问题,是开发板的USB线供电不足,导致推理到一半就重启了——换个带屏蔽的USB线就好了。
总结一下:CubeMX配硬件,CubeAI配模型,两者结合就能在STM32上跑AI了。但这才刚开始——模型剪枝、量化、精度平衡,才是真正让你「从能跑到跑得好」的关键。下一章,咱们就正式进入剪枝的世界。
嗯,基础回顾就到这里。你如果手边有开发板,建议现在就跟着走一遍流程。纸上得来终觉浅,绝知此事要躬行——这话放在嵌入式AI里,再合适不过了。