目录
对于与微控制器(MCU)或数字系统进行通信的设备,我们需要建立一些设计标准:
产生一个满足这些标准的系统需要一个串行的总线结构,尽管串行总线没有并行总线的数据吞吐能力,但它们只要很少的配线和IC连接管脚。然而,总线不仅仅是互连的线,还包含系统通讯的所有格式和过程。
串行总线的器件间通讯必须有某种形式的协议避免所有混乱、数据丢失和妨碍信息的可能性。快速器件必须可以和慢速器件通讯。系统必须不能基于所连接的器件,否则不可能进行修改或改进。应当设计一个过程决定哪些器件何时可以控制总线。而且,如果有不同时钟速度的器件连接到总线,必须定义总线的时钟源。所有这些标准都在I2C总线的规范中,接下来叫我们一起学习I2C总线吧!
I2C协议拥有两根线:串行数据线(SDA)和串行时钟线(SCL)。每个器件都有一个唯一的地址识别(无论是微控制器、LCD驱动器、存储器或键盘接口),而且都可以作为一个发送器或者接收器(由器件的功能决定)。很明显,LCD驱动器只是一个接收器,而存储器既可以接收又可以发送数据。除了发送器和接收器外,器件在执行数据传输时也可以被看作是主机或者从机。主机是初始化总线的数据传输并产生允许传输的时钟信号的器件。此时,任何被寻址的器件都被认为是从机。

表1 I2C总线术语的定义
I2C(Inter-Integrated Circuit,双向串行总线)通信协议采用主从结构,其中包括一个主设备(Master)和一个或多个从设备(Slave)。这种结构允许主设备控制通信并向从设备发送指令,从设备则响应主设备的指令并发送数据。
主从结构的工作方式如下:
主设备(Master):
从设备(Slave):

图1 主从结构
I2C总线每个设备都有一个唯一的7bit物理地址(在芯片datasheet中查看),因为I2C地址全0为广播地址,所以I2C总线理论上最多能带2^7 - 1 = 127个从设备。
这种主从结构的通信模型使得I2C总线非常适合连接多个设备,并且可以通过地址选择机制轻松地对特定设备进行通信。在实际应用中,主设备通常是一个微控制器或其他控制器,而从设备可以是各种外部设备,如传感器、存储器、执行器等。
I2C一共有两个总线:一条是双向的串行数据线SDA,一条是串行时钟线SCL。
所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上。I2C总线上的每个设备都自己一个唯一的地址,来确保不同设备之间访问的准确性。
I2C总线是一种半双工的通信协议,这意味着数据在通信双方之间只能单向传输,不支持同时的双向数据传输。在I2C通信中,主设备(Master)和从设备(Slave)之间的数据传输是单向的,通过交替的方式实现双向通信。

上拉电阻通常连接在I2C总线的数据线(SDA)和时钟线(SCL)上,作用是将这些线路的电平拉高到高电平(逻辑1),以便确保在通信空闲时线路保持稳定,同时在设备拉低线路时能够快速恢复到高电平。具体来说,上拉电阻的作用有以下几点:
保持稳定的空闲电平:在通信空闲时,上拉电阻将数据线和时钟线拉高到高电平,防止电平浮动和噪声干扰导致误判。
快速恢复到高电平:当设备拉低数据线或时钟线时,上拉电阻会帮助线路快速恢复到高电平,确保信号的准确传输和时钟同步。
限制电流流动:上拉电阻也可以限制总线上的电流流动,起到一定的电流保护作用。
高阻态指的是一个设备处于高阻抗状态,即在电路中表现为电阻非常大、电流几乎为零的状态。在I2C通信中,高阻态通常用于未被选中的从设备(Slave)或者设备处于空闲状态时,将其数据线(SDA)和时钟线(SCL)引脚置于高阻态,以允许其他设备进行通信。高阻态的作用包括:
防止干扰:设备处于高阻态时,不会对总线上的信号产生影响,防止对通信设备造成干扰。
允许并行通信:通过高阻态,多个设备可以共享同一条总线并且在需要时选择性地参与通信,实现并行通信。
节省功耗:设备处于高阻态时,电流消耗非常小,节省总线和设备的功耗。

I2C 总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。

起始和停止条件一般由主机产生。总线在起始条件后被认为处于忙的状态。在停止条件的某段时间后,总线被认为再次处于空闲状态。如果产生重复起始条件而不产生停止条件,总线会一直被认为处于忙的状态。此时的起始条件和重复起始条件在功能上是一样的。
I2C信号在数据传输过程中,当SCL=1高电平时,数据线SDA必须保持稳定状态,不允许有电平跳变,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。
SCL=1时 数据线SDA的任何电平变换会看做是总线的起始信号或者停止信号。也就是在I2C传输数据的过程中,SCL时钟线会频繁的转换电平,以保证数据的传输

主机往I2C总线上传输器件地址,所有的从机接收到这个地址后与自己的地址相比较若相同则发出一个应答ACK信号,主机收到这个信号后通讯连接建立成功,若未收到应答信号则表示寻址失败。

此外,主/从机在之后的数据通信中,数据接收方收到传输的一个字节数据后,需要给出响应,此时处在第九个时钟,发送端释放SDA线控制权,将SDA电平拉高,由接收方控制。
SDA线上的数据在SCL时钟“高”期间必须是稳定的,只有当SCL线上的时钟信号为低时,数据线上的“高”或“低”状态才可以改变。输出到SDA线上的每个字节必须是8位,数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)。
当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位ACK, 此时才认为一个字节真正的被传输完成 ,如果一段时间内没有收到从机的应答信号,则自动认为从机已正确接收到数据。

主机在发送开始信号之后,

多数从设备的地址为7位或者10位,一般都用7位。
八位设备地址=7位从机地址+读/写地址
再给地址添加一个方向位位用来表示接下来数据传输的方向,

IIC的每一帧数据由9bit组成,如果是发送数据,则包含 8bit数据+1bit ACK,如果是设备地址数据,则8bit包含7bit设备地址 1bit方向。
在单主设备中,不需要时钟同步和仲裁。而在多设备时,多个主设备可以同时在空闲的总线上开始发送数据,这时就需要仲裁决定哪一个来控制总线并完成它的数据传输,有时候也需要时钟同步来协同设备间的工作。而这正是通过时钟同步和仲裁来完成的。
时钟同步用于确保主设备和从设备之间的数据传输按照正确的时序进行。时钟同步解决了I2C总线设备间的速度同步。

时钟同步的过程:
总结:SCL线上的低电平时间是由时钟低电平最长的器件决定,SCL的高电平则是由高电平时间最短的期间决定。
在主线空闲的情况下,主设备发起传输。两个主机在启动条件的最小保持时间内生成一个启动条件,从而在总线上生成一个有效的传输启动条件,而仲裁程序就是决定哪一个主设备可以完成它的传输。
仲裁的步骤:

总结: I2C总线的控制权完全取决于竞争主设备发送的地址和数据,因此没有中央主设备,总线上也没有任何优先级顺序。谁先在SDA线上发送低电平,谁就掌握对总线的控制权。
在某些情况下,从设备可能需要更多的时间来处理数据,确认接收或者执行其他操作。如果不允许时钟拉伸,可能会导致通信错误或数据丢失。因此,时钟拉伸就是为了满足从设备在特定情况下对额外时间的需求。
当从设备需要额外的时间来处理数据或者确认接收时,它可以请求拉低时钟线。当主设备检测到在一个时钟信号周期内,时钟线被拉低,它会意识到有从设备请求拉低时钟线,即时钟拉伸发生。一旦主设备意识到时钟拉伸发生,它会暂停时钟信号的传输。这意味着主设备不再生成新的时钟信号,即时钟信号保持不变(拉低状态),直到时钟拉伸结束。
在主设备暂停时钟信号的期间,从设备有足够的时间来处理数据或者确认接收。这种额外的时间通常是为了处理一些需要较长时间的操作,如读取或写入大量数据、进行复杂的计算等。当从设备完成处理数据或者确认接收后,它会释放时钟线。这意味着时钟线上的时钟信号会恢复正常(高电平状态)。一旦主设备检测到时钟线上的时钟信号恢复正常,即时钟线由低电平变为高电平,它会恢复时钟信号的传输,继续数据传输的流程。
I2C总线是一种同步、半双工、采用电平信号收发的串行总线,其速率支持: