详解I2C

I2C(也常写作 I I C IIC IIC I 2 C I^2C I2C),全称为Inter-Integrated Circuit(“互连集成电路”),用于在集成电路之间进行短距离数据传输。它由Philips(现在的NXP半导体)公司于1980年代初开发,并成为一种广泛应用于电子设备之间通信的标准。I2C协议简单、灵活且广泛支持,常用于连接传感器、存储器、显示屏和其他外设到微控制器、微处理器或其他集成电路上。这是一种简单的双向双线总线,非常适合用于微控制器与外设之间,或者多个微控制器之间的高效互连控制。

其名称反映了最初的设计目的:它专为“集成电路”间的通信设计。I2C的两条线包括SDA(串行数据线),用于传输信息;和SCL(串行时钟线),负责同步。I2C的一个优点是它只需要这两根线进行通信,这可以在复杂系统中有效地利用资源。

它也是一种在许多产品中广泛使用的标准,扩展和集成相对简单。

I2C的主要特点包括:

  • 通信方式:I2C采用主从式通信方式。一个主设备(通常是微控制器或处理器)控制总线并发起通信,而一个或多个从设备被动地响应主设备的命令或请求。
  • 总线结构:I2C使用两根线路进行通信:
    • SCL(Serial Clock):时钟线由主设备提供,用于同步通信速度。
    • SDA(Serial Data):数据线用于传输数据和控制信号。
  • 信号电平:I2C使用双向开漏(open-drain)输出,这意味着信号线可以被拉低(逻辑0)但不能被主动拉高,只能通过外部上拉电阻回到高电平(逻辑1)。
  • 地址和帧格式:I2C使用7位或10位的设备地址来唯一标识每个从设备。通信帧包括设备地址、读/写位、数据字节和应答位(ACK)。
  • 速率和模式:I2C支持不同的通信速率,通常有标准模式(100 kbit/s)和快速模式(400 kbit/s)。还有更高速的模式如高速模式(3.4 Mbit/s)和超高速模式(5 Mbit/s)。
  • 启动和停止条件:I2C通信的开始由主设备发送启动信号(SDA从高电平切换到低电平,同时SCL保持高电平)表示。通信结束时,主设备发送停止信号(SDA从低电平切换到高电平,同时SCL保持高电平)表示。
  • 多主设备支持:I2C协议允许多个主设备共享同一条总线,通过仲裁机制来解决总线竞争问题。
  • 应用领域:I2C广泛应用于各种设备和应用领域,例如传感器、存储器(如EEPROM)、显示屏、温度传感器、实时时钟(RTC)、扩展IO芯片等。

I2C是一种简单、灵活且广泛支持的串行通信协议,适用于在电子设备之间进行短距离数据传输。它具有较低的硬件复杂性和通信开销,因此在许多嵌入式系统和电子设备中被广泛采用。

I2C协议还有一些其他的特性和扩展,如高速模式、高容量模式、地址扩展等,以满足更复杂的应用需求。虽然I2C并不适合所有情况(例如,它并不适用于长距离或高速应用),但它是一种常见的、实用的选择,适用于简单的内部通信。当希望许多从设备共享通信线并由一个(或多个)主设备管理时,它特别有用。

I2C总线通用连接框图:

I2C总线互联系统示意图

在单主机系统中,可以抽象为:

单主机I2C总线

典型的多主机系统则为:

多主机I2C总线

电气特性

I2C使用开漏/开集电极结构,同时在同一数据线上使用输入缓冲器,这允许单个数据线用于双向数据流。

双向通信的开漏结构

开漏指的是一种输出类型,可以将总线拉低到某个电压(通常是地线),或者"释放"总线,让其被上拉电阻拉高。当总线被主设备或从设备释放时,上拉电阻(RPU)负责将总线电压拉高到电源电平。由于没有设备可以强制将线路拉高,这意味着总线永远不会遇到通信问题,其中一个设备尝试传输高电平,而另一个设备传输低电平,导致短路(电源电平到地)。I2C要求在多主设备环境中,如果主设备发送高电平,但检测到线路低电平(另一个设备将其拉低),则停止通信,因为另一个设备正在使用总线。推挽接口不允许此类自由,这是I2C的一个优点。

SDA/SCL内部基本结构

上图显示了在SDA/SCL线上的从设备或主设备的内部结构的简化视图,包括用于读取输入数据的缓冲器和用于传输数据的下拉场效应晶体管(FET)。设备只能将总线线路拉低(与地短接)或释放总线线路(对地高阻抗),并允许上拉电阻将电压拉高。这是在处理I2C设备时需要了解的重要概念,因为没有设备可以将总线保持高电平。这个特性是实现双向通信的关键。

拉低总线

如前所述,开漏结构只能将总线拉低,或者"释放"总线并由电阻将其拉高。下图展示了将总线拉低时的电流流动。希望传输低电平的逻辑会激活下拉场效应晶体管,提供对地的短路,将线路拉低。

拉低总线

释放总线

当从设备或主设备希望传输逻辑高时,它只能通过关闭下拉场效应晶体管来释放总线。这将使总线悬空,而上拉电阻将把电压拉高到电源电平,被解释为高电平。下图展示了通过上拉电阻的电流流动,将总线拉高。

释放总线

通信速率模式

速率模式

常规模式

高速模式

超快模式

接口规范

一般操作

I2C总线是一种标准的双向接口,使用控制器(即主设备)与从设备进行通信。除非被主设备寻址,否则从设备不能传输数据。I2C总线上的每个设备都有一个特定的设备地址,以区分其他在同一I2C总线上的设备。许多从设备在启动时需要进行配置,以设置设备的行为。这通常在主设备访问从设备的内部寄存器映射时完成,这些寄存器具有唯一的寄存器地址。一个设备可以有一个或多个寄存器,用于存储、写入或读取数据。

物理的I2C接口由串行时钟(SCL)线和串行数据(SDA)线组成。SDA和SCL线都必须通过上拉电阻连接到VCC电源。上拉电阻的大小取决于I2C线路上的电容量。只有当总线处于空闲状态时,才能启动数据传输。如果在停止条件之后,SDA和SCL线都保持高电平,总线将被认为是空闲的。

主设备访问从设备的一般过程如下:

  1. 如果主设备想要向从设备发送数据:

    • 主设备-发送器发送起始条件并寻址从设备-接收器
    • 主设备-发送器向从设备-接收器发送数据
    • 主设备-发送器通过停止条件终止传输
  2. 如果主设备想要接收/读取从设备的数据:

    • 主设备-接收器发送起始条件并寻址从设备-发送器
    • 主设备-接收器向从设备-发送器发送要读取的寄存器
    • 主设备-接收器从从设备-发送器接收数据
    • 主设备-接收器通过停止条件终止传输

起始和停止条件

I2C通信通过主设备发送起始条件(START condition)来初始化,并通过主设备发送停止条件(STOP condition)来终止。在SCL线为高电平时,SDA线上的高至低的跳变定义了起始条件。在SCL线为高电平时,SDA线上的低至高的跳变定义了停止条件。

起始和停止条件示例

重复起始条件

重复的起始条件(Repeated START condition)类似于起始条件(START condition),用作连续的停止条件和起始条件的替代。它在外观上与起始条件相同,但与起始条件不同,因为它发生在停止条件之前(总线不处于空闲状态)。这在主设备希望启动新的通信,但不希望通过停止条件使总线空闲,从而可能失去对总线的控制权(在多主设备环境中)时非常有用。

数据有效性和字节格式

在每个SCL时钟脉冲期间传输一个数据位。一个字节由SDA线上的八个位组成。一个字节可以是设备地址、寄存器地址或从从设备写入或读取的数据。数据以最高有效位(MSB)优先的顺序传输。在START和STOP条件之间,可以从主设备向从设备传输任意数量的数据字节。在时钟周期的高电平期间,SDA线上的数据必须保持稳定,因为当SCL为高电平时,数据线的变化被解释为控制命令(START或STOP)。

单字节传输示例

应答(ACK)和非应答(NACK)

接收器在每个数据字节(包括地址字节)后发送一个ACK位。ACK位允许接收器向发送器传达字节已成功接收,并且可以发送另一个字节。

在接收器发送ACK之前,发送器必须释放SDA线。为了发送ACK位,接收器在ACK/NACK相关的时钟周期(周期9)的低电平期间拉低SDA线,以便在ACK/NACK相关的时钟周期的高电平期间,SDA线保持稳定低电平。必须考虑到设置时间和保持时间。

当SDA线在ACK/NACK相关的时钟周期中保持高电平时,这被解释为非应答(NACK)。有几种情况会导致产生NACK:

  1. 接收器由于执行某些实时功能并且尚未准备好与主设备开始通信,因此无法接收或发送。
  2. 在传输过程中,接收器接收到无法理解的数据或命令。
  3. 在传输过程中,接收器无法接收更多的数据字节。
  4. 主设备接收器完成数据读取,并通过NACK向从设备表示这一点。

NACK波形示例

I2C数据

必须通过读取或写入从设备的寄存器来发送和接收数据。寄存器是从设备内存中包含信息的位置,无论是配置信息还是一些采样数据用于发送回主设备。主设备必须向这些寄存器中写入信息,以指示从设备执行任务。

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

向I2C总线上的从设备写入数据

要在I2C总线上写入数据,主设备将在总线上发送一个带有从设备地址的起始条件,并将最后一位(R/W位)设置为0,表示写入操作。在从设备发送应答位后,主设备将发送要写入的寄存器地址。从设备再次发送应答位,通知主设备它已准备好。然后,主设备将开始向从设备发送寄存器数据,直到主设备发送完所有需要的数据(有时仅为一个字节),然后通过发送停止条件终止传输。

下图显示了向从设备寄存器写入单个字节的示例:

向从设备寄存器写数据示例

从I2C总线上的从设备读取数据

从从设备读取数据与写入数据非常相似,但有一些额外的步骤。为了从从设备读取数据,主设备首先必须告知从设备它希望从哪个寄存器读取数据。主设备通过类似写入操作的方式开始传输,发送带有R/W位为0(表示写入)的地址,然后是要从中读取数据的寄存器地址。一旦从设备确认了寄存器地址,主设备将再次发送起始条件,然后发送带有R/W位为1(表示读取)的从设备地址。这次,从设备将确认读取请求,主设备释放SDA总线,但仍向从设备提供时钟。在此事务的这个阶段,主设备将变为主设备接收器,而从设备将变为从设备发送器。

主设备将继续发送时钟脉冲,但会释放SDA线,以便从设备可以传输数据。在每个数据字节结束时,主设备将向从设备发送一个ACK,表示主设备准备好接收更多数据。一旦主设备接收到了所期望的字节数,它将发送一个NACK,告知从设备停止通信并释放总线。主设备随后发送停止条件。

下图显示了从从设备寄存器读取单个字节的示例:

从从设备寄存器读数据示例

实例

这两天调试 【开源】调试利器:高速 USB 转 UART、SPI、I2C、JTAG 这个模块时捕捉了一些波形,可以结合前文一起理解:

实例1

对应代码:

result = ch347_driver.i2c_set(device_index, 1)
if result:print("Success to set I2C speed.")
else:print("Failed to set I2C speed.")result = ch347_driver.i2c_set_delay_ms(device_index, 1)
if result:print("Success to set I2C delay.")
else:print("Failed to set I2C delay.")result = ch347_driver.stream_i2c(device_index, b'\x13', 2)
if result:print("Success!")
else:print("Failed!")

实例2

对应代码:

result = ch347_driver.i2c_set(device_index, 1)
if result:print("Success to set I2C speed.")
else:print("Failed to set I2C speed.")result = ch347_driver.i2c_set_delay_ms(device_index, 1)
if result:print("Success to set I2C delay.")
else:print("Failed to set I2C delay.")result = ch347_driver.stream_i2c(device_index, b'\x12\x13\x14', 8)
if result:print("Success!")
else:print("Failed!")

总结

I2C总结

公众号 | FunIO
微信搜一搜 “funio”,发现更多精彩内容。
个人博客 | blog.boringhex.top

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/114646.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫基础之正则表达式

目录 一、什么是正则表达式? 二、re.compile()编译函数 三、group()获取匹配结果函数 四、常用匹配规则 4.1匹配单个字符 4.2匹配前字符次数 4.3匹配原生字符串 4.4匹配字符串开头和结尾 4.5分组匹配 五、re.match()开头匹配函数 六、re.search()全文搜索…

恒流电路的三种设计方案

作为硬件研发工程师相信对恒流电路不会陌生,本文介绍下三种恒流电路的原理图。 三极管恒流电路 三极管恒流电路 三极管的恒流电路,主要是利用Q2三极管的基级导通电压为0.6~0.7V这个特性;当Q2三极管导通,Q1三极管基级电压被拉低而…

lnmp架构-mysql2

4.mysql 组复制集群 首先对所有的节点重新初始化 因为对节点的数据一致性要求非常高 主从复制的时候 slave只会复制master的binlog日志 就是二进制日志 不会复制relay_log 在server1上 根据实际情况修改主机名和网段 log_slave_updateON 意思就是 当slave的sql线程做完之后…

【Unity-Cinemachine相机】虚拟相机(Virtual Camera)的本质与基本属性

我们可以在游戏进行时修改各个属性,但在概念上,最好将Virtual Camera 当作一种相机行为的“配置文件”,而不是一个组件。 我们的相机有几种行为就为它准备几种虚拟相机,比如角色移动就为它第三人称相机,瞄准就准备一个…

Ubuntu搭建web站点并发布公网访问【内网穿透】

文章目录 前言1. 本地环境服务搭建2. 局域网测试访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4. 配置固定二级子域名4.1 保留一个二级子域名4.2 配置二级子域名4.3 测试访问公网固定二级子域名 前言 网:我们通常说的是互联网&#xff1b…

Java设计模式:四、行为型模式-06:观察者模式

文章目录 一、定义:观察者模式二、模拟场景:观察者模式2.1 观察者模式2.2 引入依赖2.3 工程结构2.4 模拟摇号2.4.1 摇号服务接口2.4.2 摇号返回结果类 三、违背方案:观察者模式3.0 引入依赖3.1 工程结构3.2 添加摇号接口和实现3.2.1 摇号服务…

【锁】定时任务推送数据-redission加锁实例优化

文章目录 redission 加锁代码-有问题优化代码看门狗是什么? redission 加锁代码-有问题 /*** 收货入库物料标签(包装码)推送接口** throws Exception*/public void synReceiveMaterialTags() throws Exception {String tag DateFormatUtils.format(new Date(), &qu…

昨天面试的时候被提问到的问题集合(答案)

1、vue的双向绑定原理是什么?里面的关键点在哪里? Vue的双向绑定原理是基于Object.defineProperty或者Proxy来实现的,其关键点在于数据劫持,即对数据的读取和修改进行拦截,在数据发生变化时自动更新视图 2、实现水平垂…

frida动态调试入门01——定位关键代码

说明 frida是一款Python工具可以方便对内存进行hook修改代码逻辑在移动端安全和逆向过程中常用到。 实战 嘟嘟牛登录页面hook 使用到的工具 1,jadx-gui 2,frida 定位关键代码 使用jadx-gui 进行模糊搜索,例如搜索encyrpt之类的加密关键…

深入解析即时通讯App开发中的关键技术

即时通讯App开发在现代社交和通信领域中扮演着重要的角色。随着移动设备的普及和网络的高速发展,人们对即时通讯工具的需求不断增加。本篇文章将深入探讨即时通讯App开发中的关键技术,帮助读者了解该领域的最新动态和技术趋势。 基础架构和通信协议 现…

《Java极简设计模式》第05章:原型模式(Prototype)

作者:冰河 星球:http://m6z.cn/6aeFbs 博客:https://binghe.gitcode.host 文章汇总:https://binghe.gitcode.host/md/all/all.html 源码地址:https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

如何使用Unity制作一个国际象棋

LinnoChess1.0 该项目旨在做一些Unity小游戏项目开发来练练手 如果有更新建议请私信RWLinno 项目地址:https://github.com/RWLinno/LinnoChess 目前效果 能够正常下棋;能够编辑棋盘;能够SL棋局;能够记录棋谱;能够显…

机器学习——聚类算法一

机器学习——聚类算法一 文章目录 前言一、基于numpy实现聚类二、K-Means聚类2.1. 原理2.2. 代码实现2.3. 局限性 三、层次聚类3.1. 原理3.2. 代码实现 四、DBSCAN算法4.1. 原理4.2. 代码实现 五、区别与相同点1. 区别:2. 相同点: 总结 前言 在机器学习…

03-MySQL

1、什么是BufferPool? 1.1、Buffer Pool基本概念 Buffer Pool:缓冲池,简称BP。其作用是用来缓存表数据与索引数据,减少磁盘IO操作,提升效率。 Buffer Pool由缓存数据页(Page)和 对缓存数据页进行描述的控制块 组成,…

【基于空间纹理的残差网络无监督Pansharpening】

Unsupervised Pansharpening method Using Residual Network with Spatial Texture Attention (基于空间纹理的残差网络无监督泛锐化方法) 近年来,深度学习已经成为最受欢迎的泛锐化工具之一,许多相关方法已经被研究并反映出良好…

day27 String类 正则表达式

String类的getBytes方法 String s "腻害"; byte[] bytes s.getBytes(StandardCharsets.UTF_8); String类的new String方法 String ss "ss我的"; byte[] gbks ss.getBytes("gbk"); String gbk new String(gbks, "gbk"); String类的…

【两周学会FPGA】从0到1学习紫光同创FPGA开发|盘古PGL22G开发板学习之数码管动态显示(五)

本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 适用于板卡型号: 紫光同创PGL22G开发平台(盘古22K) 一:盘古22K开发板(紫光同创PGL22G开发…

【防火墙】防火墙NAT Server的配置

Web举例:公网用户通过NAT Server访问内部服务器 介绍公网用户通过NAT Server访问内部服务器的配置举例。 组网需求 某公司在网络边界处部署了FW作为安全网关。为了使私网Web服务器和FTP服务器能够对外提供服务,需要在FW上配置NAT Server功能。除了公网…

Questa Sim使用教程仿真-示例

Questa Sim0基础仿真教程 文章目录 一、 打开软件二、运行编译后的文件 一、 打开软件 1、新建工程 File -> New -> project 2、填写工程名称和工程位置然后点"ok" 3、编写或者添加文件,这里直接添加一个编写好的反相器的文件。 可关注公众号&a…

趣味微项目:玩转Python编程,轻松学习快乐成长!

💂 个人网站:【工具大全】【游戏大全】【神级源码资源网】🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 在学习Python编程的旅程…