4、固件升级协议基础:UART、SPI、I2C、CAN等物理层协议对比
做固件升级,说白了就是在跟物理层打交道。你选什么协议,直接决定了升级速度、可靠性,甚至能不能升级成功。我这些年经手过不少项目,从简单的传感器升级到复杂的工业网关,每种协议都踩过坑。今天咱们就把UART、SPI、I2C、CAN这四种最常见的协议掰开揉碎了聊一聊。
4.1 UART:最通用的“老黄牛”
UART,也就是串口。这玩意儿几乎每个MCU都有,两根线(TX、RX)就能干活。我个人习惯把它当作固件升级的“保底方案”——不管多老的芯片,只要留了串口,升级就不成问题。
优点很明显:
- 硬件简单,成本低
- 全双工,收发互不干扰
- 协议栈轻量,适合Bootloader
缺点也扎心:
- 速度慢,典型波特率115200bps,实际有效数据率也就10KB/s左右
- 没有时钟同步,双方波特率必须严格匹配
- 抗干扰能力一般,长距离传输容易丢包
升级场景建议:适合小固件(< 100KB)、调试阶段、或者对成本极度敏感的产品。
我的经验:我曾经在一个项目中用UART升级128KB的固件,波特率设到921600,结果发现线缆稍微长一点就疯狂出错。后来老老实实降到115200,加了个简单的CRC校验,反而更稳定。别盲目追求高速,稳定才是第一位的。
4.2 SPI:速度之王,但线多
SPI,四根线(MOSI、MISO、SCLK、CS),全双工,速度轻松上MHz。如果你要升级几百KB甚至几MB的固件,SPI是首选。
为什么快?
- 独立的时钟线,主从同步,没有波特率误差
- 全双工,收发可以同时进行
- 没有起始位、停止位,有效数据率极高
但要注意:
- 线多,占用IO口多
- 没有内置的应答机制,需要应用层自己处理
- 从机不能主动发起通信,只能被动响应
避坑指南:我曾经在SPI升级时遇到过一个问题——从机的MISO引脚在空闲时没有拉高,导致主机误判数据。后来我强制在每次通信前先发一个0xFF来同步,问题才解决。记住:SPI的时序容错性不如UART,硬件设计一定要规范。
4.3 I2C:两线制,但慢
I2C,两根线(SCL、SDA),半双工。它的优势在于接线少,而且支持多主机、多从机。但说实话,做固件升级,I2C有点尴尬。
优点:
- 只需要两根线,还能挂多个设备
- 有内置的应答机制(ACK/NACK)
- 支持多主机仲裁
缺点:
- 速度慢,标准模式100kHz,快速模式400kHz
- 半双工,收发不能同时进行
- 每个字节后面都要跟一个ACK位,有效数据率进一步降低
- 从机地址冲突问题
升级场景建议:I2C适合小数据量升级(比如配置参数、校准数据),或者当你的MCU只有I2C接口可用时。别用它升级大固件,你会等到怀疑人生。
你想想看,用I2C升级一个512KB的固件,400kHz速率下,理论时间都要十几秒,实际加上协议开销,半分钟都算快的。而SPI可能几秒就搞定了。
4.4 CAN:工业级的可靠之选
CAN总线,两根差分线(CAN_H、CAN_L),半双工。这玩意儿在工业、汽车领域是标配。做固件升级,CAN的可靠性是其他协议比不了的。
核心优势:
- 差分信号,抗干扰能力极强
- 内置错误检测和重发机制
- 多主机,任意节点都可以发起通信
- 支持优先级仲裁,重要数据优先发送
代价:
- 硬件成本高,需要CAN收发器
- 协议复杂,数据帧最大只有8字节(CAN 2.0)
- 速度上限1Mbps,实际常用250kbps或500kbps
我的经验:我在一个工业网关项目中用CAN升级固件,距离超过100米,现场还有变频器干扰。UART和SPI根本扛不住,但CAN稳如老狗。不过要注意,CAN的数据帧只有8字节,分包和重组逻辑要写得很严谨。我曾经因为一个序号溢出bug,导致升级到一半数据错乱,整批设备都变砖了。从那以后,我强制要求序号用16位,并且每次升级前先擦除整个Flash。
4.5 四种协议对比一览
| 特性 | UART | SPI | I2C | CAN |
|---|---|---|---|---|
| 线数 | 2(TX/RX) | 4(MOSI/MISO/SCLK/CS) | 2(SCL/SDA) | 2(CAN_H/CAN_L) |
| 通信方式 | 全双工 | 全双工 | 半双工 | 半双工 |
| 典型速率 | 115200bps ~ 921600bps | 1MHz ~ 50MHz | 100kHz ~ 400kHz | 125kbps ~ 1Mbps |
| 有效数据率 | 低(有起始/停止位) | 高(无协议开销) | 中(有ACK位) | 低(帧开销大) |
| 抗干扰 | 差 | 中 | 中 | 强 |
| 硬件成本 | 低 | 低 | 低 | 高 |
| 协议复杂度 | 简单 | 简单 | 中等 | 复杂 |
| 升级适用场景 | 小固件、调试 | 大固件、高速 | 小数据、配置 | 工业、长距离 |
4.6 如何选择?我的建议
没有最好的协议,只有最合适的。我一般按这个思路选:
- 先看硬件资源:MCU有什么接口就用什么,别为了升级专门加硬件
- 再看固件大小:小于64KB,UART够用;大于256KB,上SPI
- 环境因素:有强干扰、长距离,直接上CAN,别犹豫
- 成本敏感:UART或I2C,两根线搞定
重要提醒:不管你选哪种协议,升级协议一定要包含以下三个要素:
- 帧头帧尾:用于数据包同步
- 序号:防止丢包和乱序
- 校验:CRC16起步,别用简单的累加和
我曾经见过一个产品用UART升级,只做了简单的和校验,结果现场干扰导致数据错误,升级后设备直接变砖。后来返厂拆机才发现是校验太弱了。
嗯,物理层协议就聊到这儿。下一章咱们会深入讲如何在Bootloader中实现这些协议的驱动,以及怎么处理升级过程中的异常情况。到时候我会拿实际代码出来,咱们一行一行地过。