3、I2C/SPI通信协议:I2C协议基础、SPI协议基础、在Retimer中如何选择通信接口、时序分析与常见问题

做固件开发这些年,打交道最多的就是I2C和SPI。说白了,Retimer芯片的配置、状态读取、固件升级,全靠这两个接口。你想想看,如果通信都搞不定,后面所有工作都是白搭。

今天咱们就把这两个协议掰开揉碎了讲。我会结合自己在Retimer项目中的实际踩坑经历,帮你把基础打牢。

3.1 I2C协议基础

I2C,Inter-Integrated Circuit,飞利浦公司发明的。两根线:SCL(时钟)和SDA(数据)。我刚开始接触时觉得它很简单,后来才发现,越简单的东西越容易出幺蛾子。

3.1.1 总线结构

I2C是主从架构。一个总线上可以挂多个设备,每个设备有唯一地址。7位地址模式最多支持127个设备,10位地址模式可以更多。但实际项目中,我建议一个总线上别超过10个设备,否则电容负载太大,信号容易变形。

关键点:I2C是开漏输出,必须外接上拉电阻。阻值选多大?我个人习惯:标准模式100kHz用4.7kΩ,快速模式400kHz用2.2kΩ。如果总线电容大,电阻要更小。

3.1.2 通信时序

I2C的时序其实就几个关键动作:起始条件、停止条件、数据传送、应答信号。

// 起始条件:SCL高电平时,SDA从高变低
// 停止条件:SCL高电平时,SDA从低变高
// 数据传送:SCL低电平时改变SDA,SCL高电平时采样SDA
// 应答信号:第9个时钟周期,从机拉低SDA表示ACK

嗯,这里要注意:每个字节必须跟一个ACK/NACK。如果从机没拉低SDA,主机要发送停止条件或者重新起始条件。我在项目中遇到过,有些Retimer芯片在忙的时候会NACK,这时候需要主机重试。

3.1.3 读写操作

I2C的读写流程是这样的:

  • 写操作:起始条件 → 设备地址+写位(0) → ACK → 寄存器地址 → ACK → 数据字节 → ACK → ... → 停止条件
  • 读操作:起始条件 → 设备地址+写位(0) → ACK → 寄存器地址 → ACK → 重新起始条件 → 设备地址+读位(1) → ACK → 读取数据 → NACK → 停止条件

我的经验:读操作时,最后一个字节主机要发送NACK,告诉从机不用再发了。我曾经忘了这个细节,结果从机一直发数据,总线被锁死。

3.2 SPI协议基础

SPI,Serial Peripheral Interface,摩托罗拉发明的。四根线:SCLK(时钟)、MOSI(主出从入)、MISO(主入从出)、CS(片选)。

说白了,SPI就是全双工、同步、高速的通信方式。Retimer固件升级时,我更喜欢用SPI,因为速度快,而且没有I2C那些地址和应答的麻烦。

3.2.1 四种模式

SPI有四种模式,由时钟极性(CPOL)和时钟相位(CPHA)决定:

模式 CPOL CPHA 数据采样边沿
模式0 0 0 上升沿采样
模式1 0 1 下降沿采样
模式2 1 0 上升沿采样
模式3 1 1 下降沿采样

警告:Retimer芯片的SPI模式一定要看数据手册。我见过有人用模式0去驱动只支持模式3的芯片,结果数据全是乱的。别问我怎么知道的。

3.2.2 通信流程

SPI的通信流程比I2C简单:

  1. 主机拉低CS,选中从机
  2. 主机在SCLK上产生时钟
  3. 主机通过MOSI发送数据,同时通过MISO接收数据
  4. 传输完成后,主机拉高CS

注意:SPI是全双工的,每发送一个字节,同时也会收到一个字节。如果只需要发送,接收的数据可以忽略。如果只需要接收,可以发送0x00或0xFF作为占位符。

3.3 在Retimer中如何选择通信接口

这个问题,我经常被问到。其实没有绝对的好坏,关键看场景。

我画了一张图,帮你理清思路:

Retimer通信接口选择决策树 Retimer通信接口 I2C接口 适用场景 • 配置寄存器、读取状态 • 多设备共享总线 • 速度要求不高(≤400kHz) SPI接口 适用场景 • 固件升级、批量数据传输 • 高速通信(可达几十MHz) • 实时性要求高 建议:配置用I2C,升级用SPI。如果芯片只支持一种,那就没得选。

我个人习惯是这样的:

  • 配置和监控:用I2C。因为只需要读写几个寄存器,I2C的地址机制很方便,而且线少。
  • 固件升级:用SPI。固件文件通常几百KB甚至几MB,I2C的400kHz速度太慢了。SPI可以跑到几十MHz,快很多。
  • 调试:两个都用。I2C用来查看状态,SPI用来下载固件。

避坑指南:有些Retimer芯片的I2C地址是可以配置的。如果板子上有多个Retimer,记得给它们分配不同的地址。我曾经因为两个芯片地址冲突,折腾了两天才发现。

3.4 时序分析与常见问题

时序问题,是通信协议里最让人头疼的。我见过太多工程师,代码写得没问题,但就是通信失败,最后发现是时序不满足要求。

3.4.1 I2C时序关键参数

参数 标准模式(100kHz) 快速模式(400kHz) 说明
SCL时钟频率 ≤100kHz ≤400kHz 别超了,超了芯片不认
SCL低电平时间 ≥4.7μs ≥1.3μs 时钟低电平要保持够长
SCL高电平时间 ≥4.0μs ≥0.6μs 时钟高电平也要够长
数据建立时间 ≥250ns ≥100ns 数据要在时钟上升沿前稳定
数据保持时间 ≥0ns ≥0ns 数据在时钟下降沿后保持

注意:有些MCU的I2C外设,时钟频率设置不准确。比如你设了400kHz,实际可能只有350kHz或者450kHz。最好用示波器量一下实际波形。

3.4.2 SPI时序关键参数

SPI的时序参数相对宽松,但有几个点要注意:

  • SCLK频率:看数据手册,一般Retimer支持到几十MHz。但PCB走线长了,频率要降低。
  • CS建立时间:CS拉低后,要等一段时间再发时钟。这个时间通常几ns到几十ns。
  • CS保持时间:最后一个时钟结束后,CS要保持低电平一段时间再拉高。
  • 数据有效时间:数据在时钟边沿前后要稳定。

3.4.3 常见问题与解决方法

我整理了几个高频问题,都是我在项目中真实遇到过的:

  1. I2C总线锁死

    现象:SDA一直被拉低,无法通信。

    原因:从机异常,或者主机在通信过程中被中断。

    解决:连续发送9个时钟脉冲,让从机释放总线。或者硬件复位。

  2. SPI数据错位

    现象:读回来的数据跟预期不符,但波形看起来没问题。

    原因:SPI模式不匹配,或者时钟相位设置错误。

    解决:用示波器看数据是在上升沿还是下降沿变化,确认模式。

  3. 通信速度上不去

    现象:设了高速,但实际通信失败。

    原因:PCB走线太长,或者上拉电阻太大。

    解决:缩短走线,减小上拉电阻。SPI的话,可以在MISO线上加个串联电阻抑制过冲。

  4. 片选信号干扰

    现象:一个SPI设备工作时,另一个设备也被误选中。

    原因:CS信号有毛刺,或者电平转换太慢。

    解决:在CS引脚上加个小电容(10pF左右)滤波。

我的经验:调试通信问题时,别急着改代码。先用示波器抓波形,看看起始条件、停止条件、数据、应答是不是对的。波形对了,问题就解决了一半。

好了,I2C和SPI的基础就讲到这里。这两个协议是Retimer固件开发的基石,一定要熟练掌握。下一节我们会讲具体的固件升级流程,到时候会用到今天的内容。

小练习:找一块Retimer开发板,用逻辑分析仪抓一下I2C和SPI的波形,对照数据手册看看时序是否满足要求。这是最快的学习方法。


公众号:蓝海资料掘金营,微信deep3321