IIC 通信协议详解


一、概述

IIC 协议(Inter-Integrated Circuit,可简写为 I2C),是一种用于各种电子设备之间进行通信和数据交换的串行通信协议。它是由飞利浦(Philips)公司于 1982 年首次提出并推广的一种简单、高效、低成本的通信协议。

I2C 协议采用双线结构传输数据,包括一个数据线和一个时钟线(即 SDA 和 SCL 线),其中 SDA(Serial Data)线用于双向数据传输,而 SCL(Serial Clock)线则用于同步数据传输的时钟信号。通信始终由主设备(Master)控制,从设备(Slave)被动接收和回应。这种简单的线路连接方式使得设备之间的互连变得非常容易。下图即是 I2C 的基本结构:

在这里插入图片描述

I2C 协议具有广泛的应用范围,如连接传感器、存储器、显示器等设备,常用于微控制器和嵌入式系统中,因为它使用的引脚较少,可以同时连接多个设备,并且具有简单的硬件和软件实现。

二、I2C 详解

1、I2C 总线简介

I2C 总线是一种多主机总线,连接在 I2C 总线上的器件分为主机从机

  • 主机有权发起和结束一次通信,从机只能被动呼叫;
  • 当总线上有多个主机同时启用总线时,I2C 也具备冲突检测和仲裁的功能来防止错误产生;
  • 每个连接到 I2C 总线上的器件都有一个唯一的地址(7 bit),且每个器件都可以作为主机也可以作为从机(但同一时刻只能有一个主机),总线上的器件增加和删除不影响其他器件正常工作;
  • I2C 总线在通信时总线上发送数据的器件为发送器,接收数据的器件为接收器

I2C 总线可以通过外部连线进行在线检测,便于系统故障诊断和调试,故障可以立即被寻址,软件也有利于标准化和模块化,缩短开发时间。

I2C 总线上可挂接的设备数量受总线的最大电容400pF限制。

串行的 8 位双向数据传输速率在标准模式下可达 100Kbit/s,快速模式下可达 400Kbit/s,高速模式下可达 3.4Mbit/s。

总线具有极低的电流消耗,抗噪声干扰能力强,增加总线驱动器可以使总线电容扩大 10 倍,传输距离达到 15m;兼容不同电压等级的器件,工作温度范围宽。


上图就是 I2C 总线如何同多台设备进行通信,在 I2C 总线上,每个从机都有其唯一的设备地址。所以我们只需要知道器件的地址,根据时序就可以实现微控制器与器件之间的通信。

注意,按照实际设计中经验大概是不超过 8 个器件。

这是由 I2C 地址决定:8 位地址,减去 1 位广播地址,是 7 位地址, 2 7 = 128 2^7=128 27=128,但是地址 0x00 不用,那就是 127 个地址, 所以理论上可以挂 127 个从器件。但是,I2C 协议没有规定总线上设备最大数目,但是规定了总线电容不能超过 400pF。管脚都是有输入电容的,PCB 上也会有寄生电容,所以会有一个限制。实际设计中经验值大概是不超过 8 个器件。

总线之所以规定电容大小是因为,I2C 的 OD 要求外部有电阻上拉,电阻和总线电容产生了一个 RC 延时效应,电容越大信号的边沿就越缓,有可能带来信号质量风险。传输速度越快,信号的窗口就越小,上升沿下降沿时间要求更短更陡峭,所以 RC 乘积必须更小。

2、I2C 协议相关知识

2.1 起始位

如下图,就是 I2C 通信起始标志,通过这个起始位就可以告诉 I2C 从机,主机要开始进行 I2C 通信了。在 SCL 为高电平的时候,SDA 出现下降沿就表示为起始位

2.2 停止位

如下图,就是停止 I2C 通信的标志位,和起始位的功能相反。在 SCL 位高电平的时候,SDA 出现上升沿就表示为停止位

2.3 数据传输

如下图,I2C 总线在数据传输的时候要保证在 SCL 高电平期间,SDA 上的数据稳定,即 SDA 上的数据变化只能在 SCL 低电平期间发生

2.4 应答信号

I2C 主机发送完 8 位数据以后会将 SDA 设置为输入状态,等待 I2C 从机应答,也就是等到 I2C 从机告诉主机它接收到数据了。应答信号是由从机发出的,主机需要提供应答信号所需的时钟,主机发送完 8 位数据以后紧跟着的一个时钟信号就是给应答信号使用的。从机通过将 SDA 拉低来表示发出应答信号,表示通信成功,否则表示通信失败。

2.5 I2C 设备地址格式

I2C 设备的地址为 8 位,但是时序操作时最后一位不属于地址,而是 R/W 状态位。所以有用的是前 7 位,使用时地址整体右移一位处理即可。

除此之位,一个设备地址的前四位是固定的,是厂家用来表示设备类型的:

  • 比如接口为 I2C 的温度传感器类设备地址前四位一般为 1001 即 9X;
  • EEPROM 存储器地址前四位一般为 1010 即 AX;
  • oled屏地址前四位一般为 0111 即 7X 等。

2.5 I2C 时序图

下面结合图例,将前面所提到的信息整合一下:

  1. 起始信号

当 SCL 为高电平期间,SDA 由高到低的跳变,起始信号是一种电平跳变时序信号,而不是一个电平信号。该信号由主机发出,在起始信号产生后,总线就处于被占用状态,准备数据传输。

  1. 停止信号

当 SCL 为高电平期间,SDA 由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。该信号由主机发出,在停止信号发出后,总线就处于空闲状态。

  1. 应答信号

发送器每发送一个字节,就在时钟脉冲 9 期间释放数据线,由接收器反馈一个应答信号。应答信号为低电平时,规定为有效应答位(ACK 简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

  1. 数据有效性

IIC 总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。数据在 SCL 的上升沿到来之前就需准备好。并在下降沿到来之前必须稳定。

  1. 数据传输

IIC 总线上传送的每一位数据都有一个时钟脉冲相对应(或同步控制),即在 SCL 串行时钟的配合下,在 SDA 上逐位地串行传送每一位数据。数据位的传输是边沿触发

  1. 空闲状态

IIC 总线的 SDA 和 SCL 两条信号线同时处于高电平时,规定为总线的空闲状态。此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高。

2.5.1 I2C 写时序

要在 I2C 总线上写入,主机将在总线上发送:一个启动开始标志、从机地址、最后一位(R/W位)设置为 0,这表示写入。

从设备发送 ACK 响应确认后,主设备将发送其希望写入的寄存器的寄存器地址。从设备将再次确认,让主设备知道它已准备就绪。在此之后,主机将开始向从机发送寄存器数据,直到主机发送了它需要的所有数据(有时这只是一个字节),并且主机将以停止条件终止传输。

具体步骤如下:

  1. 开始信号。
  2. 发送 I2C 设备地址,每个 I2C 器件都有一个设备地址,通过发送具体的设备地址来决定访问哪个 I2C 器件。这是一个 8 位的数据,其中高 7 位是设备地址,最后 1 位是读写位(为 1 的话表示这是一个读操作,为 0 的话表示这是一个写操作)。
  3. 读写控制位,因为是向 I2C 从设备发送数据,因此是写信号 0。
  4. 从机发送的 ACK 应答信号。
  5. 重新发送开始信号
  6. 发送要写入数据的寄存器地址。
  7. 从机发送的 ACK 应答信号。
  8. 发送要写入寄存器的数据。
  9. 从机发送的 ACK 应答信号。
  10. 停止信号。
2.5.2 I2C 读时序

主机为了读取从设备的数据,主机必须首先指出希望从从设备的哪个寄存器读取数据。这是由主机写入从设备的“写操作”类似的方式开始传输,通过发送 R/W 位等于 0 的地址(表示写入),然后是它希望从中读取的寄存器地址来完成的。

一旦从设备确认该寄存器地址,主机将再次发送启动条件,然后发送从设备地址,R/W 位设置为 1(表示读取)。这一次,从设备将确认读取请求,主机释放 SDA 总线,但将继续向从设备提供时钟。在这部分事务中,主机将成为主“接收器”,将成为从“发射器”。

主机将继续发送时钟脉冲 SCL,但会释放 SDA,以便从设备可以传输数据。在数据的每个字节结束时,主机将向从设备发送 ACK,让从设备知道它已准备好接收更多数据。一旦主机接收到预期的字节数,它将发送一个 NACK,向从设备发送信号以停止通信并释放总线。之后,主机将设置停止条件。

I2C 单字节读时序比写时序要复杂一点,读时序分为四个步骤,第一步是发送设备地址,第二步是发送要读取的寄存器地址,第三步重新发送设备地址,最后一步就是 I2C 从器件输出要读取的寄存器值,我们具体来看一下这步。

  1. 主机发送起始信号。
  2. 主机发送要读取的 I2C 从设备地址。
  3. 读写控制位,因为是向 I2C 从设备发送数据,因此是写信号 0。
  4. 从机发送的 ACK 应答信号。
  5. 重新发送 START 信号。
  6. 主机发送要读取的寄存器地址。
  7. 从机发送的 ACK 应答信号。
  8. 重新发送 START 信号。
  9. 重新发送要读取的 I2C 从设备地址。
  10. 读写控制位,这里是读信号 1,表示接下来是从 I2C 从设备里面读取数据。
  11. 从机发送的 ACK 应答信号。
  12. I2C 器件里面读取到的数据。
  13. 主机发出 NACK 信号,表示读取完成,不需要从机再发送 ACK 信号了。
  14. 主机发出 STOP 信号,停止 I2C 通信。
2.5.3 单个/多个字节的写入/读取

  • 写入单个字节
      向从机设备的某一个寄存器写一个字节数据:开始信号+设备地址(7位)+读/写(1位)+等待从机应答+寄存器地址(8位)+等待从机应答+要写的数据(8位)+等待从机应答+终止信号

  • 写入多个字节
      向从机设备的某一个寄存器写多个字节数据:开始信号+设备地址(7位)+读/写(1位)+等待从机应答+寄存器地址(8位)+等待从机应答+要写的数据_1(8位)+等待从机应答+要写的数据_2(8位)+等待从机应答+······+要写的数据_N(8位)+等待从机应答+终止信号

  • 读取一个字节
      从机设备的某一个寄存器读取一个字节数据:开始信号+设备地址(7位)+写(1位)+等待从机应答+数据地址(8位)+等待从机应答+开始信号+设备地址(7位)+读(1位)+等待从机应答+从机返回读取数据_1(8位)+主机(接收机)不再应答+终止信号

  • 读取多个字节
      从从机设备的某一个寄存器读取多个字节数据:开始信号+设备地址(7位)+写(1位)+等待从机应答+数据地址(8位)+等待从机应答+开始信号+设备地址(7位)+读(1位)+等待从机应答+从机返回读取数据_1(8位)+主机(接收机)应答+从机返回读取数据_2(8位)+主机(接收机)应答+......+从机返回读取数据_N(8位)+主机(接收机)不再应答+终止信号

3、时钟同步和仲裁

3.1 时钟同步

I2C 总线上传送信息时的时钟同步信号是由挂接在 SCL 线上的所有器件的 逻辑“与” 完成的。即如果有多个主机同时产生时钟,那么只有所有主机都发送高电平时,SCL 上才表现为高电平,否则 SCL 都表现为低电平

SCL 线上由高电平到低电平的跳变将影响到这些器件,一旦某个器件的时钟信号下跳为低电平,将使 SCL 线一直保持低电平,使 SCL 线上的所有器件开始低电平期。此时,低电平周期短的器件的时钟由低至高的跳变并不能影响 SCL 线的状态,于是这些器件将进入高电平等待的状态。当所有器件的时钟信号都上跳为高电平时,低电平期结束,SCL 线被释放返回高电平,即所有的器件都同时开始它们的高电平期。其后,第一个结束高电平期的器件又将 SCL 线拉成低电平。这样就在 SCL 线上产生一个同步时钟。

可见,时钟低电平时间由时钟低电平期最长的器件确定,而时钟高电平时间由时钟高电平期最短的器件确定

3.2 时钟仲裁

总线仲裁与时钟同步类似,当所有主机在 SDA 上都写 1 时,SDA 的数据才是 1,只要有一个主机写 0,那此时 SDA 上的数据就是 0

一个主机每发送一个 bit 数据,在 SCL 为高电平时,就检查 SDA 的电平是否和发送的数据一致,如果不一致,这个主机便知道自己输掉了仲裁,然后停止向 SDA 写数据。也就是说,如果主机一致检查到总线上数据和自己发送的数据一致,则继续传输,这样在仲裁过程中就保证了赢得仲裁的主机不会丢失数据。

输掉仲裁的主机在检测到自己输了之后也就不再产生时钟脉冲,并且要在总线空闲时才能重新传输。

仲裁的过程可能要经过多个 bit 的发送和检查,实际上两个主机如果发送的时序和数据完全一样,则两个主机都能正常完成整个数据传输。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值