第四章 硬件接口与通信协议:Bootloader的通信基石
做Bootloader,说白了就是让芯片在启动时能跟外界说上话。你得通过某种方式把固件数据灌进去,还得保证不出错。UART、I2C、SPI,这三兄弟是嵌入式世界最常用的接口。今天我们就来聊聊它们怎么用在Bootloader里。
4.1 UART通信基础
UART,通用异步收发器。我最早接触STM32就是从UART开始的,那时候觉得这东西真简单——就两根线,TX和RX,一收一发,完事。
但简单归简单,坑也不少。UART是异步的,没有时钟线,全靠双方约定好波特率。你设115200,我设9600,那收到的数据就是一堆乱码。我在项目中遇到过好几次这种低级错误,排查了半天才发现是波特率没对上。
- 波特率:115200 bps(兼顾速度和稳定性)
- 数据位:8位
- 停止位:1位
- 校验位:无
- 流控:无
为什么选115200?因为它是常用波特率里比较快的一个,而且大多数USB转串口芯片都支持得很好。你想想看,如果Bootloader用921600,虽然快,但线稍微长一点或者干扰大一点,就容易丢包。Bootloader升级这种事,稳比快重要。
UART的优点是简单、通用、调试方便。几乎每个STM32芯片都有UART,你随便找个串口工具就能跟它通信。缺点也很明显——速度上限不高,而且只能点对点,不能挂多个设备。
4.2 I2C与SPI协议对比
I2C和SPI都是同步串行协议,都有时钟线。但它们的性格完全不同。
| 特性 | I2C | SPI |
|---|---|---|
| 信号线数量 | 2根(SCL, SDA) | 4根(SCK, MOSI, MISO, CS) |
| 通信方式 | 半双工 | 全双工 |
| 速率 | 标准100kbps,快速400kbps | 可达数十Mbps |
| 设备寻址 | 7位或10位地址 | 片选信号(CS) |
| 总线拓扑 | 多主多从 | 一主多从 |
| 硬件复杂度 | 较低(开漏输出,需上拉电阻) | 中等(推挽输出) |
| 抗干扰能力 | 一般 | 较好 |
I2C的优势在于线少,两根线就能挂一堆设备。但它的协议比较复杂,有起始条件、停止条件、应答机制,软件模拟起来挺麻烦的。我记得有一次用GPIO模拟I2C读传感器,时序怎么调都不对,最后发现是上拉电阻阻值选大了,信号上升沿太慢。
SPI就粗暴多了——时钟一拉,数据就往外蹦。全双工意味着你可以同时收发,效率高。但线多,而且每个从设备都要一根独立的片选线。如果板子上挂了8个SPI设备,光片选就占8个GPIO。
4.3 在Bootloader中选择通信接口的考量
选哪个接口做Bootloader的升级通道?这不是拍脑袋决定的。我总结了几条原则:
- 硬件资源占用——这个芯片还剩多少引脚?UART最少只要2个引脚(TX/RX),I2C也是2个,SPI至少4个。如果引脚紧张,UART或I2C更合适。
- 升级速度要求——固件有多大?如果只有几十KB,UART的115200bps完全够用。如果固件有1MB以上,SPI能省下不少时间。
- 可靠性需求——升级过程中断一次,板子可能就变砖了。UART没有硬件流控,数据容易丢失。SPI有独立的时钟线,时序更可控。
- 调试便利性——开发阶段哪个接口最容易接出来?UART一根USB转串口线就能搞定,SPI和I2C通常需要逻辑分析仪。
- 量产一致性——生产线上用什么工具烧录?如果产线已经标配了UART烧录器,就别为了追求速度改成SPI。
下面这张图总结了三种接口在Bootloader场景下的选择逻辑:
4.4 实际项目中的选择策略
说了这么多理论,来点实际的。我做过几个不同产品的Bootloader,选择策略大致如下:
- 消费类产品(智能家居、小家电):用UART。成本敏感,MCU引脚少,而且产线烧录工具基本都是UART接口。固件一般不超过256KB,115200bps够用。
- 工业控制设备:用SPI。环境干扰大,UART容易丢数据。SPI有独立时钟,抗干扰能力强。而且工业设备通常有外部Flash存参数,SPI正好复用。
- 传感器节点:用I2C。节点上挂了一堆传感器,I2C总线可以共用。Bootloader升级频率低,速度慢点无所谓。
- 汽车电子:用CAN。嗯,这个不在本章讨论范围,但提一句——汽车上UART、I2C、SPI都不靠谱,CAN才是王道。
嗯,接口选型这事,没有标准答案。每个项目都有自己的约束条件。你只要记住:Bootloader的通信接口,不是选最快的,也不是选最省引脚的,而是选最不容易出错的。因为一旦Bootloader跑飞了,你的板子就真的变砖了。