I2C协议核心时序:起始、停止、数据位与应答
好,咱们正式进入协议层面。I2C的通信说到底就是四条规矩:起始条件怎么发、停止条件怎么收、数据位怎么摆、应答位怎么确认。把这四条记牢了,I2C就懂了七成。
起始条件(S)和停止条件(P)
先看起始条件。SCL在高电平的时候,SDA从高电平切换到低电平。注意,必须SCL先稳定在高电平,SDA才能跳变。为什么会这样?因为SCL高电平时总线是空闲状态,SDA不能随便动,只有起始条件才允许这个操作。
停止条件正好反过来:SCL高电平时,SDA从低电平切回高电平。这两个条件都是主设备控制的,从设备只能被动响应。
停止条件:SCL=1 → SDA 0→1
我曾经在项目里遇到一个坑:主设备发完起始条件后,SCL没保持够时间,从机没识别到。结果后续数据全对不上。查了两天才发现是起始条件的保持时间(tHD;STA)不满足规格书。所以说,别看时序图简单,参数一个都不能省。
数据位传输:SCL与SDA的配合
数据位的规则只有一句话:SCL低电平时SDA才能变化,SCL高电平时SDA必须保持稳定。你想想看,如果SCL高电平时SDA变了,那就会被解释成起始或停止条件。所以规范里严格规定了数据建立时间(tSU;DAT)和保持时间(tHD;DAT)。
一个字节有8位,从最高位(MSB)开始传。主设备每发一个位,都会拉低SCL,改变SDA,然后释放SCL让从机拉高(或主设备自己拉高),在SCL高电平中间采样。
| 时序参数 | 含义 | 标准模式(100kHz) | 快速模式(400kHz) |
|---|---|---|---|
| tSU;DAT | 数据建立时间 | ≥250 ns | ≥100 ns |
| tHD;DAT | 数据保持时间 | ≥0 ns | ≥0 ns |
| tHIGH | SCL高电平时间 | ≥4.0 μs | ≥0.6 μs |
| tLOW | SCL低电平时间 | ≥4.7 μs | ≥1.3 μs |
应答位机制:ACK与NACK
每传完一个字节(8位),就会紧跟一个应答位(第9个SCL时钟)。规则很简单:
- 发送方在第9个SCL时钟释放SDA(变为高阻输入)
- 接收方如果想应答,就把SDA拉低
- 如果接收方不想应答(比如错了、忙、或是最后一个字节),就保持SDA高电平
主设备怎么区分是应答还是非应答?很简单,主设备在第9个SCL高电平采样SDA。低电平就是ACK,高电平就是NACK。
避坑指南:我曾经调试一块温度传感器,读寄存器时总返回0xFF。示波器一看,从机在应答位发了NACK。原因是地址对了,但寄存器地址没发对。另一种情况:从机正在处理内部操作时,会主动拉低SCL(时钟拉伸),如果你没处理好,应答位会乱掉。
- 每个字节后必须有应答位(不管是主发还是从发)
- NACK通常用来表示传输结束或错误
- 从机时钟拉伸时,SCL被拉低,主设备必须等待
下面这张图把一次完整写事务的时序串起来,从起始到停止。你看,SCL和SDA的配合非常规矩。
说白了,I2C协议的本质就是主设备控制SCL的节奏,SDA在合适的时候变、合适的时候稳。起始和停止是帧头帧尾,数据位是内容,应答位是握手信号。把这套逻辑刻在脑子里,你写驱动时就能预判什么时候总线会卡住。
好了,这一章就讲这些。你可以找一块示波器抓一下实际波形,对照着看,比只看书本深刻很多。