2. 嵌入式系统基础
做嵌入式开发,选对硬件平台和搭好开发环境,是后面所有工作的基础。这一章我带你过一遍主流MCU选型、IDE配置和调试工具的使用。这些内容看起来琐碎,但直接影响你后续的开发效率。
2.1 主流MCU选型:STM32 vs GD32
先聊聊芯片选型。目前市面上最常用的就是STM32和GD32这两大系列。很多人问我到底选哪个?我的回答是:看项目需求。
| 对比维度 | STM32(ST) | GD32(兆易创新) |
|---|---|---|
| 内核 | Cortex-M0/M3/M4/M7 | Cortex-M3/M4/M23/M33 |
| 主频 | 最高 480MHz(H7系列) | 最高 200MHz(GD32F5系列) |
| 价格 | 较高,供货波动大 | 便宜 30%~50%,供货稳定 |
| 生态 | 极其完善,资料丰富 | 兼容STM32,但资料略少 |
| DMA通道数 | 2~16个(视型号) | 2~14个(视型号) |
| 中断优先级 | 16级可编程 | 16级可编程 |
我的建议:如果是做产品量产,成本敏感就用GD32;如果是做原型验证或学习,STM32的生态会让你少踩很多坑。我个人习惯在项目初期先用STM32开发,后期再根据成本评估是否切换到GD32。
2.2 IDE配置:Keil vs IAR
IDE的选择其实是个老话题。Keil MDK和IAR Embedded Workbench各有千秋。我两个都用过,说说我的感受。
2.2.1 Keil MDK配置要点
Keil的界面更友好,上手快。但要注意几个关键配置:
- 芯片选择:在Device选项卡里选对具体型号,比如STM32F407VG
- Flash烧录算法:在Utilities选项卡里添加对应的Flash算法文件
- 调试器设置:在Debug选项卡里选择J-Link或ST-Link
- 优化等级:调试阶段用-O0,发布阶段用-O2或-Os
小技巧:Keil的工程文件(.uvprojx)是XML格式的,有时候配置乱了可以直接用文本编辑器打开修改。我曾经遇到过工程文件损坏,用这个方法救回来了。
2.2.2 IAR配置要点
IAR的编译器优化做得更好,生成的代码体积更小。配置时注意:
- 芯片选择:在General Options里选对器件
- 链接脚本:IAR使用.icf文件,需要根据芯片Flash和RAM大小调整
- 调试器:在Debugger选项卡里选择驱动
- C-Runtime:建议关闭semihosting,否则调试会卡死
避坑指南:我曾经在IAR里忘记关闭semihosting,结果程序一跑就卡在printf函数里。排查了半天才发现是这个问题。所以,嵌入式开发里printf不是随便用的。
2.3 调试工具:J-Link vs ST-Link
调试工具是开发者的眼睛。选对了,调试效率翻倍。
| 特性 | J-Link(SEGGER) | ST-Link(ST) |
|---|---|---|
| 速度 | 最高 50MHz SWO | 最高 4MHz SWO |
| 断点数量 | 无限(硬件+软件) | 6个硬件断点 |
| RTT支持 | 原生支持 | 不支持 |
| 价格 | 较贵(正版) | 便宜(开发板自带) |
| 适用场景 | 复杂调试、性能分析 | 日常开发、简单调试 |
我个人习惯:调试DMA和中断协同这类复杂逻辑时,一定用J-Link。它的RTT功能可以实时输出日志,比串口打印方便太多。
2.4 开发环境搭建流程图
下面这张图展示了从选型到调试的完整流程:
2.5 实战:搭建一个最小工程
说了这么多理论,我们来动手搭一个最小工程。以STM32F407VG + Keil MDK为例:
// 1. 新建工程,选择芯片 STM32F407VG
// 2. 添加启动文件 startup_stm32f40xx.s
// 3. 添加系统时钟配置 system_stm32f4xx.c
// 4. 编写主函数 main.c
#include "stm32f4xx.h"
int main(void) {
// 使能GPIO时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
// 配置PD12为推挽输出
GPIOD->MODER |= GPIO_MODER_MODER12_0;
while(1) {
// 点亮LED
GPIOD->BSRR = GPIO_BSRR_BS_12;
delay(1000000);
// 熄灭LED
GPIOD->BSRR = GPIO_BSRR_BR_12;
delay(1000000);
}
}
调试技巧:第一次下载程序时,记得检查BOOT0和BOOT1的电平设置。我遇到过好几次因为BOOT引脚配置不对,导致程序下载成功但跑不起来的情况。
2.6 常见问题与解决方案
- 下载失败:检查SWD接线,确保SWDIO、SWCLK、GND三根线都接好
- 调试器识别不到:更新驱动,或者换个USB口试试
- 程序跑飞:检查中断向量表是否配置正确,堆栈大小是否足够
- 优化后功能异常:降低优化等级,或者用volatile修饰关键变量