3. I2C总线协议基础:从物理层到读写操作

各位同学,今天我们聊聊I2C总线。说实话,I2C在SFP模块里太常见了——模块的EEPROM、数字诊断信息,全是通过这两根线读出来的。我刚开始做光模块时,总觉得I2C很简单,不就是两根线嘛。结果有一次调试,模块死活读不到数据,折腾了两天才发现是时序问题。嗯,从那以后,我对I2C再也不敢马虎了。

3.1 I2C物理层:SCL和SDA

I2C总线就两根线:SCL(时钟线)和SDA(数据线)。你想想看,所有设备都挂在这两根线上,靠地址区分,是不是很巧妙?

物理层有几个关键点,我列出来:

  • 开漏输出:SCL和SDA都是开漏结构。什么意思?就是只能拉低,不能主动拉高。拉高靠上拉电阻。
  • 上拉电阻:一般4.7kΩ或10kΩ。我建议SFP模块用4.7kΩ,因为模块内部还有电容,阻值太大信号上升沿会变缓。
  • 线或逻辑:多个设备可以同时拉低总线,谁先拉低谁说了算。这就是仲裁的基础。
  • 最大电容:标准模式下总线电容不超过400pF。超过这个值,信号质量会变差。

重要提醒:SFP模块的I2C总线通常由主机(Host)提供上拉电阻。模块内部不要加额外的上拉,否则电阻并联后阻值太小,可能导致信号无法拉高。

我个人习惯在设计SFP模块时,在模块端加一个100Ω的串联电阻,用来抑制振铃。这个做法在高速I2C(400kHz)下特别有用。

3.2 I2C时序:起始条件、停止条件、数据有效性

时序是I2C的核心。说白了,就是SCL和SDA怎么配合,才能让数据正确传输。

3.2.1 起始条件(Start Condition)

起始条件很简单:SCL为高电平时,SDA从高切换到低。这个下降沿告诉所有从设备:总线要开始传输了,大家准备好。

我在项目中遇到过一个问题:主机发送起始条件时,SDA下降沿不够陡峭,导致某些从设备没检测到。后来查了手册,发现是上拉电阻太大,加上总线电容也大,信号边沿变缓了。换成4.7kΩ后问题解决。

3.2.2 停止条件(Stop Condition)

停止条件正好相反:SCL为高电平时,SDA从低切换到高。这个上升沿告诉所有设备:传输结束,总线释放。

小技巧:调试时可以用示波器同时抓SCL和SDA。看到SCL高电平时SDA有跳变,那就是起始或停止条件。我曾经靠这个快速定位了一个地址错误的问题。

3.2.3 数据有效性

数据有效性规则就一句话:SCL高电平时,SDA上的数据必须稳定。数据只能在SCL低电平时改变。

为什么会这样?因为从设备是在SCL的上升沿采样SDA。如果SDA在SCL高电平时变化,采样结果就不确定。

来看一个典型的I2C字节传输时序:

SCL:  ████████░░░░████████░░░░████████░░░░...
SDA:  ██░░██░░██░░██░░██░░██░░██░░██░░██...
       ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑  ↑
       D7 D6 D5 D4 D3 D2 D1 D0 ACK

每个字节8位,后面跟一个应答位(ACK)。主机发送完8位后释放SDA,从设备拉低SDA表示应答。

3.3 I2C地址与读写操作

I2C地址是7位的(也有10位地址模式,但SFP模块基本用7位)。每个从设备有一个唯一地址。SFP模块的EEPROM地址通常是0xA0(写)和0xA1(读)。

地址怎么组成?我画个图你就明白了:

7位地址 + 读写位 = 8位数据

例如:SFP EEPROM地址 0x50(7位)
写操作:0x50 << 1 | 0 = 0xA0
读操作:0x50 << 1 | 1 = 0xA1

读写操作流程,我总结成表格:

操作 流程 说明
写操作 起始条件 → 发送地址+写位 → 等待ACK → 发送寄存器地址 → 等待ACK → 发送数据 → 等待ACK → 停止条件 每次发送后都要等待从设备应答
读操作 起始条件 → 发送地址+写位 → 等待ACK → 发送寄存器地址 → 等待ACK → 重复起始条件 → 发送地址+读位 → 等待ACK → 读取数据 → 发送NACK → 停止条件 需要先写寄存器地址,再重新起始读
连续读写 在读写操作中,每传输一个字节后,地址自动+1 SFP EEPROM支持连续读取,效率高

避坑指南:我曾经在连续读取SFP模块的DDM数据时,忘记在最后一个字节发送NACK。结果模块一直拉低SDA,总线被锁死了。记住:读操作的最后一个字节,主机要发送NACK(不拉低SDA),然后发送停止条件。

3.4 知识体系图

下面我用一张图把I2C的核心知识点串起来:

I2C总线协议知识体系 物理层 SCL(时钟线) SDA(数据线) 开漏输出 + 上拉电阻 线或逻辑 / 仲裁 时序 起始条件:SCL高→SDA下降 停止条件:SCL高→SDA上升 数据有效性:SCL高时稳定 应答机制(ACK/NACK) 地址与读写 7位地址 + 读写位 写操作流程 读操作流程 连续读写 / 重复起始 SFP模块中的应用 读取EEPROM(地址0xA0/0xA1) 读取DDM数字诊断信息(温度、电压、光功率等) 三个核心模块相互依赖,共同构成I2C通信的基础 物理层保证信号传输,时序保证数据正确,地址保证设备识别 关键参数速查 标准模式100kHz | 快速模式400kHz | 上拉电阻4.7kΩ | 总线电容≤400pF

3.5 实战要点总结

最后,我把I2C调试中容易踩的坑列出来:

  1. 总线锁死:从设备没收到停止条件,一直拉低SDA。解决办法:主机发送9个时钟脉冲,让从设备复位。
  2. 地址错误:7位地址左移一位后,别忘了加上读写位。我见过有人直接发0x50,结果设备没应答。
  3. 应答超时:从设备处理慢,没来得及拉低SDA。建议加超时处理,一般5ms就够了。
  4. 电平不匹配:主机是3.3V,模块是1.8V?需要电平转换。SFP模块通常是3.3V,但有些新模块用1.8V。

我的调试习惯:先用逻辑分析仪抓完整的I2C波形,看起始条件、地址、数据、停止条件是否都对。没问题了再用示波器看信号质量。这样能快速定位问题。

好了,I2C的基础就讲到这里。记住:物理层是骨架,时序是血液,地址是灵魂。三者缺一不可。下一节我们讲SFP模块的EEPROM结构,到时候你会看到I2C怎么实际应用的。

专注资料整理