当前位置: 首页 > ds >正文

I2C 通信协议

I2C 通信协议

1. I2C 简介

  • I2C(Inter IC Bus)是由Philips公司开发的一种通用数据总线;
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data);这两根线都是主机在控制。
  • 同步,半双工;
  • 带数据应答;
  • 支持总线挂载多设备(一主多从、多主多从);一主多从就是单片机作为主机,主导 I2C 总线的运行,挂载在 I2C 总线的所有外部模块都是从机,从机只有被主机点名之后才能控制 I2C 总线,不能再未经允许的情况下去碰 I2C 总线,防止冲突。多主多从是在总线上任何一个模块都可以主动跳出来,控制总线,但是同一个时间只能有一个模块控制总线,当多个模块同时要控制总线时,就产生了总线冲突,I2C 协议会进行仲裁,决定一个模块取得控制权,失败的一方自动变回从机,由于时钟线也是由主机控制的,所以在多主机模型下,还需要进行时钟同步。多主机情况下,协议是比较复杂的。

2. 硬件电路

  • 所有I2C设备的SCL连在一起,SDA连在一起;
  • 设备的SCL和SDA均要配置成开漏输出模式;
  • SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右;

在这里插入图片描述
上面的 CPU 作为主机,主机的权力很大,包括对 SCL 线的完全控制,任何时候,都是主机完全掌控 SCL 线。在空闲状态下,主机可以主动发起对 SDA 的控制,只有在从机发送数据和从机应答的时候,主机才会转交 SDA 的控制权给从机。从机的权利比较小,对于 SCL 时钟线,在任何时刻都只能被动的读取,从机不允许控制 SCL 线;对于 SDA 数据线,从机不允许主动发起对 SDA 的控制,只有在主机发起读取从机的时候或者从机应答的时候,从机才能短暂地取得 SDA 的控制权。

I2C 所有的设备,包括 CPU 和被控 IC,引脚的内部结构都是下图这样的:
在这里插入图片描述
左边是 SCL 的结构,右边是 SDA 的结构,都包含输入和输出。首先引脚的信号进来,都可以通过一个数据缓冲器或者是斯密特触发器进行输入到 IN 口,因为输入对电路没有任何影响,所以任何设备在任何时刻都是可以输入的。但在输出的部分,也就是 OUT 口,采用的是开漏输出的配置,所有设备都只能输出低电平而不能输出高电平,为了避免引脚浮空,所以都需要在 SCL 和 SDA 各外置一个上拉电阻,通过一个电阻拉到高电平的,属于弱上拉。

开漏模式有一个特点:“线与”,只要有任意一个或多个设备输出低电平,总线就处于低电平;只有所有设备都输出高电平,总线才处于高电平。I2C 就是利用这一特性,执行多主机模式下的时钟同步和总线仲裁。

所以这里 SCL 虽然在一主多从模式下可以用推挽模式,但是它仍然采用了开漏加上拉输出的模式。因为多主多从要用到这个模式。

3. I2C 时序基本单元

3.1 起始和终止条件

  • 起始条件:SCL 高电平期间,SDA 从高电平切换到低电平。
  • 终止条件:SCL 高电平期间,SDA 从低电平切换到高电平。

在这里插入图片描述
在 I2C 总线处于空闲状态时,SCL 和 SDA 都处于高电平状态,也就是没有任何一个设备去碰 SCL 和 SDA。SCL 和 SDA 由外挂的上拉电阻拉高至高电平,总线处于平静的高电平状态。当主机需要进行数据收发时,要先打破总线的高电平,产生一个起始条件。当从机捕获到 SCL 高电平,SDA 下降沿信号时,就会进行自身的复位,等待主机的召唤。主机要在把 SCL 拉低,一方面是占用这个总线,另一方面是为了方便这些基本单元的拼接,就是保证除了起始和终止条件,每个时序单元的 SCL 都是以低电平开始,低电平结束。这样这些单元拼接起来,SCL 才能续得上。

起始和终止都是由主机产生的,从机不允许产生起始和终止。在总线空闲状态时,从机必须始终双手放开,不允许主动跳出来,去碰总线。如果允许的话,就是多主机模型了。

3.2 发送一个字节

  • 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节。

在这里插入图片描述

起始条件之后,SCL 处于低电平,主机如果想发送0,就拉低 SDA 到低电平,如果想发送 1,就放手,SDA 回弹到高电平。在 SCL 低电平期间,允许改变 SDA 的电平;当放好一位数据之后,主机就松手时钟线,SCL 回弹到高电平。在高电平期间,是从机读取 SDA 的时候。一般都是在 SCL 的上升沿的时候,从机就已经读取完成了。因为时钟是主机控制的,从机并不知道什么时候就会产生下降沿,所以从机在上升沿时,就会立刻把数据读走。主机过以一段时间之后就可以继续拉底 SCL,传输下一位。主机需要在 SCL 下降沿之后尽快把数据放在 SDA 上。主机有SCL的控制权,所以只需要在低电平的任意时刻把数据放在 SDA 上就行。数据放完之后,主机再松手 SCL,SCL高电平继续下一个比特的传输。就这样的流程,在 SCL 的同步下,依次进行主机发送和从机接收。循环八次就发送了八位数据。

由于这里有时钟线进行同步,所以如果主机一个字节发送一半,突然进中断了,不操作 SCL 和 SDA了,时序就会在中断的位置不断拉长。SDA 和 SCL 就会暂停变化,传输也完成暂停,等中断结束后,主机回来继续操作。传输仍然不会出问题,这就是同步时序的好处。

上面整个过程是主机发送一个字节,所以 SDA 和 SCL全程由主机掌控,从机只能被动读取。

3.3 接收一个字节

  • 接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA,释放 SDA 相当于切换成输入模式,可以这样理解,所有设备包括主机都始终处于输入模式,当主机需要发送的时候,就可以主动去拉低 SDA,而主机在被动接收的时候,就必须先释放 SDA,因为总线是线与的特征,任何一个设备拉低了,总线就是低电平,如果接收的时候,还不释放 SDA,那别人无论发什么数据,总线都始终是低电平)。

在这里插入图片描述

实线部分表示主机控制的电平,虚线部分表示从机控制的电平。

SCL 全程由主机控制。SDA 主机在接收前要释放,交由从机控制。因为 SCL 时钟是由主机控制的,所以从机的数据变换基本上都是贴着 SCL 下降沿进行的,而主机可以在 SCL 高电平的任意时刻读取。

3.4 应答机制

  • 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。发送应答位的目的是告诉从机是否还要继续发。如果从机发送一个数据后,得到了主机的应答,那从机就会继续发送。如果从机没得到主机的应答,就会释放 SDA,交出 SDA 的控制权,防止干扰主机之后的操作。
  • 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)。在调用发送一个字节之后,就要紧跟着调用接收应答的时序,用来判断从机有没有收到刚才给它的数据,如果从机收到了,在应答位这里,主机释放 SDA 的时候,从机就应该立刻把 SDA 拉下来,然后在 SCL 高电平期间,主机读取应答位。如果应答位为 0,就说明从机确实收到了。这个场景就是主机刚发送一个字节,然后把 SDA 放手,SDA 回弹高电平,如果有接收到的从机,就会把 SDA 拉下来,然后主机会在 SCL 高电平的时候读取数据,就会发现有人把 SDA 拽下来了,就会知道对方接收到了。如果主机读取到 SDA 在它释放之后,并没有被拽下来,就说明没有人回应,或者收到了没有回应。

在这里插入图片描述

4. I2C 时序

每个设备都有确定一个唯一的设备地址。主机在起始条件之后,要先发送一个字节叫一下从机名字。所有从机都会收到第一个字节,和自己的名字进行比较,如果不一样,就可以认为主机没有喊我,之后的时序就可以不管了。如果一样就说明,主机现在在叫我,就要响应之后主机的读写操作。在同一条 I2C 总线里,挂载的每个设备地址必须不一样。

从机设备地址,在 I2C 协议标准里分为 7 位地址(比较广泛)和 10 位地址。每个 I2C 设备出厂时,厂商都会为它分配一个 7 位的地址。一般不同型号的芯片地址都是不同的,相同型号的芯片地址都是一样的。当相同的芯片挂载在同一条总线时,就需要用到地址中的可变部分,一般器件地址的最后几位是可以在电路中改变的。

4.1 指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)。

在这里插入图片描述
先发送设备地址,再指定设备地址中某个寄存器的地址,然后再发送数据。

SCL 和 SDA 在空闲状态下都是高电平,在 SCL 高电平的情况下,SDA 拉低,产生起始条件。紧跟着的时序是发送一个字节的时序。字节的内容是从机地址+读写位(0表示写,1表示读),从机地址是 7 位,读写位是 1 位。发送从机地址就是确定通信的对象。发送读写位就是确认接下来是要写入还是读出。SCL 低电平期间,主机变换 SDA 数据;SCL 高电平期间,从机读取 SDA 数据。

当发送完一个字节之后,紧跟着的单元就得是接收从机的应答位(Receive Ack,RA)。在这个时刻,主机要释放 SDA,引脚电平回弹到高电平,根据协议规定,从机要在这个位拉低 SDA。应答位结束后,从机就要释放 SDA。

从机设备可以自己定义第二个字节和后续字节的用途,一般第二个字节可以是寄存器地址或者是指令控制字等。

第三个字节发送完毕之后,如果不需要再继续传输数据了,就可以产生一个停止条件(Stop,P)。在停止条件之前,先拉低 SDA,为后续 SDA 的上升沿做准备。然后释放 SCL,再释放 SDA。这样就产生了 SCL 高电平期间,SDA 的上升沿,也就产生了停止条件。

4.2 当前地址读

对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)。当前地址读不能指定读的地址。

在这里插入图片描述

当第一个字节的最后一位是读的情况下,第二个字节,数据的传输方向就要反过来,主机要把 SDA 的控制权交给从机。主机调用接收一个字节的时序,进行接收操作。从机得到主机的允许,可以在 SCL 低电平期间写入 SDA,然后主机在 SCL 高电平期间读取 SDA。主机在 SCL 高电平期间依次读取 8 位,就接收到了从机发送的一个字节数据。

这里会出现一个问题,I2C 协议规定,在主机进行寻址时,一旦读写标志位给 1 了,表示读,下一个字节就要立马转为读的时序,所以主机还来不及指定,想要读哪个寄存器就的开始接收了,所以这里就没有指定地址这个环节。但主机没有指定地址,从机应该发哪个寄存器的数据呢?在从机中,所有的寄存器被分配到一个线性区域中,并且会有一个单独的指针变量指示这其中一个寄存器,这个就是当前地址指针。这个指针上电默认指向 0 地址,每写入一个字节和读出一个字节后,这个指针就会自增一次。

4.3 指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)。

在这里插入图片描述

我们参考指定地址写的时序,一开始两个字节的时序,是指定地址的时序(发送设备地址和寄存器地址),把后面写数据的部分去掉,然后追加到这个当前地址读时序的前面,就得到了指定地址读的时序。但是中间会多一个 Sr(Start Repeat),重复起始条件,相当于另起一个时序。因为指定读写标志位只能是跟着起始条件的第一个字节,所以想要切换读写方向,只能再起一个起始条件。起始条件后重新寻址并指定读写标志位。

如果要读取多个字节,最后的时序可以多个,读完一个字节后再上一个Ack,然后重复这个过程,就可以读取多个字节。

如果只想读一个字节,在读完一个字节之后,一定要给从机发送一个非应答(Send Ack, SA),就是该主机应答时,主机不把 SDA 拉低。从机读到 SDA 为 1,就表示主机没有应答。从机收到非应答后,就知道主机不想要继续了。从机就会释放总线,把 SDA 控制权交还给主机。然后主机应答了,从机就会认为主机还要数据,就会读取下一个指针指向的数据并发送。

从机控制 SDA 发生一个字节的权利,开始于读写标志位为 1,结束于主机给应答为 1。

http://www.xdnf.cn/news/10987.html

相关文章:

  • Java并发编程:读写锁与普通互斥锁的深度对比
  • GitHub 趋势日报 (2025年06月02日)
  • Excel表格批量下载 CyberWin Excel Doenlaoder 智能编程-——玄武芯辰
  • IP查询与网络风险的关系
  • 基础知识掌握
  • 构建基于深度学习的人体姿态估计系统 数据预处理到模型训练、评估和部署 _如何利用人体姿态识别估计数据集_数据进行人体姿态估计研究的建议Human3.6M
  • Web前端为什么要打包?Webpack 和 Vite 如何助力现代开发?
  • 【Redis】set 类型
  • 腾讯下乡了。。。
  • Linux远程连接主机——ssh命令详解
  • 适老化场景重构:现代家政老年照护虚拟仿真实训室建设方案​
  • 结构性设计模式之Composite(组合)
  • AUTOSAR CP——Can模块
  • 游戏开发常见数据压缩
  • [蓝桥杯]上三角方阵
  • Termux下如何使用MATLAB
  • Kdump 介绍与使用方式
  • PyTorch 入门学习笔记(数字识别实战)
  • SoloSpeech - 高质量语音处理模型,一键提取指定说话人音频并提升提取音频清晰度和质量 本地一键整合包下载
  • java-springboot文件上传校验之只允许上传excel文件,且检查不能是脚本或者有害文件或可行性文件
  • 【氮化镓】钝化层对p-GaN HEMT阈值电压的影响
  • DrissionPage 异常处理实战指南:构建稳健的网页自动化防线
  • 第二章 2.TCP IP Protocol Suite(CCNA)
  • Flask 应用的生产环境部署指南
  • Java基础 Day28 完结篇
  • Python Day42
  • 定时通知群内值班人功能
  • POJO,DTO,VO和Model
  • 深入解读 MCP(Model Context Protocol):大模型时代的“操作系统协议”
  • js-day7