无名sh · 2022年12月31日 · 上海市

i2c详解+送apb_i2c工程+送中英文协议

image.png
0.本文的内容目录
本文一共接近一万一千字,为了帮助大家阅读,我把本文的内容目录截图如下,大家根据需要阅读,或者一次阅读不完,下次再读的时候方便查阅。
image.png
image.png
1.I2C概述
I2C是Inter-Integrated Circuit(内部集成电路)的简称,是一种通用的总线协议。它是由Philips(飞利浦)公司,现NXP(恩智浦)半导体开发的一种简单的双向两线总线协议标准。

I2C 总线是一种非常流行的串行总线,用于单个或多个主机与单个或多个从机之间的通信。下图Figure 1 所示为嵌入式系统的典型 I2C 总线,其中使用多个从机。微控制器代表I2C 的主机,控制IO扩展器、各种传感器、EEPROM、ADC/DAC等。所有这些都由主机的2个引脚SCL和SDA控制。

image.png
2.I2C的电气特性
I2C使用漏极开路/集电极开路(open-drain/open-collector),在同一条线路上带有输入缓冲器(input buffer),允许将单条数据线用于双向数据流。

2.1SDA和SCL总线要接上拉电阻或电流源
SDA和SCL都是双向线路,将所有设备的SDA线全部连在一起构成SDA总线,将所有设备的SCL线全部连在一起构成SCL总线,工作地线GND共用,每个设备都可以通过SDA和SCL线,向外传输信号(高低电平)或者从外面接收信号(高低电平),这些互连设备中至少需要一个主机。

SDA和SCL信号线上,必须通过电流源或上拉电阻连接到正电源电压。因为I2C设备内部输出电路已设计成开漏(OD)输出或开集电极(OC)输出(如图1-14),所以要在总线上外接上拉电阻或电流源,用来给总线上提供高电平。
image.png
2.2为什么I2C接口内部是OD(OC)输出
I2C设备内部为什么要设计成OD或OC结构,而不设计成推挽结构呢?其目的是防止总线上进行“线与”时发生短路现象造成设备过热或损坏。因为如果设计成推挽结构(如图1-15),在SDA或SCL总线上,同一时刻某些设备输出高电平,某些设备输出低电平时,连接电源的上拉开关管和连接地的下拉开关管之间就会短路,导致开关功耗过大(如有限流保护)或者烧坏器件。对于单个主机(一主多从)应用,如果从机也没有延长时钟的功能,那么控制器(主机)的SCL输出可以设计为推挽驱动输出。
image.png
2.3为什么I2C接口内部不集成上拉电阻
为什么不采用图1-15那样,把外部的上拉电阻集成到设备(芯片)内部去呢?上拉电阻集成到芯片内部,导致芯片结构复杂、芯片功耗增大以及无法兼容不同电源电压的设备(如下图所示)。
image.png
芯片内部不集成上拉电阻,共用外部的上拉电阻,其作用有三:①简化芯片内部电路;②减小芯片内部功耗;③不同电源供电的设备可以做到高电平信号兼容(如下图所示)。
image.png
2.4使用漏极开路(open-drain)进行双向通信
漏极开路是指一种输出类型,它可以将总线拉低到某个电压(在大多数情况下为接地),或者“释放”总线,让它被上拉电阻拉起。如果总线被主机或从机释放,线路上的上拉电阻 (RPU) 负责将总线电压拉至电源轨(power rail:参考下面的注释[1])。由于没有任何设备可以在线路上强制设置高电平,这意味着总线永远不会遇到,一个设备可能尝试发送高电平,而另一个设备发送低电平,从而导致短路(电源轨对地)的通信问题。I2C 要求,如果多主机环境中的一个主机准备传输高电平,但看到线路为低电平(另一个设备正在将其拉低),这时由于另一个设备正在使用总线,因而将会停止通信。推挽式(push-pull,参考下面注释)接口不允许这种类型的自由,这是 I2C 的优势。

注:

[1]power rail, 电源轨是指上拉电阻所接入的电源电压VCC,但由于上拉电阻(kohm)与FET关断时候的超大阻抗(Mohm)分压,导致总线上的电压会略低于VCC。但是由于分压电阻差距过大,一般是认为相等的。

[2]推挽输出的是由两个互补的三极管或者MOS管组成,始终保持一个导通,另一个截止的状态,假如一个主机A使用推挽输出高电平,另一个主机B使用推挽输出低电平,这时候电流将通过VCC流过主机A的上管,主机B的下管到地,总线的电压由两个管子的导通电阻进行分压,如果管子一致性较好,那么总线上的约为 VCC的一半。

[3]推挽输出的特性决定了其不能用于多主机的环境中,但是由于推挽输出的能力比漏极开路输出的能力强太多(因为没有上拉电阻的限流作用),在I2C 的超快速模式(5Mbit/s)中要求必须使用推挽输出,才能满足信号的时序要求,在这个模式下,只能沿一个方向传输数据,用于驱动 LED 控制器和其他不需要反馈的设备时,它最有用。

[4]漏极开路输出允许线与(与门)的逻辑功能,导致某个设备输出为低时,线路就是低电平,而输出高电平时,可以通过输入缓冲器来判断总线的电平,就不需要再修改IO口的输入输出模式了,对于代码编写软件模拟I2C 来说是极其方便低电平,而输出高电平时,可以通过输入缓冲器来判断总线的电平,就不需要再修改IO口的输入输出模式了,对于代码编写软件模拟I2C 来说是极其方便的。
image.png
Figure 2是SDA/SCL线上的主机或从机设备的内部结构简化图,它包含了用于读取输入数据的缓冲器和用于传输数据的下拉FET。设备只能将总线拉低(提供对地短路)或释放总线(对地高阻抗),并允许上拉电阻升高电压。这是在处理I2C设备时要实现的一个重要概念,没有设备可以将总线一直保持在高位。这一特性允许进行双向通信。

2.1.1 漏极开路拉低
如上所述,漏极开路设置可能只会将总线拉低,或“释放”总线并让电阻将其拉高。Figure 3显示了将总线拉低时的电流流动。想要传输低电平的逻辑将激活下拉FET,这将提供对地短路,将线路拉低。
image.png
2.1.2 漏极开路释放总线
当从设备或主设备希望传输逻辑高电平时,它只能通过关闭下拉FET来释放总线。这使总线浮动,上拉电阻将电压拉至电压轨,这将被解释为高。图4显示了通过上拉电阻将总线拉高的电流流动。
image.png
3.I2C接口
3.1接口概述
I2C总线很受欢迎,因为它使用简单,可以有多个主机和多个从机,并且只需要两条带上拉电阻的导线就可以连接几乎无限数量的I2C设备。I2C可以使用具有通用I/O引脚的更慢的微控制器,因为除了读取和写入字节的功能外,它们只需要生成正确的启动和停止条件。

每个从机都有一个唯一的地址。传输是串行的,它被分成8位数据包。所有这些简单的要求使得即使使用没有特殊I2C硬件控制器的廉价微控制器,实现I2C接口也非常简单。您只需要2个空闲的I/O引脚和几个简单的i2C例程就可以发送和接收命令。

I2C总线规范描述了双向数据传输的五种操作速度类别:
image.png
基本的I2C通信使用8位或字节的传输。每个I2C从设备都有一个7位地址,需要在总线上唯一。还有一些设备具有规范允许的10位地址。7位地址表示第7位至第1位,而第0位用于向设备发出读写信号。如果位0(地址字节中)设置为1,则主设备将从从I2C设备读取。主设备不需要地址,因为它生成时钟(通过SCL)并寻址各个I2C从设备。在正常状态下,两条线路(SCL和SDA)均为高电平。通信由主设备发起。

两个信号(SCL和SDA)都是双向的。它们通过电阻器连接到正电源电压。这意味着当总线空闲时,两条线路都很高。总线上的所有设备必须具有集电极开路或漏极开路引脚。激活线路意味着将其下拉(线与)。单个总线上的设备数量几乎是无限的。唯一的要求是总线电容不超过400 pF。由于逻辑1电平取决于电源电压,因此没有标准总线电压。

大多数I2C设备支持重复起始条件。这意味着在通信以停止条件结束之前,主机可以用地址字节重复开始条件,并将模式从写入更改为读取。

3.2 I2C术语
【发送器】–这是将数据传输到总线的设备

【接收器】–这是从总线接收数据的设备

【主机】–这是生成时钟、启动通信、发送I2C命令和停止通信的设备

【从机】–这是侦听总线并由主设备寻址的设备

【多主机】–I2C可以有多个主机,每个主机都可以发送命令

【仲裁】–当更多主机需要使用总线时,确定总线上哪些主机可以使用仲裁的过程

【同步】–同步两个或多个设备的时钟的过程

3.3 常规的I2C操作
I2C总线是一个标准的双向接口,它使用一个控制器(称为主控制器)与从设备通信。从设备不能传输数据,除非它已被主设备寻址。I2C总线上的每个设备都有一个特定的设备地址,以区分同一I2C总线中的其他设备。许多从设备在启动时需要配置以设置设备的行为。这通常在主机访问具有唯一寄存器地址的从机内部寄存器映射时完成。设备可以具有存储数据的一个或多个寄存器,

物理I2C接口由串行时钟(SCL)和串行数据(SDA)线组成。SDA和SCL线必须通过上拉电阻器连接到VCC。上拉电阻器的大小由I2C线路上的电容量决定。数据传输只能在总线空闲时启动。如果在STOP条件后SDA和SCL线都为高电平,则总线被视为空闲。主设备访问从设备的一般程序如下:

1主机要向从机发送数据:

[1]主机发送START条件并寻址从机(发送从机地址);

[2]主机向接收数据的从机发送数据;

[3]主机在STOP条件下终止传输。

2主机希望接收/读取从机数据:

[1]主机发送START条件并寻址从机(发送从机地址);

[2]主机发送要访问的寄存器地址(位于从机内)进行读取;

[3]主机接收从机过来的数据;

[4]主机发送STOP条件终止传输。

3.3.1 开始/停止条件
I2C通信由主机发送START条件启动,并由主机发送STOP条件终止。当SCL为高时,SDA线上的高到低转换定义了START条件。当SCL为高时,SDA线上的低到高转换定义STOP条件。

image.png
在启动条件之后,总线被认为是繁忙的,只有在检测到停止条件之后,才能由另一个主机使用。在“开始”条件之后,主机可以生成重复的“开始”。这相当于正常启动,通常后跟从I2C地址。

具有专用I2C硬件的微控制器可以很容易地检测总线变化,也可以作为I2C从设备。然而,如果I2C通信在软件中实现,则总线信号必须在每个时钟周期至少采样两次,以便检测必要的变化。

3.3.2 重复起始条件
重复起始条件类似于开始条件,用于代替背靠背的先停止后启动条件。它看起来与START条件相同,但其实与START条件不同,因为它发生在STOP条件之前(当总线不空闲时)。当主机希望启动新的通信,但不希望在STOP条件下让总线空闲时,这很有用,这可能会导致主机失去对另一主机的总线控制(在多主机环境中)。
image.png
3.3.3 位传输
对于每个时钟脉冲,传输一位数据。SDA信号只能在SCL信号为低时发生变化。当时钟为高时,数据应该是稳定的。
image.png
3.3.4 数据传输
image.png
I2C协议总线上的数据以8位数据包(字节)传输。对字节数没有限制,但是,每个字节后面必须跟一个确认位ACK。该位指示设备是否准备好继续下一个字节。对于包括确认位ACK在内的所有数据位,主机必须生成时钟脉冲。如果从设备未确认传输,这意味着没有更多数据或设备尚未准备好进行传输。主设备必须生成停止或重复启动条件。
image.png
3.4 数据有效性和字节格式
在SCL的每个时钟脉冲期间传送一个数据位。SDA线上的一个字节由八位组成。字节可以是设备地址、寄存器地址,也可以是从设备写入或读取的数据。

数据首先传输最高有效位(MSB)。任何数量的数据字节都可以在START和STOP条件之间从主设备传输到从设备。SDA线上的数据必须在时钟周期的高相位期间保持稳定,因为SCL为高时数据线的变化解释为控制命令(START或STOP)。
image.png
3.5 ACK和NACK
每个数据字节(包括地址字节)后面跟着来自接收器的一个ACK位。ACK位允许接收机与发射机通信,表明字节已成功接收,并且可以发送另一个字节。在接收机发送ACK之前,发射机必须释放SDA线路。为了发送ACK位,接收机应在ACK/NACK相关时钟周期的低相位(周期9)期间下拉SDA线,以使SDA线在ACK/ACK相关时钟时段的高相位期间稳定为低电平。必须考虑设置和保持时间。当SDA线在ACK/NACK相关时钟周期(周期9)期间保持高电平时,这被解释为NACK。有几个条件导致NACK的产生:

[1]总线上不存在带有发送地址的接收器,因此没有设备做出应答。

[2]接收器无法接收或发送,因为它正在执行某些实时功能,并且尚未准备好与主机开始通信。

[3]在传输过程中,接收器接收到它不理解的数据或命令。

[4]在传输过程中,接收器无法接收更多的数据字节。

[5]主接收机完成数据读取,并通过NACK向发送器发送传输结束的信号。
image.png
3.6 时钟同步
在空闲总线时,两个主机可以同时启动传输,必须有一种方法来决定由哪一个主机来控制总线并完成传输。这是通过时钟同步和仲裁两个步骤来完成的。在一主多从的系统中,不需要时钟同步和仲裁。
image.png
参考上图,使用设备的SCL接口和SCL总线之间的“线与”连接来执行时钟同步。主机一的SCL接口一旦检测到SCL总线上由高电平到低电平的转换时,主机一便拉低自己的SCL,并开始倒计数应有的SCL低电平保持时间,直到应有的低电平时间结束,便把SCL时钟拉到高电平状态。如果另一个主机二的SCL时钟仍然处于低电平周期内,则主机一的SCL时钟由低到高的转换不会改变SCL总线为低电平的状态,则主机一的SCL时钟进入高电平等待状态。因此,SCL总线被具有最长低电平周期的主机保持在低电平。

当所有相关的主机都已完成其低电平周期的计数时,SCL时钟总线被释放并变为高电平。主机SCL接口和SCL总线的状态之间保持一致,都为高电平。所有主机开始计算它们的高电平周期。第一个完成高电平周期的主机再次将SCL线拉低。

这样,就产生了同步的SCL总线时钟,其低周期由具有最长时钟低周期的主机确定,其高周期由具有最短时钟高周期的主机确定。

3.7 时钟拉伸(Clock stretching)
正如我们前面所说的,主机决定时钟速度。然而在某些情况下,I2C从设备不能与主设备给出的时钟速度协作,需要稍微减速。这是通过一种叫做时钟拉伸的机制来完成的。

如果需要降低总线速度,I2C从机可以保持时钟。另一方面,主机需要在将时钟信号释放到高状态之后读取时钟信号,并等待直到线路实际变高。

在传输一个字节时,从机可能能够快速接收数据字节,但需要更多时间来存储接收到的字节或准备要传输的字节,如果基于以上原因无法立即进行下一个字节的传输时,那么从机在接收完一个字节并应答后,可以将SCL线(主机输出)的低电平继续拉低并保持,以强制主机进入等待状态,直到从机做好了传输下一个字节的准备。

时钟拉伸通过保持 SCL线路低电平来暂停事务。在该线路再次释放为高电平之前,事务无法继续。时钟拉伸是可选的,实际上,大多数目标设备都不包含 SCL 驱动程序,因此它们无法拉伸时钟。
image.png
3.8 总线仲裁
对于I2C总线上的正常数据传输,只能激活一个主设备。如果出于某种原因,两个主机同时启动I2C命令,则仲裁程序确定哪个主机获胜并可以继续执行该命令。当SCL信号为高时,对SDA信号执行仲裁。每个主机检查总线上的SDA信号是否对应于生成的SDA。如果总线上的SDA信号为低电平,但应该为高电平,则该主机已失去仲裁。失去仲裁的主I2C设备可以生成SCL脉冲,直到字节结束,然后必须释放总线并进入从属模式。仲裁程序可以继续,直到所有数据被传输。这意味着在多主机系统中,每个I2C主机必须监控I2C总线的冲突并相应地采取行动。

仲裁协议用于多主机的系统中,单主机系统不需要仲裁。仲裁程序发生在主机之间,从机不涉及仲裁。只有当总线空闲时,主机才可以启动传输。两个主机同时发起启动后,总线需要对这两个主机进行仲裁,以确定最终由哪个主机控制总线并完成其传输。

设备的SDA接口线每次输出电平后,会立即回读SDA总线电平,用来判断自己的输出是否与总线一致。SCL线和SDA一样,也有这种回读判读机制。

仲裁由SCL线和SDA线一起配合来完成的,其分工如下:

SCL线负责时钟同步:两个主机在空闲状态时,同时发起启动,然后各自根据自己的时序要求拉低SCL总线输出低电平,释放SCL总线输出高电平,根据前面章节介绍的SCL时钟同步机制实现时钟同步。

SDA线负责数据仲裁:仲裁是在SDA线上一位一位地进行的。在每一位传输期间,当SCL为高电平时,每个主机各自判断自己SDA线输出的电平是否与SDA总线电平一致(回读判读机制),如果某主机发现输出电平和回读电平不一致,则该主机仲裁失败,失去对总线的控制权,随即关闭自己SDA输出驱动器,另一个主机赢得仲裁获取对总线的控制权,继续完成它的传输事务。这种仲裁过程可能需要进行很多位。

image.png
在仲裁过程中,赢得仲裁的主机不会丢失任何信息,仲裁失败的主机可以继续产生时钟脉冲,直到其仲裁失败的字节结束,并且可以在总线空闲时重新发起仲裁。

如果一个主机也具有从机的功能,并且在寻址阶段仲裁失败,那么获胜的主机可能正在尝试寻址它。因此,失败的主机必须立即切换到其从机模式。根据连接到总线的主机数量,以上的仲裁方式也适合更多主机的系统。由于对I2C总线的控制完全由参与竞争的主机发送的地址和数据决定,所以总线上没有中央控制器,也没有任何优先级顺序。

当一个主机发送重启或停止信号,而另一个主机仍在发送数据时,如果仲裁程序仍在进行中,则会出现未定义(异常)的状态。换句话说,以下组合会导致异常情况:

主机1发送重启信号,主机2发送数据位(所以重启前一定要判断重启建立时间)。

主机1发送停止信号,主机2发送数据位。

主机1发送重启信号,主机2发送停止信号。

3.9 7位从机地址的读写
数据传输遵循下图中所示的格式。主机在启动后,发送从机地址,该地址为7位长度。后面第8位是数据传输方向位,逻辑“1”代表读(R),表示接下来的数据由从机发送给主机,逻辑“0”代表写(W),表示接下来的数据由主机发生给从机。

image.png
3.9.1 主机写从机
如果主机仅写入从机,则数据传输方向不会改变。

image.png
3.9.2 主机读从机
如果主机只需要从从机读取,那么它只需发送具有设置为读取的R/W位的I2C地址。之后,主机开始读取数据。
image.png
3.9.3 混合读写(传输过程中改变方向)
有时主机需要写入一些数据,然后从从机读取。在这种情况下,它必须首先写入从机,改变数据传输方向,然后读取设备。这意味着发送R/W位设置为写的I2C地址,然后发送一些附加数据,如寄存器地址。在写入完成之后,主设备生成重复的开始条件,并发送具有设置为读取的R/W位的I2C地址。此后,数据传输方向改变,主设备开始读取数据。
image.png
3.10 10位寻址
大多数兼容I2C总线的从机具有7位从机地址编码,理论上可以在总线连接128个从机设备,为了在同一总线上连接更多的从机设备,I2C规范增加了10位地址编码的从机,理论上从机可以扩展到1024个。目前10位寻址设备没有被广泛使用。具有7位和10位地址的设备可以连接到同一个I2C总线,可用于所有总线速度模式。

如下图所示,10位从机地址由启动(S)或重启(Sr)信号后的前两个字节构成:①第一个字节的前七位是组合1111 0XX,其中前五位(1111 0)是特殊规定且不可更改的;后两位(XX)是10位地址的两个最高有效位(MSB );第一个字节的第八位是决定信号方向的R/W位。②第二个字节是10位地址的低8位。

前面针对7位寻址设备描述的读/写格式的所有组合对于10位寻址也是适合的。这里举2个例子来进一步说明10位地址的用法:

3.10.1 10位地址写操作
如下图所示,主机向具有10位从机地址的从机发送数据。传输方向不变。主机启动发送第一个寻址字节,每个从机判读第一个寻址字节的第八位(R/W方向位)是否为0,如果为0,每个从机将第一个寻址字节的前七位(1111 0XX)与其自身地址进行比较,这时前七位地址相同的从设备会同时产生应答(A1);接着主机发送第二个寻址字节(XXXXXXXX),所有从机将该地址(XXXXXXXX)的全部八位与它们自己的地址进行比较,但是只有一个从机找到匹配并产生应答(A2),找到匹配的从机继续保持被寻址状态,直到收到停止(P)或重启(Sr)信号。

image.png
3.10.2 10位地址读
主机从带有10位从机地址的从机读取数据。主机启动后发送第一个寻址字节和第二个寻址字节后,只有一个从机被寻址。在重复的开始条件(Sr)之后,匹配的从机记得它以前被寻址过。然后,该从机检查重启(Sr)之后的主机第一个字地址节的前七位是否与自己的相同(此时无需第二个寻址字节),并测试第八个(R/W)位是否为1,如果前七位相同、第八位是1,从机认为它已经作为发送器被寻址,并产生应答A3。从机继续保持被寻址,直到收到停止(P)或重启(Sr)信号。由于重启(Sr)后的第一个寻址字节的第八位(R/W)是R(1),所以其他从机都不会被寻址。

image.png
3.11 特殊保留地址
I2C地址的分配由负责分配的I2C总线委员会管理。保留两组8个I2C地址供将来使用,一个地址用于10位I2C寻址。其特殊作用如下:
image.png
通用呼叫地址用于寻址从属总线上的所有设备。如果任何从属设备不需要响应此类呼叫或从属设备不支持常规呼叫,则必须忽略该呼叫。如果设备支持普通呼叫并希望接收数据,则必须确认地址并作为从属接收器读取数据。

3.11.1 广播寻址
广播寻址(00000000)用于同时寻址连接到I2C总线的每个设备。

[1]如果设备不需要广播提供的任何数据,它可以回复NACK来忽略广播地址;

[2]如果设备需要来自广播的数据,会对广播地址进行ACK,并作为一个从接收设备;

[3]如果多个设备响应广播地址ACK,主设备并不知道有多少个设备回应。每个能够处理此数据的从接收设备第二个和后面的字节ACK。

一般广播地址的含义总是在地址的第二个字节中指定,如下图:
image.png
当LSB=0时,
image.png
当LSB=1时,

[1]当LSB=1时,2个字节的地址序列是一个硬件通用调用。

[2]这意味着地址序列是由硬件主设备传输的,例如键盘扫描器。第二个字节剩下的7位包含硬件主设备地址,这个地址会被一个连接到总线的智能设备(例如微控制器)识别,然后总线接受来自硬件设备的信息。

[3]由于硬件主设备实现不知道消息必须要传输到哪个设备,因此它只能生成这个硬件通用调用和他自己的地址,然后标识给系统。
image.png
3.11.2 起始字节(start byte)
微控制器有两种方式连接到I2C总线上。有片上的硬件I2C总线接口的微控制器可以变成为只接收总线的中断请求。当设备没有这样的接口,它必须要通过软件手段来检测总线。很明显,微控制器检测的时间或者轮询总线的时间越多,实现自己功能的时间就越少。

因此快速硬件设备和依赖软件轮询的相对慢速微控制器是有速度差别的。在这种情况下,数据传输前有一个比正常时间长很多的起始过程。起始过程组成如下:

一个开始条件(S)& 一个开始字节(0000 0001)& 应答位(ACK)&重复的开始条件(Sr)
image.png
主机发送完开始条件后,发送开始字节(0000 0001)。另外的微控制器可以以低采样率来采样SDA线知道开始字节的7个0中的一个被侦测到。在侦测到SDA线的低电平后,微控制器可以切换到更高的采样率来探测用于同步的重复开始条件。

在开始字节后一个应答相关的时钟脉冲产生。设备不允许应答开始字节。

3.11.3 总线清除(bus clear)
总线清除指的是清除总线被卡死在低电平的故障,使其恢复正常状态。

在极少数情况下,如果SCL时钟总线被卡在低电平(长时间陷在低电平状态),对其正确的处理方式为:①如果您的I2C设备有硬件复位输入,那么首先使用硬件复位信号复位I2C总线。②如果I2C设备没有硬件复位输入,则重启电源供电以强制激活设备内部硬件上电复位(POR)电路,实施开机复位I2C总线状态机。

在极少数情况下,如果SDA数据总线被卡在低电平(长时间陷在低电平状态),对其正确的处理方式为:①主机应发送9个时钟脉冲,将SDA总线保持在低电平的设备应该会在这9个时钟周期内的某个时间将其释放。②如果9个时钟周期内没有释放,则使用硬件复位或重启电源复位来清除总线。

3.11.4 设备ID
在出厂前,芯片制造商将设备ID(身份编码)存储在芯片内部的只读存储空间,如下图所示,设备ID包含内容如下:

[1] 12位芯片制造商名称编码,每个制造商都是唯一的(例如”0000 0000 0000”代表恩智浦)。

[2] 9位芯片器件标识码,芯片制造商分配(例如AT24C02)。

[3] 3位芯片版本,由制造商指定(例如RevX)。
image.png
设备ID是只读的,在设备中是硬连线的,可以通过以下方式访问:

[1] 主机发送启动(S)信号。

[2] 主机发送设备ID(特殊保留的)地址 “1111 1000”,最后一位R/W位一定要为“0”,表示“写”操作;可能有多个从机应答。

[3] 主机发送从机设备地址。此时,代表传输方向LSB位无关紧要,“0”或“1” 均可。只有一个从机设备必须应答该字节。

[4] 主机发送重启(Sr)信号。注意:启动(S)信号会重置从机,并且无法执行设备ID读取。此外停止(P)或重启(Sr)后访问另一个从机设备也会重置原来的从机,并且无法执行设备ID读取。

[5] 主机发送设备ID(特殊保留的)地址 “1111 1001”,最后一位R/W位一定要为“1”,表示“读”操作。

[6] 主机接收完设备ID第一个字节并应答,然后接收完设备ID第二字节并应答,最后接收设备ID第三个字节。注意:以上读取的三个字节就是设备ID,包含 12个制造商位(第一个字节+第二个字节的4个MSB)、9个器件标识位(第二个字节的4个LSB+第三个字节的5个MSB)、3个芯片版本位(第三个字节的3个LSB)。

[7] 主机通过不应答最后一个字节来结束读取操作,从而重置从机状态机,从机转为等待主机发送停止(P)信号的状态。备注:主机通过发送NACK,可以随时停止读取设备ID的操作。如果主机在收到第三个字节后继续应答,从机就回滚到第一个字节,并继续重复发送设备ID序列,直到检测到NACK。

  1. I2C数据传输的例子
    数据必须发送到从机或接收来自从机的数据,但实现这一点的方式是读取或写入从机中的寄存器。

寄存器是Slave‘s memory中包含信息的位置,无论是配置信息还是要发送回主机的一些采样数据。主机必须将信息写入这些寄存器,以便指示从机执行任务。

虽然I2C从设备中有寄存器是常见的,但请注意,并非所有从设备都有寄存器。有些设备很简单,只包含一个寄存器,可以通过在从地址之后立即发送寄存器数据而不是寻址寄存器来直接写入。单个寄存器设备的一个例子是一个8位I2C开关,它通过I2C命令进行控制。由于它有1位来启用或禁用信道,所以只需要1个寄存器,而主机只需在从属地址之后写入寄存器数据,跳过寄存器号。

4.1通过I2C总线写从机
要在I2C总线上写入,主机将在总线上发送一个启动条件,其中从机的地址以及设置为0的最后一位(R/W位)表示写入。在从机发送确认位后,主机将发送它希望写入的寄存器的地址。从机将再次确认,让主机知道它已经准备好了。此后,主机将开始向从机发送寄存器数据,直到主机发送了所需的所有数据(有时这只是一个字节)主机将在STOP条件下终止传输。

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

[1]主机在开始信号之后,需要先发送寻址字节,其中第0位为0表示主机要向从机写数据。

[2]从机在接收到每个数据之后,需要发送ACK信号,表示成功接收到数据。

[3]主机在发送完数据之后,发送停止信号。
image.png
4.2通过I2C总线读从机
读从机与写非常相似,但需要额外的步骤。为了读取从机,主设备必须首先指示从机它希望从哪个寄存器读取数据。这是通过主机以与写入类似的方式开始传输,发送R/W位等于0(表示写入)的地址,然后是它希望读取的寄存器地址来完成的。一旦从设备确认该寄存器地址,主设备将再次发送START条件,随后是R/W位设置为1的从设备地址(表示读取)。这一次,从设备将确认读取请求,主设备释放SDA总线,但将继续向从设备提供时钟。在事务的这一部分,主设备将成为主接收机,从设备将成为从发射机。

主设备将继续发送时钟脉冲,但将释放SDA线路,以便从设备可以传输数据。在数据的每个字节结束时,主机将向从机发送ACK,让从机知道它已经准备好接收更多数据。一旦主设备接收到预期的字节数,它将发送NACK,向从设备发出信号以停止通信并释放总线。主机将使用STOP(停止)条件进行跟踪。
image.png
下图完整的展示了主机由从机读取数据的时序图,需要注意的是:

[1]主机在开始信号之后,需要先发送寻址字节,其中第1位为1,表示主机由从机读取数据。

[2]主机在接收到每个数据之后,需要发送ACK信号,表示成功接收到数据。

[3]主机在接收完最后一个字节的数据之后,发送“NACK”表示接收完成,之后,从机放弃SDA的控制权,主机发送停止信号,数据接收过程结束。

image.png

  1. 送apb_i2c工程和中英文协议
    关注微信公众号《芯片验证日记》,后台回复”i2c”,可得apb_i2c工程和中英文协议对应的百度链接。连接中的内容如下图所示:
    image.png
  2. 参考文献:
    [1] https://baijiahao.baidu.com/s...

[2] https://baijiahao.baidu.com/s...

[3] https://blog.csdn.net/lhl_blo...

[4] https://embetronicx.com/tutor...

[5] https://blog.csdn.net/qq_3894...

[6] https://blog.csdn.net/qq_3894...

[7] Understanding the I2C Bus, TEXAS INSTRUMENTS

[8] UM10204 I2C-bus specification and user manual

[9] I2C Interface Technical Deep Dive

[10] THE I2C-BUS SPECIFICATION VERSION 2.1

[11] I2C总线规范

  1. 同类文章推荐

SPI协议详解+送apb_spi和ahb_spi工程

详解SPI通信协议

uart协议详解+送apb_uart项目

写文章不易,如果觉得对您有帮助,麻烦一键三连,或者赏个鸡腿也行!

推荐阅读
关注数
7
文章数
10
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息