0,引言
在上一篇文章我们讲解了《I2C从入门到精通之五:I2C通信协议Protocol-写操作》,今天我们继续接着介绍I2C通信协议Protocol-读操作。读操作包含一次假写操作(Dummy Write)和一次读数据返回。那么为什么会这样呢?
所有I2C主题的文章都会收录在《深入浅出聊I2C》https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzU3NDY3OTA2Nw==&action=getalbum&album_id=4272525982776868870#wechat_redirect合集里,欢迎评阅。通过这个专集的阅读,你将成为I2C专家。
百度网盘分享的文件
上如是I2C学习资料和标准(pdf格式),需要下载的朋友,请关注本微信公众号“硬件工程师宝典”,在对话框内回复“I2C”,将获取标准下载链接。其中“I2C_Spec_Rev7_2021_UM10204.pdf”这份文件是最新的I2C specification, 希望大家重点阅读。
一、I2C读操作为什么包含一次假写操作(Dummy Write)
I2C读操作通常包含一次“写”和一次“读”的过程,这主要是为了指定从设备内部要读取的数据源(例如寄存器地址)。这种模式在许多具有内部寄存器映射的I2C从设备中非常常见,例如传感器、EEPROM、ADC等。
下面详细解释为什么会采用这种“先写后读”的模式:
1. 第一次“写”操作的目的:指定内部寄存器地址
许多I2C从设备不仅仅是一个简单的存储单元,它们内部包含多个功能块或数据存储区域,这些区域通过内部寄存器地址来区分。
当主设备想要从从设备读取数据时,它通常需要告诉从设备:“请给我你内部某个特定寄存器的数据。”
为了实现这个目的,主设备首先会发起一个写操作:
发送从设备地址+ 写位 (R/W = 0):这告诉总线上的所有设备,主设备要与某个从设备通信,并且是准备写入数据。
发送内部寄存器地址:主设备紧接着发送一个字节,这个字节就是它想要读取的从设备内部的寄存器地址。从设备接收到这个地址后,会将其内部的“数据指针”或“地址计数器”指向这个特定的寄存器。
这个“写”操作本身并没有传输实际的数据到从设备,它的作用是配置从设备,告知它接下来要从哪个位置提供数据。
这就是为什么我们先介绍写操作write的原因。
2. 重复起始条件 (Repeated START) 的作用
在指定完内部寄存器地址后,主设备需要立即切换到读模式,从该寄存器读取数据。
如果主设备发送一个停止条件(STOP Condition),然后再发送一个起始条件 (START Condition) 来开始读操作,那么总线会暂时释放,其他主设备可能会趁机占用总线,从而中断当前通信序列。
为了保持总线控制权,并确保读操作紧随写操作之后,主设备会发送一个重复起始条件。重复起始条件允许主设备在不释放总线的情况下,改变通信方向。
3. 第二次“读”操作的目的:实际读取数据
在重复起始条件之后,主设备会再次发送从设备的地址,但这次会将读位(R/W = 1) 设置为1。
这明确地告诉从设备:“现在,我准备从你那里读取数据了,请从你之前指向的那个内部寄存器开始发送数据。”
从设备收到这个读请求后,就会从其内部指定(通过第一次写操作)的寄存器开始,将数据发送给主设备。主设备则接收这些数据,并通过发送ACK/NACK来控制数据流。
4. 总结来说:
- 第一次“写”:不是为了写入数据,而是为了设置从设备内部的“读取地址”或“数据源”。
- 重复起始条件:用于在不释放总线的情况下,无缝地从设置模式切换到读取模式。
- 第二次“读”:才是真正从从设备获取数据的过程。
二.I2C读操作的数据流
以下是I2C读操作的典型数据流过程,如图1所示:
图1. I2C主设备master从从设备slave读取data的数据流
1) 起始条件 (START Condition):
当I2C总线空闲时(SCL和SDA线都为高电平),主设备通过在SCL线为高电平期间,将SDA线从高电平拉低来发出起始条件。这标志着一次通信的开始。
2)发送从设备地址和写操作位 (Slave Address + R/W bit = '0'):
主设备发送一个8位字节。
这个字节的前7位是从设备的唯一地址。
第8位是读/写 (R/W) 控制位,此时设置为'0',表示主设备最初是向从设备发送一个写请求(通常是为了指定要读取的内部寄存器地址)。
3) 从设备应答 (ACK from Slave):
在主设备发送完地址和读/写位后,它会释放SDA线。
如果总线上存在与该地址匹配的从设备,并且它已准备好通信,它会在第9个时钟周期将SDA线拉低,发送一个应答信号 (ACK)。
4) 发送内部寄存器地址 (Register Address, if applicable):
对于许多从设备(如EEPROM或传感器),主设备需要指定要读取数据的从设备内部寄存器地址。
主设备会发送一个8位字节,包含目标寄存器的地址。
5) 从设备应答 (ACK from Slave):
从设备接收到寄存器地址后,会再次发送一个ACK信号,确认已收到并准备好进行后续操作。
6) 重复起始条件 (Repeated START Condition):
此时,主设备需要将操作从“写”切换到“读”。它不会发送停止条件来终止当前传输,而是发送一个重复起始条件。
重复起始条件与普通起始条件相同:在SCL为高电平期间,SDA从高电平拉低。这允许主设备在不释放总线控制权的情况下改变传输方向。
7) 发送从设备地址和读操作位 (Slave Address + R/W bit = '1'):
主设备再次发送从设备的7位地址,但这次将读/写 (R/W) 控制位设置为'1',表示主设备现在要从从设备读取数据。
8)从设备应答 (ACK from Slave):
从设备接收到其地址和读请求后,会发送一个ACK信号,确认它已准备好发送数据。
9) 从设备发送数据字节 (Data Bytes from Slave):
从设备开始向主设备发送数据字节。
每个数据字节都是8位。
10) 主设备应答或非应答 (ACK/NACK from Master):
主设备在接收每个数据字节后,通常会发送一个ACK信号,表示它已成功接收该字节,并希望接收更多数据。
当主设备接收到最后一个期望的数据字节时,它会发送一个非应答信号(NACK)(即在第9个时钟周期保持SDA为高电平),通知从设备不再需要更多数据,并准备终止传输。
11)停止条件 (STOP Condition):
在主设备发送NACK后,它通过在SCL线为高电平期间,将SDA线从低电平拉高来发出停止条件。
这标志着一次通信的结束,并释放总线,使其返回空闲状态。
12) 关键点总结:
重复起始条件:是读操作中一个重要的环节,它允许主设备在不释放总线的情况下,从写模式切换到读模式。
主设备控制ACK/NACK:在读操作中,主设备负责在接收每个字节后发送ACK或NACK,以控制从设备是否继续发送数据。
R/W位:地址字节的最低位(R/W位)在读操作中会发送两次,第一次为'0'(写)以指定寄存器,第二次为'1'(读)以获取数据。
三.I2C读操作实例
我们以一款16 位精度的模数转换器(ADS1115)。
ADS1115 具有 16 位的 ADC,因此会输出 16 位的数据转换结果。控制器设备从转换寄存器读取以获取 ADC 转换数据。转换寄存器地址指针为 00h。转换数据以二进制补码形式呈现为 16 位的结果。正的满量程输入会产生 7FFFh 的输出代码,而负的满量程输入会产生 8000h 的输出代码。当 ADDR 引脚连接到 GND 时,该设备响应地址 48h。图 4-5 展示了在地址指针为 00h 时从转换数据寄存器读取的示例。
图2. I2C主设备master从ADS1115读取数据data实例
I2C 写操作始于一个起始条件。SDA 被拉低,然后 SCL 也被拉低。接着控制器会写入 I2C 地址。同样,设备会响应地址 100 1000(7bit 0x48,8bit 0x90)。控制器首先需要告知设备要从哪个寄存器读取数据。为此,通信首先向设备发送一个 I2C 写操作,以便设置从 ADS1115 的数据转换寄存器进行读取。此时,R/W 位被设置为低,表示通信从设备开始是写操作。当地址帧完成后,ADS1115 通过拉低地址帧的最后一个位来确认。
在表明控制器正在从ADS1115 读取数据之后,控制器告知设备要读取哪个寄存器。第二个字节是数据转换寄存器的寄存器指针。在此处,向 ADS1115 发送 00h。作为响应,ADS1115 拉低 SDA 以确认 ACK。最后,控制器发出停止信号以释放总线。
现在控制器已告知设备访问数据转换寄存器,接下来控制器会执行从该寄存器的读取操作。控制器再次写入I2C 地址。控制器已经指明了要读取哪个寄存器,现在控制器向设备发送读取指令,以便读取 ADS1115 的数据转换寄存器。此时,R/W 位被设置为高电平,表示进行读取操作。同样,在完成地址帧后,ADS1115 会确认地址。
接下来的两个数据字节用于读取该寄存器。第一个字节是转换数据的最高有效字节,然后第二个字节是最低有效字节转换数据的读取。控制器每次读取一个字节后都会收到一个确认信号。最后,控制器发送一个STOP 信号以结束 I2C 通信。
与前面的例子一样,图2是一个便于理解的示意图,展示了与该设备的 I2C 通信情况。如果在通信过程中出现任何问题,可以使用 SDA 和 SCL 的示波器波形图来进行对比,以与本示例的描述进行对照。
四, 抛砖引玉
在第五篇我们已经深入介绍I2C通信协议协议Protocol的写操作。这一节我们又学习了读操作,读操作包含一次假写操作(Dummy Write)和一次读数据返回。I2C的其它operation都是在读写操作的基础上组合而来,在此不一一赘述。
敬请关注下一篇:《I2C从入门到精通之七:I2C设备的电气特性electrical specifications》
五,参考文献:
需要以下参考文献(I2C标准)的朋友,请关注本微信公众号“硬件工程师宝典”,在对话框内回复“I2C”,将获取标准下载连接。其中“I2C_Spec_Rev7_2021_UM10204.pdf”这份文件是最新的I2C specification, 希望大家重点阅读。
百度网盘分享的文件