嵌入式通信协议1000问:UART、SPI、I2C、RS-485与车载应用

本篇整理通信协议 1000 问专题首批内容,覆盖基础概念、UART/SPI/I2C/RS-485 原理、常见故障和汽车 ECU 应用。接口速率、时序和电气参数必须以具体 MCU、收发器与从设备数据手册为准;以下数值用于理解,不应直接当作所有器件的保证值。

一、通信基础

Q1. 同步通信和异步通信的核心区别是什么?

答案: 同步通信通过共享时钟或同步机制确定采样时刻;异步通信通常没有独立时钟线,收发双方依靠预先约定的波特率和帧格式进行采样。SPI 是典型同步接口,UART 是典型异步接口。

Q2. 为什么同步通信不需要像 UART 一样预先约定波特率?

答案: 同步接口的时钟由主设备提供,数据传输节拍由 SCK 等时钟线决定,因此从设备按时钟边沿采样。双方仍需满足时钟频率、建立/保持时间和时钟模式约束,并不是“完全不需要配置速率”。

Q3. UART 两端晶振误差为什么会造成乱码?

答案: UART 接收端通常通过起始位检测同步一帧,然后按本地波特率在预期采样点读取数据。如果收发双方时钟偏差过大,误差会在一帧内逐渐累积,采样点可能偏离数据有效窗口,造成位错误、帧错误或乱码。可通过示波器测量 bit 宽度并核对双方实际波特率。

Q4. 全双工、半双工和单工有什么区别?

答案: 全双工允许两个方向同时传输;半双工允许双向传输但需要分时切换;单工只有一个方向。SPI 通常支持全双工;I2C 和常见两线 RS-485 为半双工;SENT 通常是传感器到 ECU 的单向数据传输。

Q5. 主从模式中谁控制时钟和总线?I2C 为什么可以多主?

答案: SPI/I2C 的主设备通常负责发起事务和控制时钟;从设备在被选中或地址匹配后响应。I2C 支持多主仲裁,多个主设备同时发起时可通过总线电平仲裁机制解决竞争;RS-485 只定义物理层,不自带统一的多主仲裁协议,通常由上层协议安排轮询或令牌。

flowchart TD
  A[通信需求] --> B{是否有独立时钟?}
  B -->|有| C[同步:SPI / I2C]
  B -->|无| D[异步:UART / 常见 RS-485 UART链路]
  C --> E{方向能力}
  D --> E
  E -->|同时双向| F[全双工]
  E -->|交替双向| G[半双工]
  E -->|单向| H[单工]

二、四种常见协议

Q6. UART 一帧数据如何组成?为什么要有起始位和停止位?

答案: 常见 UART 帧由空闲电平、起始位、数据位、可选校验位和停止位组成。起始位让接收端检测一帧开始并重新同步采样;停止位提供帧间隔并确认帧结束。常见配置为 8N1,但数据位、校验和停止位数量需两端一致。

常见故障: 波特率不一致、电平不匹配、接收中断响应不及时、缓冲区溢出、DMA/ISR 与任务间数据竞争。

Q7. SPI 的四根信号线各做什么?CPOL/CPHA 如何决定模式?

答案: 常见 SPI 信号为 SCK(时钟)、MOSI(主出从入)、MISO(主入从出)和 CS/SS(片选)。CPOL 定义时钟空闲电平,CPHA 定义在哪个时钟边沿采样;两者组合成 Mode 0–3。

调试方法: 以从设备数据手册的时序图为准,确认采样边沿、数据变化边沿、CS 建立/保持时间和最大 SCK 频率。不能只根据“上升沿采样”一句话猜模式。

Q8. I2C 为什么使用开漏输出和上拉电阻?

答案: I2C 的 SDA/SCL 通常采用开漏/开集结构,器件只能主动拉低总线,释放总线后由上拉电阻拉高。这样多个器件可以安全共享总线,并支持线与逻辑和仲裁。

上拉电阻过大,上升沿太慢;过小,低电平灌电流过大。选值要结合总线电容、总线速率、器件灌电流能力和上升时间规范计算,而不是固定套用 4.7kΩ。

Q9. I2C 时钟拉伸、ACK 和多主仲裁分别解决什么问题?

答案:

  • ACK/NACK:接收方在每 8 个数据位后表明是否应答。
  • Clock Stretching:从设备通过保持 SCL 为低电平,让主设备等待其完成处理。
  • 多主仲裁:多个主设备同时发送时,通过监测总线状态判断谁继续占用总线。

若 MCU I2C 外设不支持或配置不正确地处理时钟拉伸,可能出现通信挂起或超时。

Q10. RS-485 和 UART 是同一种协议吗?

答案: 不是。UART 通常指异步串行数据帧/控制器接口;RS-485 定义差分收发器的电气特性。常见系统把 UART 控制器与 RS-485 收发器组合,使用 Modbus RTU 等上层协议。

半双工 RS-485 需要控制 DE/RE 方向脚。最后一个停止位完全发送结束后才能切回接收,否则可能截断最后一个字节。总线两端通常按拓扑和线缆特性配置终端电阻,常见标称值为 120Ω,但要以实际线缆特性阻抗为准。

flowchart LR
  MCU[MCU UART] --> DIR[DE / RE 方向控制]
  DIR --> PHY[RS-485 差分收发器]
  PHY --> BUS[A / B 双绞线总线]
  BUS --> NODE1[节点 1]
  BUS --> NODE2[节点 2]
  BUS --> NODE3[节点 N]

三、协议故障排查

Q11. UART 有发送波形但 MCU 没收到数据,先查什么?

答案: 分层验证:先确认 TX/RX 接线交叉和电平,再用逻辑分析仪确认对端是否真的返回数据;随后检查 UART 接收标志、中断入口、DMA 状态、环形缓冲区读写索引和任务消费速度。若 ISR 已收到但应用没读到,重点检查缓冲区溢出和并发访问。

Q12. SPI Flash 偶发写错,为什么降低时钟可能有效?

答案: 芯片标称最高 SCK 通常是在规定电气和时序条件下的上限。板级走线、阻抗不连续、负载电容、串扰和边沿振铃可能压缩采样裕量。降低 SCK、优化走线和端接、检查 CPOL/CPHA 与 CS 时序,可提高信号和时序余量。应通过示波器在器件引脚处验证,而非仅凭“降速后好了”就认定唯一根因。

Q13. I2C 传感器读数偶发跳变,怎样定位?

答案: 检查供电、上拉电阻、总线电容、地址冲突、SCL/SDA 毛刺、ACK/NACK、时钟拉伸和软件读写状态机。用示波器或逻辑分析仪捕获异常瞬间的总线波形,确认是否多出时钟、丢失 ACK 或读错寄存器。不要未经验证就随意并联电容,因为它会增加总线负载并改变上升时间。

Q14. RS-485 偶发 CRC 错误,为什么要检查 DE 方向切换?

答案: 若发送端在 UART 最后一个停止位完全移出移位寄存器之前就撤销 DE,差分驱动器可能过早关闭,导致末尾 bit 被截断。应使用 UART Transmission Complete 标志或可靠的发送完成中断,在最后一个停止位结束后再切换方向,并测量 DE 与 A/B 波形。

flowchart TD
  A[通信异常] --> B{协议类型}
  B -->|UART| C[波特率 / 电平 / ISR / Ring Buffer]
  B -->|SPI| D[CPOL CPHA / CS / SCK波形 / 走线]
  B -->|I2C| E[上拉 / 总线电容 / ACK / 毛刺]
  B -->|RS-485| F[DE时序 / 终端 / 共模 / 总线冲突]
  C --> G[示波器 / 逻辑分析仪复现]
  D --> G
  E --> G
  F --> G
  G --> H[根因验证与回归测试]

四、汽车 ECU 中的典型用途

Q15. SPI、UART、I2C、SENT 在汽车 ECU 中分别用于什么?

答案:

  • SPI:外部 Flash、外部 CAN 控制器、IMU/角度/压力等传感器。
  • UART:调试口、产线测试、GPS/北斗模块、蓝牙/蜂窝通信模块。
  • I2C:温度传感器、PMIC、电压监测、EEPROM 等低速外设。
  • SENT:汽车传感器到 ECU 的单向数字通信,ECU 可通过输入捕获测量脉冲宽度解码。

AUTOSAR 边界: 这些 MCU 内部外设通常通过 MCAL 或项目自定义驱动访问;并不是所有外设都经过 COM/PduR。外部 SPI Flash 的管理也不等同于 AUTOSAR Fee 对片上 Flash 的标准抽象。

五、选型与验证

协议选型前先确认:距离、速率、节点数、拓扑、线束环境、EMC、同步要求、功耗、成本、诊断能力和安全要求。然后按目标器件数据手册设计时序与电气参数,并在最差温度、电压、线束长度和噪声条件下验证。

Flomo 原始来源