第二篇:I2C 与 SPI —— 同步通信的时序陷阱

第二篇:I2C 与 SPI —— 同步通信的时序陷阱 很多开发者能调通代码但一旦遇到“偶尔死机”、“换个传感器就读不到数据”或者“长线通信丢包”往往就束手无策。这一篇我们不讲寄存器专门从硬件可靠性、时序裕量和物理层设计的角度拆解这两个接口的设计精髓。如果说 GPIO 是孤军奋战那么 I2C 和 SPI 就是团队协作。一个强调“节约”一个追求“速度”。但由于物理层设计的巨大差异它们在硬件设计上的考量点完全不同。1. I2CI2C 只需要两根线SDA/SCL其核心是开漏结构Open-Drain。这也意味着它的信号质量几乎全看那颗上拉电阻。1.1 上拉电阻的“定量计算”不能只用 4.7k很多人习惯随手放个 4.7k欧姆 电阻但在工业场景下这可能导致通信失败。电阻太大会怎样信号上升沿变缓。I2C 依靠电阻回弹到高电平如果总线电容走线长、设备多较大电阻又大波形会变成“圆角矩形”。当高电平没爬升到 0.7VDD时下一个时钟就来了导致数据位判断错误。电阻太小会怎样功耗增加且 IO 口拉低时的电流过大超过 3mA导致低电平电压V_OL抬升无法被识别为逻辑 0。经验法则* 标准模式 (100kbps)4.7k欧姆 至10k欧姆。快速模式 (400kbps)1k欧姆至2.2k欧姆。架构思维如果你的总线上挂了 10 个传感器或者走线超过了 20cm请务必减小电阻值。1.2 死机之源I2C 总线挂死Bus Hang这是最让工程师头疼的问题。现象是 SDA 始终为低重启软件都没用。成因MCU 在读取数据时意外复位而从机正好输出低电平ACK 或数据 0。从机在等时钟主机在等从机释放总线两者陷入“死锁”。硬件对策1.电源控制给从机的 VCC 增加一个由 GPIO 控制的 MOS 管死机时彻底断电重启。2.模拟时钟软件在初始化时先手动翻转 SCL 引脚发 9 个脉冲强制让从机释放 SDA。2. SPI速度与时序的“极限运动”SPI 是推挽输出速度可以跑上几十 MHz但它的软肋在于同步时序的严苛要求。2.1 采样点之争CPOL 与 CPHA 的硬件本质SPI 有 4 种模式选错模式波形看起来也对但数据会产生“移位”。硬件逻辑你必须确保数据在稳定期Setup Time采样而不是在跳变边沿Transition。设计细节如果走线很长时钟线和数据线的延迟不对等即便模式选对了也会在高频下出现误码。2.2 阻抗匹配解决高速下的“波形震荡”当 SPI 速率超过 20MHz比如驱动高速 TFT 屏或 Flash你的 PCB 走线就不再是导线而是传输线。问题信号边沿过陡会导致阻抗不连续产生波形反射。在示波器上会看到明显的过冲和回沟。对策在 SPI 的发送端靠近芯片的引脚串联一个 22欧姆 至 47欧姆的电阻。它能有效吸收反射让波形变得“漂亮”且稳定。3. 跨越边界长距离通信的硬件挑战I2C 和 SPI 协议设计初衷是板内通信距离 10cm。如果要过排线或者去另一个外壳必须增加保护防串扰在排线中不要让 SCL 和 SDA 挨在一起。最好的做法是VCC / SDA / GND / SCL用地线隔离信号线。电平转换当 3.3V 的 STM32 连接 5V 的老一代传感器时SPI 必须加双向电平转换芯片如 TXS0104不能只靠分压电阻。静电保护如果接口需要热插拔每一根信号线都要加低电容的 ESD 保护管否则芯片很容易在插拔瞬间“暴毙”。4. 示波器实战如何判定你的接口设计合格写完这一篇我建议你拿掉示波器探头的钩子用接地弹簧测量以下三点上升时间Rise TimeI2C 信号从 30% 爬升到 70% 电压的时间是否符合手册要求通常 300ns。低电平噪声IO 拉低时电压是否紧贴 GND 0.4V有没有明显的毛刺。建立/保持时间在 SPI 时钟有效沿到来前数据线是否已经提前稳定。结语I2C 考的是物理层适应性电阻与电容的平衡SPI 考的是信号完整性速度与匹配的权衡。作为架构师理解了这两个接口的“脾气”你就能在硬件方案评审时一眼看出那些潜在的“通信炸弹”。