声明:文章图片均来自网络和相关文档,如有侵权,请联系删除。
目录
1.0 I2C概念
I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线,它只需要两根线:时钟线(SCL)和数据线(SDA),即可在连接于总线上的器件之间传送信息。由于其简单性,I2C被广泛用于微控制器与传感器、显示器、EEPROM等器件之间的通信。
I2C使用多主从架构,主设备用于产生时钟,启动数据传输,此时任何被寻址的器件均被认为是从设备。在I2C总线上,主和从、发和收的关系不是恒定的,取决于此时数据传送方向。如果主设备要发送数据给从设备,则主设备首先寻址从设备,然后主动发送数据至从设备,最后由主设备终止数据传送;如果主设备要接收从设备的数据,首先由主设备寻址从设备.然后主设备接收从设备发送的数据,最后由主设备终止接收过程。
I2C总线结构图如下图1所示:
图1. I2C总线结构图
I2C通信时序图如下图2所示:
图2. I2C时序图
I2C总线特点:
- I2C总线上可以挂载一个主设备和多个从设备,实现一对一(一个主设备对接一个从设备)或者一对多(一个主设备对接多个从设备)的通信;
- 主设备负责调度总线,决定某个时间和其中一个从设备通信。在同一时间,只有主设备和其中一个从设备通信,其余的从设备处于等待状态,等待主设备与其通信;
- 每个从设备在I2C总线上都有唯一的地址,主设备就是通过地址来区分不同的从设备,从而决定和哪一个从设备通信;
- SDA(数据线)和SCL(时钟线)都是双向I/O线,接口电路为开漏输出,需通过上拉电阻接电源VCC;
- I2C将SCL处于高时SDA拉低的动作作为开始信号,SCL处于高时SDA拉高的动作作为结束信号;
- 传输数据时,SDA在SCL低电平时改变数据,在SCL高电平时保持数据,每个SCL脉冲的高电平传递1位数据。
- idle状态,SCL和SDA都是高电平。
1.1 I2C开始和结束信号
当总线上的主机都不驱动总线,总线进入空闲状态,SCL 和 SDA 都为高电平。总线空闲状态下总线上的主设备都可以通过发送开始条件启动通信。
I2C起始信号(S):当SCL高电平时,SDA由高电平向低电平转换,表示开始数据传输;
I2C停止信号(P):当SCL高电平时,SDA由低电平向高电平转换,表示结束当前数据传输;
1.2 I2C从设备地址
开始条件后面的帧是地址帧,用于指定主机通信的对象地址,在发送停止条件之前,指定的从设备一直有效。I2C有2种从设备地址模式,分别为 7bit 地址模式和 10bit 地址模式。
1.2.1 7bit 从设备地址模式
在 7bit 从设备地址模式中,如上图,第一个字节的前7bit(A6:A0)就是从设备地址,最低位(LSB)为R/W位。当R/W位被设置为0时,表示写操作,即主设备向从设备写数据。当R/W位被设置为1时,表示读操作,即主设备从从设备读取数据。
1.2.2 10bit 从设备地址模式
在10bit 从设备地址模式中,如上图,需要传输2个字节数据来设置10bit地址。传输的第一个字节有3部分定义:前5个bit(bit7:3,协议固定为11110),用于通知从设备这是一个10bit模式的传输;随后的2个bit(A9:A8)表示从设备地址,最后1bit(LSB)是R/W位。传输的第二个字节(A7:A0)则全部用于表示从设备地址。这样,A9: A0就表示了10bit 从设备地址。
1.2.3 I2C特殊从设备地址
I2C协议定义一些特殊用途的地址,如下列表所示,故在选择从设备地址的时候,需要注意是否和下列特殊含义的地址定义有冲突。
Slave地址 | R/W bit | 说明 |
0000 000 | 0 | 广播地址 |
0000 000 | 1 | START byte |
0000 001 | X | CBUS地址 |
0000 010 | X | 保留 |
0000 011 | X | 保留 |
0000 1XX | X | 高速模式下Master code |
1111 1XX | X | 保留 |
1111 0XX | X | 10位Slave寻址 |
0001 000 | X | SMBus主设备 |
0001 100 | X | SMBus Alert告警响应地址 |
1100 001 | X | SMBus器件默认地址 |
1.3 I2C应答信号
I2C每次传输完8位数据后,需要从设备反馈一个应答位,以确认从设备是否正常接收了数据。当主设备发送了8位数据后,会再产生一个时钟,此时主设备放开SDA的控制,读取SDA电平,在上拉电阻的影响下,此时SDA默认为高,必须从设备拉低, 以确认收到数据。
应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。
1.4 I2C的工作模式
在I2C总线上,主和从、发和收的关系不是恒定的,取决于此时数据传送方向。I2C的工作模式可以分为下列4种:
(1)Master模式发送数据:发送写请求,写数据到从设备;
(2)Master模式接收数据:发送读请求,接收来自从设备的数据;
(3)Slave模式发送数据:响应主设备的读请求,向主设备发送数据;
(4)Slave模式接收:响应写请求,接收来自主设备的数据;
其中,Master模式发送对应Slave模式接收,时序如下:
Master模式接收对应Slave模式发送,时序如下:
几个读写时序实例:
1.5 I2C通信速率
I2C总线支持三种模式:标准模式、快速模式、高速模式,其对应的速率如下表所示:
模式 | 速率(bit/s) |
标准模式(Standard mode) | 100k |
快速模式(Fast mode) | 400k |
快速模式+(Fast mode plus) | 1M |
高速模式(High-speed mode) | 3.4M |
1.6 I2C完整传输流程
I2C完整传输流程如下:
① SDA和SCL开始都为高,然后主设备将SDA拉低,表示开始信号;
② 在接下来的8个时间周期里,主设备控制SDA的高低,发送从设备地址。其中第8位如果为0,表示接下来是写操作,即主设备传输数据给从设备;如果为1,表示接下来是读操作,即从设备传输数据给主设备;另外,数据传输是从最高位到最低位,因此传输方式为MSB(Most Significant Bit)。
③ 总线中,对应从设备地址的设备,把SDA拉低,发出应答信号;
④ 在接下来的8个时间周期里,如果是写操作,则主设备控制SDA的高低;如果是读操作,则是从设备控制 SDA的高低;
⑤ 每次传输完成,接收数据的设备,都发出应答信号;
⑥ 最后,在SCL为高时,主设备由低拉高SDA,表示停止信号,整个传输结束;
1.7 I2C数据有效性
I2C总线进行数据传送时,在SCL的每个时钟脉冲期间传输一个数据位。当SCL为高电平时表示SDA为有效数据,此时SDA为高电平则表示“ 1”,SDA为低电平则表示“0”;SCL为低电平时表示SDA为无效数据,此时SDA会进行电平切换,为下次数据表示做准备。
换言之,SCL处于高电平周期时,SDA线上的数据必须保持稳定;只有SCL是低电平时,SDA的高或低状态才能改变。
1.8 模拟I2C和硬件I2C
模拟I2C,即用GPIO来模拟I2C时序。通常需要手动写代码控制IO口的电平变化,模拟IIC协议的时序,实现IIC的信号和数据传输。这种方法需要知道I2C完整的通信时序流程,并且需要编写时序细节,比如怎么表示开始信号、结束信号和ACK信号,怎么表示有效数据等。
硬件I2C,即使用MCU的I2C控制器。通常只需要设置I2C控制器的参数, 如传输速率、设备地址、传输的数据等等,I2C控制器就能自动按照I2C协议传输数据。使用硬件I2C,它有相应的I2C驱动电路,有专用的IIC引脚,效率更高,写代码会相对简单,只要调用I2C的控制函数即可,不需要用代码去控制SCL、SDA的各种高低电平变化来实现I2C协议。
因为I2C设备的速率比较低,通常两种方式都可以,模拟I2C方便移植,硬件I2C工作效率相对较高。
1.9 I2C时钟同步和仲裁
在单主机系统中,不需要时钟同步和仲裁。当I2C总线中存在多个主设备时,会产生总线裁决问题。当总线空闲时,多个主设备同时想占用总线,企图启动总线传输数据,这时就需要通过时钟同步和仲裁来决定哪台主设备可以控制总线。
1.9.1 时钟同步
由于 I2C 总线具有线“与”的逻辑功能, SCL 线上只要有一个节点处于低电平,总线上就表现低电平,当所有的节点都发送高电平时,总线才能表现为高电平。
如上图所示,主机A拉低CLKA,并开始计数CLKA低电平保持时间,直到应有的低电平时间结束,便把CLKA时钟拉到高电平状态。此时,主机B的CLKB时钟仍然处于低电平周期内,则主机A的CLKA时钟进入高电平等待状态。因此,SCL总线被具有最长低电平周期的主机保持在低电平。
当所有的主机都已完成其低电平周期的计数时,SCL时钟总线被释放并变为高电平。主机CLK接口和SCL总线的状态之间保持一致,都为高电平。所有主机开始计算它们的高电平周期。第一个完成高电平周期的主机再次将SCL线拉低。
这样,就产生了同步的SCL总线时钟,其低电平周期由具有最长低电平周期的主机确定,其高电平周期由具有最短高电平周期的主机确定。
由于 I2C 这种特性,当多个主机同时发送时钟信号时,在总线上表示的是统一的时钟信号。如果从机希望主机降低传送速度可以通过将 SCL 主动拉低延长其低电平时间来通知主机,当主机在准备下一次传送时发现 SCL 的电平被拉低时进行等待,直到从机完成操作并释放 SCL 线的控制权。
1.9.2 总线仲裁
仲裁由SCL线和SDA线一起配合来完成的,SCL线负责时钟同步,SDA线负责数据仲裁。仲裁是在SDA线上一位一位进行的,每个主机在发送数据后,当SCL为高电平时,每个主机各自判断自己SDA线输出的电平是否与SDA总线电平一致(回读判读机制),如果某主机发现自己SDA线输出电平和SDA总线回读电平不一致,则该主机仲裁失败,失去对总线的控制权,随即关闭自己SDA输出驱动器;另一个主机赢得仲裁,获取对总线的控制权,继续完成它的传输事务。这种仲裁过程可能需要进行很多位。
如上图所示,在第1个SCL时钟高电平时,主机A读取SDA总线的电平,并和自己DATA1输出电平进行比较,结果一致;同时,主机B也执行这样的操作,结果也是一致;因为每个主机各自DATA线的输出电平与SDA总线电平一致,故继续进行下一个bit的仲裁。直到第4个SCL时钟高电平时,主机A发现自己DATA1线输出电平(“1”)和SDA总线回读电平(“0”)不一致,主机A仲裁失败,失去对总线的控制权;主机B的DATA2线的输出电平与SDA总线电平一致,主机B赢得仲裁,获取对总线的控制权,继续完成它的传输事务。
在仲裁过程中,赢得仲裁的主机不会丢失任何信息,仲裁失败的主机继续输出时钟脉冲(在 SCL 上),直到赢得仲裁的主机发送完当前的串行字节,并且可以在总线空闲时重新发起仲裁。通过这种原理可以保证 I2C 总线在多个主机企图控制总线时保证数据的不丢失。