这篇文章主要是理解,不是入门文章,建议先去搜索入门文章,看不懂再来看这篇文章,帮助理解。
1. 应用场景
- 嵌入式系统中,用于将板载外设连接到CPU,比如说传感器
- 因为只有一个数据线和时钟线,抗干扰能力差,传输速度不高,所以适用于板内低速外设,一根线,只能是半双工。
2. 工作原理
两根线:
- 时钟线 SCL:时钟的作用一定要理解,类似于军训走正步时的口哨声,没时钟就停止,有时钟才继续下一步,系统内的所有设备在时钟的步调下运作,才不会混乱。时钟是目前任何数字系统运行的基本驱动力。
- 数据线 SDA:就是传数据的一根线,没什么特别的地方。一根线决定了传输数据不会特别快,而且不能长距离传输。
3. 工作模式
- 一主多从模式(99%场景)
- 多主多从模式(不用管)
4. 通信过程
4.1 主发从收(CPU下发指令)
CPU视角:
发START → [发设备地址+0 → ACK] → [寄存器地址 → ACK] → [数据1 → ACK → ... → 数据N → ACK] → 发STOP
- 有开始,有结束
- 先发地址,选中设备,选中设备后,选择设备寄存器,都选好了以后发数据,发数据以字节为单位,数据长度是N个字节,不会有不完整的字节,否则信号会出现歧义。
- 除了开始结束,任何操作都有ACK
- START:在SCL高电平时拉低SDA,就代表开启信号,那就说明刚开始SDA是高,表示空闲。
- STOP:在SCL保持高电平时,将SDA从低电平释放至高电平,就代表结束信号。
4.2 从发主收(外设上报状态)无此模式!
不行!从设备不能主动上报状态!
结构上因为时钟是CPU控制的,从机控制不了时钟,所以不能主动发。
4.3 主发主读(CPU先写)
当需要读取从设备的特定寄存器(如传感器数据寄存器、EEPROM存储单元)时,主设备需先写入目标地址,再切换为读操作。
流程步骤:
写地址阶段:
主设备发送START信号 + 从设备地址(写模式,R/W位=0) → 等待ACK。
主设备发送寄存器地址 → 从设备回复ACK。
读数据阶段:
主设备发送Repeated START信号(不释放总线)。
主设备发送从设备地址(读模式,R/W位=1) → 等待ACK。
从设备发送数据 → 主设备回复ACK/NACK控制数据流。
终止:主设备发送STOP信号结束通信。
为什么要先写后读?
大多数I2C从设备(如EEPROM、传感器)内部有一个地址指针寄存器,用于指示当前操作的数据位置。
工作原理
-
写地址阶段:主设备发送寄存器地址(如0x00),从设备收到后将该地址存入指针寄存器,相当于设置数据读取的起点。
-
读数据阶段:从设备根据指针寄存器的值返回对应地址的数据,并在每次读取后自动递增指针(连续读时)。
必要性:若跳过写地址直接读,从设备可能返回随机地址的数据(如上次操作残留的指针值),导致数据错乱。