第四章 硬件接口与通信协议:Bootloader的通信基石

做Bootloader,说白了就是让芯片在启动时能跟外界说上话。你得通过某种方式把固件数据灌进去,还得保证不出错。UART、I2C、SPI,这三兄弟是嵌入式世界最常用的接口。今天我们就来聊聊它们怎么用在Bootloader里。

4.1 UART通信基础

UART,通用异步收发器。我最早接触STM32就是从UART开始的,那时候觉得这东西真简单——就两根线,TX和RX,一收一发,完事。

但简单归简单,坑也不少。UART是异步的,没有时钟线,全靠双方约定好波特率。你设115200,我设9600,那收到的数据就是一堆乱码。我在项目中遇到过好几次这种低级错误,排查了半天才发现是波特率没对上。

UART在Bootloader中的典型配置:
  • 波特率: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。

我的个人习惯: 如果Bootloader只需要跟一个外部Flash通信,我首选SPI。速度快,协议简单,不容易出幺蛾子。如果是要跟多个传感器或小容量存储设备通信,I2C更省引脚。

4.3 在Bootloader中选择通信接口的考量

选哪个接口做Bootloader的升级通道?这不是拍脑袋决定的。我总结了几条原则:

  1. 硬件资源占用——这个芯片还剩多少引脚?UART最少只要2个引脚(TX/RX),I2C也是2个,SPI至少4个。如果引脚紧张,UART或I2C更合适。
  2. 升级速度要求——固件有多大?如果只有几十KB,UART的115200bps完全够用。如果固件有1MB以上,SPI能省下不少时间。
  3. 可靠性需求——升级过程中断一次,板子可能就变砖了。UART没有硬件流控,数据容易丢失。SPI有独立的时钟线,时序更可控。
  4. 调试便利性——开发阶段哪个接口最容易接出来?UART一根USB转串口线就能搞定,SPI和I2C通常需要逻辑分析仪。
  5. 量产一致性——生产线上用什么工具烧录?如果产线已经标配了UART烧录器,就别为了追求速度改成SPI。
我曾经踩过的坑: 有个项目选了I2C做Bootloader升级通道,因为省引脚。结果量产时发现,不同批次的EEPROM芯片在I2C总线上有轻微的时序差异,导致部分板子升级到一半就卡死了。后来全部改回UART,问题解决。所以,Bootloader的通信接口,越简单越可靠。

下面这张图总结了三种接口在Bootloader场景下的选择逻辑:

Bootloader通信接口选择逻辑 选择通信接口 引脚是否紧张?(≤2个空闲引脚) 是 UART 或 I2C 否 SPI 优先 固件>500KB? 需要多从设备? 选 UART(稳) 选 I2C(省线) 核心原则:Bootloader 升级,可靠性第一 速度慢一点可以等,升级失败变砖就麻烦了

4.4 实际项目中的选择策略

说了这么多理论,来点实际的。我做过几个不同产品的Bootloader,选择策略大致如下:

  • 消费类产品(智能家居、小家电):用UART。成本敏感,MCU引脚少,而且产线烧录工具基本都是UART接口。固件一般不超过256KB,115200bps够用。
  • 工业控制设备:用SPI。环境干扰大,UART容易丢数据。SPI有独立时钟,抗干扰能力强。而且工业设备通常有外部Flash存参数,SPI正好复用。
  • 传感器节点:用I2C。节点上挂了一堆传感器,I2C总线可以共用。Bootloader升级频率低,速度慢点无所谓。
  • 汽车电子:用CAN。嗯,这个不在本章讨论范围,但提一句——汽车上UART、I2C、SPI都不靠谱,CAN才是王道。
一个小技巧: 如果你不确定选哪个,先留UART。因为UART是调试最方便的接口,开发阶段你肯定要用它打印日志。等产品稳定了,再考虑要不要换成SPI或I2C提速。

嗯,接口选型这事,没有标准答案。每个项目都有自己的约束条件。你只要记住:Bootloader的通信接口,不是选最快的,也不是选最省引脚的,而是选最不容易出错的。因为一旦Bootloader跑飞了,你的板子就真的变砖了。