一文搞懂I2C协议-硬件基础 | 8月更文挑战

1,396 阅读9分钟

这是我参与8月更文挑战的第28天,活动详情查看:8月更文挑战

I2C是什么

I2C总线是由飞利浦在80年代初设计的,以允许位于同一电路板上的组件之间能够轻松通信。其大大简化了电路的设计,早期的电视机中很多地方用到了I2C这种通信方式。飞利浦半导体于2006年迁移到了NXP。I2C名称翻译为“ Inter IC”。有时,该总线称为IIC或I²C总线。I2C总结的基本的特征:

  • 电路简单,只需要两根线,时钟线SCL和数据线SDA
  • I2C为总线型结构,主设备依靠从设备地址进行寻址
  • I2C总线上的设备可以为一主多从或者多主多从,多主多从模式下,需要提供仲裁和冲突检测机制。
  • I2C主设备提供时钟,SDA可以双向传输数据
  • I2C标准的传输速率可以达到100Kbit/s,快速模式下可以达到400Kbit/s,高速模式下可以到达3.4Mbit/s。一般最为常用的传输速率<=100Kbit/s。

I2C的硬件电路

I2C主-从设备硬件连接电路如下: 在这里插入图片描述 I2C硬件电路特征:

  • 连接到I2C总线上的设备,必须是以开漏或开集电极的方式连接,这样才能实现线与
  • SCL和SDA必须接上拉电阻,电阻的大小为4.7K到10K之间。
  • 连接到总线上的设备数量受400pF电容的限制。

这里需要注意的三个点:开漏或开集电极、上拉电阻、线与,下面纷纷讨论一下。需要实现说明的是,本人不是电子专业毕业,如果有哪里说的不对的地方,欢迎大家批评指正。

漏极/集电极开路

上面说到芯片的SDA和SCL必须以开漏或者开集电极的方式连接到I2C总线,下面就来分析一下为何必须使用这种方式。

首先说一下,何为漏极/集电极开路,下面以三极管的集电极开路为例讲解一下,MOS管的漏极开路原理相似。 在这里插入图片描述 上图就是三极管的集电极开路连接方式,这种连接方式的特点如下:

  • 输入端为“1”,即高电平,三极管导通,三极管C极与E极导通,输出为“0”。
  • 输入端为“0”,即低电平,三极管截止,三极管输出“1”。
  • 输入和输出反相。
  • 如果输出端不接上拉电阻,输入端为”0“时,输出端为”高组态“。
  • 输入端只能输出“0”,不能输出“1”,如果想输出“1”,需外接上拉电阻
  • 可以实现“线与”的功能,下一节介绍。
  • 电器兼容性好,上拉电阻接不同电压就可以接入到不同的系统中,接3.3V接入到3.3V系统,接5V就接入到5V系统。

上面就是三极管的集电极开路硬件电路,但是,其存在一个问题,就是输入和输出是反相的,需要额外的电路将其再次“反相”,才能使输入和输出一致。

在这里插入图片描述 上图电路中,增加了一个反相三极管,即三极管2,下面看一下它的输入和输出特征:

  • 输入端为“1”,即高电平,三极管1导通,三极管2截止,输出端由于为“开集电极”,由于上拉电阻的作用,输出“1”。
  • . 输入端为“0”,即低电平,三极管1截止,三极管2导通,这时输出端的输出为“0“。

可以看到输入和输出的相位是相同的了。好了,上面就是三极管的集电极开路的电路原理,那么,为什么 连接到I2C总线上的设备,必须是以开漏或开集电极的方式连接呢?根本原因是这种电路可以实现**“线与”**的功能。

线与

由于I2C是一种总线通信协议,所以,会有多个设备挂载在I2C的两根信号线上。设备通信的原理就是按照SCL上的时钟,有规律的改变SDA上的电平,来达到数据通信的要求。那由于总线上挂接了多个设备,不可避免的是会同时有个多个设备试图去改变信号线上的电平,那么必然会产生冲突。所以,如果要正常通信,必须避免冲突的发生。 一种简单的预防冲突机制是:设备在发送数据之前,需要进行冲突检测,检测的依据就是检查SDA的电平状态:只要检测到SDA为低电平,那就是表示总线处于被占用的状态,那么,为了避免发生冲突,当前设备必须等待一段时间以后再次去检测SDA的电平状态,如果总线变成“空闲”的了(即SDA为高电平),那么该设备才能进行通信。

这里有一个关键点就是:如何保证连接到I2C总线上的多个的设备,只要存在一个设备占用了总线,其他设备无论如何也不能使总线变为空闲呢?上文说的集电极开路结构就能达到这个要求。 在这里插入图片描述 如上图,每个设备的SDA输出的值,不完全相同,但是,只要有一个为“0”,其结果就是“0”,这就是线与,其可以保证SDA线上的信号,要么稳定为“0”(至少一个设备输出为0),要么稳定为“1”(全部设备输出都为1)。利用“线与”,I2C总线上的设备,可以方便的检测总线的工作状态,从而可以实现冲突检测和正常的通信时序。

I2C时序

上面主要介绍了I2C总线的硬件基本原理,可是,设备之间如何要完成最终的通信,必须严格按照一定的时序来完成不同信号的交互,这些时序就是I2C通信的硬件协议

边沿控制信号

I2C设备在进行通信时,首先都是由主设备发起。如果主设备要写数据到从设备,主设备将数据放到SDA,等待数据稳定之后,主设备向SCL发送一个上升沿通知从设备读取数据,在SCL高电平期间,SDA的数据应该是稳定的;如果是主设备要读取从设备发来的数据,主设备向SCL发送一个下降沿通知从设备将数据放到SDA上,主设备在SCL高电平期间读取SDA上的数据,读取数据期间,SDA上的数据必须是稳定的。

总结一下:

  • 写:主设备将数据放到SDA上,等数据稳定之后,发送边沿信号(上升沿)通知从设备读取SDA上的数据。
  • 读:主设备发出边沿信号(下降沿)告诉从设备发送数据,检测到边沿信号之后,从设备改变数据,主设备在时钟高电平期间读取数据。

数据有效性规定

在这里插入图片描述

  • I2C在进行数据传送时,SCL为高电平时,SDA上的数据必须稳定。
  • 只有SCL为低电平时,SDA上的数据才允许变化。

开始/停止信号

I2C的开始和停止信号,如下: 在这里插入图片描述

  • 起始和终止信号都是由主设备发起的。
  • 起始信号之后,总线处于占用状态,结束信号之后,总线回到空闲状态。

数据传输

I2C在进行数据传输时的一般规则如下:

  • 发送到SDA 线上的每个字节必须为8 位,每次传输可以发送的字节数量不受限制。
  • 首先传输的是数据的最高位(MSB),每个字节后必须跟一个响应位,所以,一帧数据共有9位。
  • 如果从机要完成一些其他功能后(例如一个内部中断服务程序)才能接收或发送下一个完整的数据字节,可以使时钟线SCL 保持低电平,迫使主机进入等待状态,当从机准备好接收下一个数据字节并释放时钟线SCL后数据传输继续。

在这里插入图片描述 数据接收端在接收到数据之后,如果需要继续接收数据,那么其需要向发送端发送应答信号;如果数据接收端不再接收数据,需要发送非应答信号。

读/写时序

设备寻址

I2C开始通信时,主设备会发起总线寻址,方式就是在发起起始信号之后,发送一个字节的寻址地址。 在这里插入图片描述

  • R/W位:表示数据传输方向,0表示主机向从机写,1表示主机由从机读取数据。
  • 设备地址分为可编程和不可编程,有的设备地址是固定的不变的,而有的设备可以通过芯片的引脚来设定设备的地址,地址可编程的设备,方便在一条I2C总线上,连接多个相同的设备,然后通过地址进行区分。

I2C写时序

下图完整的展示了主机向从机写一个字节的时序图,需要注意的包括:

  • 主机在开始信号之后,需要先发送寻址字节,其中,第0位,为0表示主机要向从机写数据。
  • 从机在接收到每个数据之后,需要发送ACK信号,表示成功接收到数据。
  • 主机在发送完数据之后,发送停止信号。 在这里插入图片描述

I2C读时序

下图完整的展示了主机由从机读取数据的时序图,需要注意的包括:

  • 主机在开始信号之后,需要先发送寻址字节,其中,第1位,为1表示主机由从机读取数据。
  • 主机在接收到每个数据之后,需要发送ACK信号,表示成功接收到数据。
  • 主机在接收完最后一个字节的数据之后,发送“NACK”表示接收完成,之后,从机放弃SDA的控制权,主机发送停止信号,数据接收过程结束。 在这里插入图片描述