I2C协议详解(图文并茂+超详细)

什么是 I²C?

  • I²C  叫集成电路总线
  • 它是一种串行通信接口,具有双向两线同步串行总线,通常由两根线组成——SDA(串行数据线)和SCL(串行时钟线)和上拉电阻。
  • 它们用于需要许多不同部件(例如传感器、引脚、扩展和驱动程序)协同工作的项目,因为它们可以将多达 128 个设备连接到主板,同时保持清晰的通信路径!
  • 它用于将各种低速设备连接在一起,如微控制器、EEPROM、A/D 和 D/A 转换器等。
  • 与 UART 或 SPI 不同,I2C 总线驱动器是漏极开路的,可防止总线争用并消除驱动器损坏的机会。
  • I2C 中的每条信号线都包含上拉电阻,当没有设备将其拉低时,可将信号恢复至线路的高电平。
  • 所有传输均由“主设备”发起和终止;“主设备”可以向一个或多个“从设备”写入数据,或者向“从设备”请求数据。“Master”和“Slave”在系统中并不是固定的。事实上,任何设备只要配置了适当的硬件或固件,都可以用作“Master”或“Slave”。
  • 数据以一个字节传输,每个字节后跟一个1位握手信号作为ACK/NACK位(确认/无响应)。

为什么使用I2C?

  • I2C总线目前仍然是各种电路常用的通信外设,且实现简单。无论总线上连接多少个设备,只需要两条信号线(时钟SCL和数据SDA)。
  • 它是真正的多主总线,优于SPI。
  • 此外,I2C接口也很灵活,使其能够与慢速设备通信,同时还具有高速模式来传输大数据。标准模式下传输速率可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s;
  • 由于其灵活性,I2C 将始终是连接设备的最佳通信外设之一。

特征

线数2(SCL 和 SDA)
数据帧大小

8 位数据包

最大速度标准模式 = 100 Kbps
快速模式 = 400 Kbps
高速模式 = 3.4 Mbps
超快速模式 = 5 Mbps
严格的波特率?否(与 UART 相比)
master数量无限
slave数量视情况而定(最多 127,但电容可达 400 pf

I²C通讯协议

I²C 如何工作?

  • I2C 数据在消息中传输,消息被分解为数据帧。
  • 每条消息包含:
    • 启动条件
    • 停止条件
    • 读取和写入位
    • ACK/NACK 位 
    • 从机地址
    • 数据帧
启动和停止条件
  • 启动条件:
    • 当主设备将SDA线从高电平切换到低电平,然后将SCL线从高电平切换到低电平时,传输将开始。
    • 向其他从属设备发出信号,表明传输即将发生。
    • 如果两个主机同时发送启动条件想要获得总线的所有权,那么谁先将 SDA 拉低,谁就“获胜”
  • 停止条件:
    • 所有数据帧发送完毕后,将发送停止条件。
    • SCL线先从低电平切换到高电平,然后SDA线从低电平切换到高电平
    • 在正常数据写入操作期间,当 SCL 为高电平时,SDA 上的值不应更改,因为这可能会导致错误停止情况。
读/写位
  • 单个位指定主机是否正在向从机传输(写入)数据(低电压电平)或从其请求(读取)数据(高电压电平)。
ACK/NACK 位
  • 由接收设备在每个帧后发送,以向发送方发送信号是否成功接收到数据帧 (ACK) 或未成功接收 (NACK)
从机地址
  • 与 SPI 相比,I2C 没有从机选择线,这导致从机设备无法知道数据何时发送给自己而不是其他从机。
  • 为了解决这个问题,I2C 使用地址帧,它是新消息中起始位之后的第一帧。
  • 主设备将首先发送它想要与之通信的从设备的唯一地址。
    • 如果该地址与从机自己的地址匹配,它将向主设备发送回 ACK 位。
    • 如果不匹配,从机将不执行任何操作,从而使 SDA 线保持高电平。

寻址:

主设备将其想要与其通信的从设备的地址发送到与其连接的每个从设备。从设备将接收到的地址与自己的地址进行比较。

  • 如果匹配成功,则从设备知道它将与主设备建立通信。它将向主设备发送回 ACK 位。
  • 与 SPI 相比,I2C 没有从机选择线,这导致从机设备无法知道数据何时发送给自己而不是其他从机。
  • 为了解决这个问题,I2C 使用地址帧,它是新消息中起始位之后的第一帧。
  • 主设备将首先发送它想要与之通信的从设备的唯一地址。
    • 如果该地址与从机自己的地址匹配,它将向主设备发送回 ACK 位。
    • 如果不匹配,从机将不执行任何操作,从而使 SDA 线保持高电平。
7位/10位设备地址
  • I2C 通常有 7 位地址,并且只有 127 个不同的 I2C 设备。然而,实际上,I2C 设备的类型要多得多,并且 I2C 设备很有可能在总线上具有相同的地址。
  • 为了克服这一限制,许多器件通过外部配置引脚使用双地址以及 10 位地址方案。
  • 10 位地址方案对普通 I2C 协议有两个影响:
    • 地址帧现在有两个字节而不是 1 个字节。
    • 第一个字节的前五个最高有效位用于标识 10 位地址,约定为“11110”。

 

 

数据帧(要传输的数据)
  • 发送地址帧并且主设备从从设备接收到 ACK 位后,将开始传输 8 位长的数据,首先发送最高有效位 (MSB)。
  • 当主设备定期生成时钟脉冲时,数据由主设备或从设备根据读/写位在 SDA 上发送。
  • 每个数据帧后面都有一个 ACK​​/NACK 位,以表明数据是否已成功接收。在发送下一个数据帧之前,主机或从机必须接收到 ACK 位
  • 此过程完成后,主设备将向从设备发送停止条件,从而结束传输。

I2C通信的步骤

  • 步骤1:主设备将产生一个开始信号,向其他设备发出信号,开始监听总线并准备接收数据。(SCL高,SDA由高变低)当发送启动信号条件时,总线将进入繁忙状态,其中当前数据传输仅限于选定的主设备和从设备。只有在产生停止条件后,总线才会被释放并再次处于空闲模式。
  • 步骤2:主设备向每个设备发送一个7位设备地址加上一位读写数据帧。该位还将指示下一个数据传输的方向。0 = 主设备向从设备写入数据。1 = 主设备读取数据到从设备。
  • 步骤3:每个从机将主机发送的地址与自己的地址进行比较。成功匹配地址的从设备通过拉低 SDA 线返回 ACK 位。
  • 步骤4:当主设备收到从设备的确认信号后,开始发送或接收数据。下图是向指定设备传输数据的过程图。 
  • 步骤5:接收设备发送完每个数据帧后,向发送方返回另一个ACK位,以确认该帧已成功接收,然后发送方继续发送该数据帧,以此类推。
  • 步骤6:当数据传输完成后,主设备会向其他设备发出停止信号,释放总线,总线进入空闲状态。

 

 

I²C 总线操作

I2C总线的操作是主从设备之间的读写过程。主要分为3个流程:
  • 主设备向从设备写入数据:

 

  • 主设备从从设备读取数据:

 

  • 重复启动条件:
    • 在总线空闲状态期间使用,此时没有其他主机可以断言对总线的控制并且不存在停止条件
    • 这是一个单主系统。重复/重新启动条件机制比使用停止信号结束传输并再次启动总线更有效
    • 例如,
      • 主设备向从设备写入数据然后重新启动启动条件,然后从从设备读取数据或
      • 主设备从从设备读取数据然后重新启动启动条件,然后主设备向从设备写入数据:

I2C的优点和缺点

优点

  • 即使总线上有许多设备,引脚/信号数量也很少
  • 灵活=支持多主多从通讯
  • 简单 = 仅使用 2 根电线
  • 适应性强=适应各种从设备的需求。
  • 可靠 = ACK/NACK 确认每个帧已成功传输。
  • 设备可以随时在总线上安装或移除。

缺点

  • 由于使用上拉电阻,因此速度比 SPI 慢。
  • 开漏设计=有限速度。
  • 由于使用电阻器,需要更多空间
  • 随着设备数量的增加而变得复杂。

  • 15
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Linux操作系统下,I2C是一种常见的通信协议,用于连接主机与各种外部设备,如传感器、扩展模块等。在编写Linux下的I2C代码时,需要使用Linux提供的I2C子系统,它包含了各种函数和结构体,用于管理和操作I2C总线。 首先,我们需要创建一个I2C设备的句柄,可以使用函数`open()`打开对应的设备文件,如`/dev/i2c-0`。如果成功打开设备文件,就可以使用`ioctl()`函数进行各种设置和控制操作。例如,通过`I2C_SLAVE`命令可以指定要与之通信的从设备的地址。 接下来,我们可以使用`i2c_smbus_*()`系列函数来进行I2C通信。这些函数封装了一些常用的I2C操作,如读写字节、读取寄存器等。对于特定的I2C设备,可能还需要使用其他特定的函数进行访问。 在使用`i2c_smbus_*()`函数进行通信时,需要注意传入的参数。例如,读操作需要指定要读取的字节个数,写操作需要指定要写入的数据。同时,还要注意处理函数的返回值,以便判断操作是否成功。 另外,可以使用`close()`关闭I2C设备的句柄,释放资源。 需要注意的是,编写Linux下的I2C代码需要有一定的编程基础和对Linux系统的了解。还需要查阅相关的资料,了解具体的设备地址、寄存器映射关系,以及所需的操作命令和数据格式等。 总之,编写Linux下的I2C代码需要熟悉Linux系统提供的I2C子系统和相关函数,同时还需要了解具体的设备和通信协议的细节。只有掌握了这些知识,才能有效地进行I2C通信,并与外部设备进行数据交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流浪_彩虹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值