第1章 I2C协议基础——从一根线到一棵树

做嵌入式这些年,我接触过不少通信协议。SPI、UART、CAN……但要说最“接地气”的,还得是I²C。你别看它只有两根线,SDA和SCL,却能挂几十个设备。我第一次调I²C温度传感器时,总觉得这协议挺简单,结果被时序折腾了好几天。所以这一章,我们先把这个基础打牢。

1.1 I²C总线起源

I²C是Philips(现在的NXP)在1982年搞出来的。初衷很简单——给电视、音响这类消费电子内部的芯片之间,省掉那些乱七八糟的并行线。两根线、一套协议,就能把CPU、存储器、AD转换器、温度传感器全串起来。

早期的版本叫Standard模式,速率100 kbit/s。后来慢慢演进出Fast模式(400 kbit/s)、Fast+(1 Mbit/s)、High Speed(3.4 Mbit/s),甚至Ultra Fast。不过说实话,我们平时调试温度传感器,大部分场景还是Standard或Fast模式。你想想看,温度变化本来就慢,100k的速率已经完全够用了。

模式最大速率典型应用
Standard100 kbit/s温度传感器、EEPROM
Fast400 kbit/s多数传感器、RTC
Fast+1 Mbit/s大容量存储、显示驱动
High Speed3.4 Mbit/s音视频、高速ADC

1.2 电气特性——两根线的门道

I²C是开漏+上拉的结构。SDA和SCL都是开漏输出,不能主动输出高电平。高电平全靠外部上拉电阻拉上去。为什么这么设计?好处是多个设备可以直接“线与”——任何一个设备拉低,总线就被拉低,不会短路。

避坑提醒: 我曾经在一块板子上为了省成本,用了10kΩ上拉电阻。结果总线电容一大,SCL上升沿变得很缓,读温度传感器每次都会丢一个字节。后来换成4.7kΩ才正常。上拉电阻不是随便选的,要结合总线电容和速率计算。
  • 上拉电阻范围: 标准模式下一般4.7kΩ~10kΩ,Fast模式建议2.2kΩ~4.7kΩ。
  • 总线电容: 每根线总电容不宜超过400 pF(标准模式),否则上升沿会超标。
  • Vih / Vil: 输入高电平最低0.7×VDD,输入低电平最高0.3×VDD。不同电压域混接时要小心。

另外要注意的是,I²C不是差分信号,抗干扰能力一般。如果传感器和主控隔着半米长的线缆,我建议加一个PCA9600这样的缓冲器,不然通信失败的概率挺高。

1.3 主从架构——谁说了算

I²C总线上通信靠主从模式。主机发起通信、产生时钟、发送起始条件和停止条件。从机只能响应,不能主动发起。一个总线上可以有多个主机,但同一时间只能有一个主机控制总线。为什么?两个主机同时拉低SCL……嗯,那就仲裁了。

  • 主机: 通常是MCU、SoC、FPGA。
  • 从机: 温度传感器、AD转换器、EEPROM、显示驱动芯片。
  • 多主仲裁: 如果两个主机同时尝试拉低SDA,谁先释放谁就输。仲裁靠检查SDA电平是否与预期一致。
个人经验: 我习惯在设计初期就先规划好每一个从机的7位地址,避免冲突。比如温度传感器通常有A0/A1/A2引脚,可以焊电阻改变地址。最好画个表格贴在原理图边上,省得后来查。

1.4 SDA和SCL信号——读懂波形才算入门

SDA是数据线,SCL是时钟线。数据在SCL低电平期间变化,高电平期间采样。这规矩很严格——只要SCL高电平时SDA变化了,就会被判为起始或停止条件。我刚开始学I²C时,逻辑分析仪上看到一段奇怪的波形,怎么都分析不出来,后来发现是上拉电阻太小导致SCL上升沿过冲,SCL高电平时SDA恰好抖了一下,被误判为启动信号。所以保持时序干净很重要。

信号事件SCLSDA
起始条件 (S)高电平下降沿
停止条件 (P)高电平上升沿
数据位为1高电平保持高
数据位为0高电平保持低
应答位 (ACK)高电平从机拉低
非应答 (NACK)高电平从机释放(高)
数据的传输节奏: 主机先发送起始条件,然后发送从机地址(7位)+ 读/写位(1位)。从机应答ACK后,主机接着发送寄存器地址,再收到或发送数据。每次传输后都需要应答位,直到停止条件。时序边界就藏在SCL的保持时间、上升时间、数据建立时间这些参数里。

下面是我画的I²C基本数据传输结构图,可以帮你把协议流程串起来。

I²C 单次写传输流程(主->从) 起始条件 (S) 从机地址(7bit) R/W# (1bit) ACK 寄存器地址(8bit) ACK 数据字节(8bit) ACK 停止条件 (P) 说明: 从机地址和R/W#一起组成第一个字节(8位),主机发送后等待从机ACK。 寄存器地址用于指定从机内部的哪个寄存器。温度传感器通常有配置寄存器、数据寄存器等。 数据字节可以连续传输多个(本图只画了一个示意),每字节后都需要ACK。

1.5 时序参数——那些让人头疼的ns

调试温度传感器时,最怕遇到时序违例。我整理了几个关键参数,你在看数据手册时必须盯着看:

参数符号标准模式最小值Fast模式最小值说明
SCL时钟频率fSCL--100 kHz 或 400 kHz
SCL低电平时间tLOW4.7 μs1.3 μsSCL为低时的最小保持时间
SCL高电平时间tHIGH4.0 μs0.6 μsSCL为高时的最小保持时间
数据建立时间tSU;DAT250 ns100 nsSCL高电平前SDA必须稳定
数据保持时间tHD;DAT0 ns0 nsSCL下降沿后SDA保持时间
SCL上升时间tr最大1000 ns最大300 ns受上拉电阻和总线电容影响
实战中的坑: 我曾经用GPIO模拟I²C做温度传感器读取,没有严格检查tSU;DAT。结果在某个温度点读数突然跳变,后来用示波器抓波形才发现,数据建立时间差了大概80ns。从那以后,凡是模拟I²C我都在发送每一位后加一个空操作的延迟,保证时序富裕量。

1.6 小结

这一章我们把I²C的底子打了一遍。从起源到电气特性,从主从架构到波形时序。你可能觉得理论枯燥,但后面所有时序调试、边界计算、波形分析,都离不开这些基础。特别是SDA/SCL信号那张图——你去抓一个真实传感器的波形对照着看,会发现协议就是这么运行的。