news 2026/3/25 14:51:32

I2C从入门到精通之六:I2C通信协议Protocol-读操作

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
I2C从入门到精通之六:I2C通信协议Protocol-读操作

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, 希望大家重点阅读。

百度网盘分享的文件

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/15 14:34:30

在duckdb 递归CTE中实现深度优先搜索DFS

原帖地址 https://github.com/duckdb/duckdb/discussions/15386 通常的递归CTE都是广度优先搜索(BFS) WITH RECURSIVE edges(a, b) as( VALUES(1, 2),(1, 3),(2, 4),(4, 5),(4, 6) ), bfs(node, path) AS (SELECT 1 AS node, [] :: STRUCT("from&…

作者头像 李华
网站建设 2026/3/22 21:13:28

基于记忆增强网络的语言模型推理优化

基于记忆增强网络的语言模型推理优化 关键词:记忆增强网络、语言模型、推理优化、注意力机制、深度学习 摘要:本文聚焦于基于记忆增强网络的语言模型推理优化。首先介绍了相关背景,包括研究目的、预期读者、文档结构和术语定义。接着阐述了核心概念,如记忆增强网络和语言模…

作者头像 李华
网站建设 2026/3/20 11:49:08

分类管理与分类统计 UI -Cordova 与 OpenHarmony 混合开发实战

欢迎大家加入[开源鸿蒙跨平台开发者社区](https://openharmonycross平台开发者社区](https://openharmonycrossplatform.csdn.net),一起共建开源鸿蒙跨平台生态。 本文对应模块:pages.js 中“分类统计”页面以及分类管理相关的 UI 结构,重点是…

作者头像 李华
网站建设 2026/3/24 9:08:02

AI也会“三思而后答“?揭秘Self-RAG智能检索术

当AI遇到"灵魂拷问"你问智能客服:"我的快递到哪儿了?"它回答:"根据牛顿第一定律,物体会保持匀速直线运动..."你会不会当场翻白眼?这就是传统AI系统的尴尬:有些问题明明知识库…

作者头像 李华