I2C详解(1) 一文快速了解I2C的工作原理
I2C详解(1) 一文快速了解I2C的工作原理
I2C详解(2) I2C总线的规范以及用户手册(1) I2C 总线协议
I2C详解(3) I2C总线的规范以及用户手册(2) I2C 其他的总线协议以及总线速度
I2C详解(4) I2C总线的规范以及用户手册(3) I2C电气规格和时序
I2C详解(5) I2C总线的规范以及用户手册(4) MIPI I3C 概述
I2C详解(6) STM32软件模拟I2C
文章目录
前言
本文参考TI的应用报告 SVLA704
本文的目的主要是让大家有I2C的工作原理有个认知,更详细的规范在后续文章中。
摘要
I2C 总线是一种非常流行且功能强大的总线,用于主机(或多个主机)与单个或多个从机之间的通信。 Figure 1 显示了有多少不同的外设可以共享一条仅通过2根电线连接到处理器的总线,这是与其他接口相比, I2C 总线可以提供的最大优势之一。
本应用笔记旨在帮助用户了解I2C 总线的工作原理。
Figure 1 所示为嵌入式系统的典型 I2C 总线,其中使用多个从机。微控制器代表 I2C 主机,控制IO扩展器、各种传感器、EEPROM、ADC/DAC等。所有这些都由主机仅2个引脚控制。
Figure 1. I2C 总线示例
1. 电气特性
I2C 使用漏极开路/集电极开路,在同一条线路上带有输入缓冲器,允许将单条数据线用于双向数据流。
1.1 使用开漏进行双向通信
开漏是指一种输出类型,它可以将总线拉低到电压(在大多数情况下为地),或者“释放”总线,让它被上拉电阻拉起。如果总线由主机或从机释放,线路上的上拉电阻 (RPU) 负责将总线电压拉至电源轨。由于没有设备可以强制拉高线路上的电压,这意味着总线永远不会遇到通信问题,即一个设备可能尝试发送高电平,而另一个设备发送低电平,导致短路(电源轨对地)。I2C 要求,如果多主机环境中的一个主机准备传输高电平,但看到线路电平为低电平(另一个设备正在将其拉低),说明另一个设备正在使用总线,因而将会停止通信。推挽式接口不允许这种类型的自由,这是 I2C 的优势。
注:
- 电源轨是指上拉电阻所接入的电源电压VCC,但由于上拉电阻(kohm)与FET关断时候的超大阻抗(Mohm)分压,导致总线上的电压会略低于VCC。但是由于分压电阻差距过大,一般是认为相等的。
- 不可避免的,总是会存在寄生电容,因而电平从高到低、从低到高是需要一定的时间的。
- 推挽输出的是由两个互补的三极管或者MOS管组成,始终保持一个导通,另一个截止的状态,假如一个主机A使用推挽输出高电平,另一个主机B使用推挽输出低电平,这时候电流将通过VCC流过主机A的上管,主机B的下管到地,总线的电压由两个管子的导通电阻进行分压,如果管子一致性较好,那么总线上的约为 VCC的一半。
- 推挽输出的特性决定了其不能用于多主机的环境中,但是由于推挽输出的能力比开漏输出的能力强太多(因为没有上拉电阻的限流作用),在I2C 的超快速模式(5Mbit/s)中要求必须使用推挽输出,才能满足信号的时序要求,在这个模式下,只能沿一个方向传输数据,用于驱动 LED 控制器和其他不需要反馈的设
备时,它最有用。 - 开漏输出允许线与(与门)的逻辑功能,导致某个设备输出为低时,线路就是低电平,而输出高电平时,可以通过输入缓冲器来判断总线的电平,就不需要再修改IO口的输入输出模式了,对于代码编写软件模拟I2C 来说是极其方便的。
Figure 2. SDA/SCL 线的基本内部结构
1.1.1 开漏拉低
如上一节所述,漏极开路设置只能将总线拉低,或“释放”总线,让电阻将其拉至高电平。 Figure 3显示了将总线拉低的电流。想要发送低电平的逻辑,将激活下拉式FET,这将提供接地短路,从而将线路拉低。
Figure 3. 通过开漏接口将总线拉至低电平
1.1.2 开漏释放总线
当从机或主机希望发送逻辑高电平时,它只能通过关闭下拉式FET来释放总线。这使得总线悬空,上拉电阻将电压拉到电压轨,这将被解释为高电平。 Figure 4 显示了流经上拉电阻的电流,该电阻将总线拉至高电平。
Figure 4. 使用开漏接口释放总线
2. I2C 接口
2.1 一般 I2C 操作
I2C 总线是一个标准的双向接口,使用称为主控制器的控制器与从机进行通信。从机不能传输数据,除非它被主机寻址。 I2C 总线上的每个器件都有一个特定的器件地址,用于区分同一 I2C 总线上的其他器件。许多从机需要在启动时进行配置以设置设备的行为。这通常是在主机访问从机的内部寄存器映射时完成的,这些寄存器映射具有唯一的寄存器地址。一个设备可以有一个或多个寄存器,用于存储、写入或读取数据。
物理 I2C 接口由串行时钟 (SCL) 和串行数据 (SDA) 线路组成。SDA和SCL线路都必须通过上拉电阻连接到VCC。上拉电阻的大小由I2C 线路上的电容量决定(有关更多详细信息,请参阅 I2C 上拉电阻计算 (SLVA689))。仅当总线空闲时,才能启动数据传输。如果 SDA 和 SCL 线路在 STOP 条件之后都处于高电平,则总线被视为空闲。
主机访问从机的一般过程如下:
- 假设主机要将数据发送到从机:
- 主-发射器发送START条件并寻址到从-接收器
- 主-发射器将数据发送到从-接收器
- 主-发射器以停止条件终止传输
- 如果主机想要从从机接收/读取数据:
- 主-接收器发送START条件并寻址到从-发射器
- 主-接收器发送请求的寄存器到从-发射器以读取数据
- 主-接收器从从-发射器接收数据
- 主-接收器以 STOP 条件终止传输
2.1.1 启动和停止条件
与此器件的 I2C 通信由发送 START 条件的主机启动,并由发送 STOP 条件的主机终止。当 SCL 为高电平时,SDA 线路上的高到低转换定义了 START 条件。当 SCL 为高电平时,SDA 线路上的从低到高的转换定义了 STOP 条件。
Figure 5. START 和 STOP 条件示例
2.1.2 重复起始条件
重复的起始条件类似于起始条件,用于代替紧跟在停止条件后的起始条件。 它看起来与起始条件相同,但与起始条件不同,因为它发生在停止条件之前(当总线未空闲时)。当主机希望启动新的通信,但不希望总线在停止条件下空闲时,这很有用,因为主节点可能会失去对另一个主机的总线的控制(在多个主机环境中)。
2.2 数据有效性和字节格式
在SCL的每个时钟脉冲期间传输一个数据位。一个字节由 SDA 线路上的八位组成。字节可以是设备地址、寄存器地址或写入或从从机中读取的数据。首先传输数据最高有效位 (MSB)。在起始和停止条件之间,可以将任意数量的数据字节从主机传输到从机。SDA线上的数据必须在时钟周期的高电平期间保持稳定,因为当SCL为高电平时,数据线的变化被解释为控制命令(起始或停止)。
Figure 6. 一个字节传输的示例
2.3 应答 (ACK) 和无应答 (NACK)
每个数据字节(包括地址字节)后跟来自接收器的一个ACK。应答位允许接收机与发送器通信,表示该字节已成功接收,并且可以发送另一个字节。
在接收机可以发送ACK之前,发射机必须释放SDA线。要发送ACK位,接收机应在ACK/NACK相关时钟周期(周期9)的低相位期间拉下SDA线,以便在ACK/NACK相关时钟周期的高相位期间SDA线路稳定低电平。必须考虑建立时间和保持时间。在接收机可以发送ACK之前,发射机必须释放SDA线。要发送ACK位,接收机应在ACK/NACK相关时钟周期(周期9)的低相位期间拉下SDA线,以便在ACK/NACK相关时钟周期的高相位期间SDA线路稳定低电平。必须考虑建立时间和保持时间。.
当SDA线在与ACK/NACK相关的时钟周期内保持高电平时,这被解释为NACK。有几个条件会导致 NACK 的生成:
- 接收机无法接收或发送,因为它正在执行某些实时功能,并且尚未准备好开始与主站通信。
- 在传输过程中,接收方会收到它不理解的数据或命令。
- 在传输过程中,接收方无法再接收任何数据字节。
- 主-接收器完成读取数据的操作,并通过NACK告诉给从机。
注:
- Acknowledge (ACK) and Not Acknowledge (NACK),这个(ACK)可以表示应答,响应,确认等等意思,表示对操作的一个反应,相应的(NACK)就是反面的意思,无应答,无响应,不进行确认等等,目前也没有一个权威的术语进行描述,而我自己都是以应答 (ACK) 和无应答 (NACK)进行翻译,请观众知悉。
Figure 7. NACK 波形示例
3. I2C 数据
数据必须发送到从机,或从从机接收数据,实现此目的的方式是通过读取或写入从设备中的寄存器。
寄存器是从机内存中包含信息的位置,无论是配置信息,还是一些要发送回主机的采样数据。主机必须将信息写入这些寄存器,以便指示从机执行任务。
虽然在 I2C 从机中通常具有多个寄存器,但请注意,并非所有从机都有多个寄存器 。有些器件很简单,只包含1个寄存器,可以通过在从地址之后立即发送寄存器数据直接写入寄存器,而不是寻址寄存器。单寄存器器件的一个例子是8位 I2C 开关,它通过I2C 命令进行控制。由于它有1位来启用或禁用通道,因此只需要1个寄存器,并且主机只需在从机地址后写入寄存器数据,从而调过寄存器号。
3.1 在 I2C 总线上写入从机
要在 I2C 总线上写入,从机将在总线上发送一个起始条件,其中包含从机的地址,以及设置为0的最后一位 (R/W位) 这表示写入。在从机发送应答位后,主机将发送它希望写入的寄存器的寄存器地址。从机会再次应答,让主机知道它已经准备好了。在此之后,主机将开始将寄存器数据发送到从机,直到主机发送了它需要的所有数据(有时这只是一个字节),主机将以STOP条件终止传输。
Figure 8 显示了将单个字节写入从机寄存器的示例。
Figure 8. I2C 写入从机寄存器的示例
3.2 从I2C 总线上的从机读取数据
从从机那里读取与写入非常相似,但有一些额外的步骤。为了从从机中读取,主机必须首先告诉从机希望读取的寄存器。这是由主机以与写入类似的方式开始传输来完成的,方法是发送 R/¯W 位等于0的地址(表示写入),然后是它希望读取的寄存器地址。一旦从机应答了此寄存器地址,主机将再次发送START条件,然后是 R/¯W 位设置为1(表示读取)的从地址。这一次,主机将应答读取请求,主机释放SDA总线,但将继续向从机提供时钟。在这一部分通讯中,主机将成为主-接收方,从机将成为从-发送器。
主机将继续发出时钟脉冲,但会释放SDA线,以便从机可以传输数据。在每个数据字节结束时,从机将向从机发送一个ACK,让从机知道它已经准备好处理更多数据。一旦主机收到它所期望的字节数,它将发送一个NACK,向从机发出STOP 条件以停止通信并释放总线。
Figure 9 显示了从从机寄存器读取单个字节的示例。.
Figure 9. I2C 读取从机寄存器的示例