空闲状态
如下图中 ① 所标识区域所⽰,当没有设备在驱动总线时, SCL 和 SDA 信号线都保持⾼电平( 由上拉电阻拉⾼ ),这种状态我们称之为空闲状态。
起始状态和停止状态
为了能表示更多状态,我们可以允许: 在 SCL 高电平期间, SDA 产生一个从高电平到低电平的跳变,用它来表示开始信息 在 SCL 高电平期间, SDA 产生一个从低电平到高电平的跳变,用它来表示停止信息
用上面的两种特殊情况,就可以有效的和 SDA 传递正常数据 0 或者 1 进行区分。相当于 "在一般情况中,设置特殊情况"。
Master发送设备地址
想想,主设备怎么正确选择要进行通信的从设备?
如图
从设备的地址
I2C设备的地址是由制造厂商决定的,一般是7位或者10位,但绝大多数都是7位,所以下面我都是以7位为例。
帧格式
如下图就是从设备7位地址的帧格式。
图中数据 [1:7] 位用于传输从机地址。 图中数据 [8]( R / W )位,用于标识本次通信是读、还是写。
写操作(Master to Slave):当读写位为 0 时,表示主设备要向从设备写入数据
读操作(Slave to Master):当读写位为 1 时,表示主设备要从从设备读取数据。
ACK
发送方怎么知道从设备同意被选中?从设备在收到 7 位地址+ 1 位读写位后,确认地址是自己的,会在第 9 个时钟(必须是第9个,这是规定)高电平时,拉低一次 SDA,告诉发送方,我同意通信,就是ACK位。
应答位ACK /无应答位NACK
在每个字节 (可以是地址或数据) 传输完成后,由接收方向发送方发送一个反馈位,表示是否成功接收了该字节。这个反馈位称之为应答位 ( Acknowledge : ACK ) 或无应答位 ( Nonacknowledge : NACK )。
ACK:表示数据成功接收。
NACK:可能表示接收方未准备好、地址不匹配、接收失败或读取结束信号等,具体后续会详细介绍。
所以说,I2C是一种可靠的通信方式。
Master写数据
MCU-I2C 作为主机,向从机 I2C 设备写入或者发送常规数据,我们秒懂。因为发送常规数据和发送 7 位地址 + 1 位读写位 + ACK 应答位完全相同。只不过发送常规数据就没有 7 位地址 + 1 位读写位,统一 8 比特,即一字节即可。
Master读数据
| 步骤 | 解释 |
|---|---|
| 第 1 步 | 主机发送起始标志,即 SCL 高电平期间,SDA 高到低跳变 |
| 第 2 步 | 主机发送 7 位地址 + 读写标志 (=1,表示读操作) 位,MSB 优先发送 |
| 第 3 步 | 从机在地址匹配后,发送应答标志 (ACK)。从机利用 "线与" 特性,拉低 SDA |
| 第 4 步 | 从机发送 数据 0 (1 字节) |
| 第 5 步 | 主机发送应答标志 (ACK) |
| … | … |
| 第 m 步 | 从机发送 数据 n (1 字节) |
| 第 m+1 步 | 主机发送应答标志 (NACK)。 |
| 第 m+2 步 | 主机发送停止标志 |
ACK与NACK
- ACK:Master 收到,请继续发
- NACK:Master 收到,我要的数据已经够了,请不要发送了,请不要占据 SDA
最后一次应答必须是NACK,如果是ACK的话,从机会继续发数据,这样会和主机发送的停止位产生竞争。
Master读数据会来不及接收吗?
一般不会,因为Master是SCL时钟信号的主导者,Slave发送数据是在也是在Master主导的时钟信号下进行的。
关于主从设备
注意:虽然说I2C通信是由Master主导的,但是这并不意味着Slave就不能读写数据。
如下面这个生活中的例子:
老师:XXX,你站起来,你看你作业多长时间没交了,上课还经常走神(Master 选择 Slave,并写数据)
老师:你有什么说的,你说说看(Master 要求读取 Slave)
学生:我错了,我错了,后面肯定改 (Slave 在 Master 的要求下,给 Master 发送数据)
上述过程老师 (Master) 在主导通信,但是学生 ( Slave ) 也能收发数据,这个主导通信的老师才是 Master。
当然,Master的角色也并不是一成不变的,绝大多数情况下,都是MCU中的I2C充当Master,但是其实也是可以调换的,让MCU的I2C充当Slave,这种情况极其少见,这里我便不再赘述。