STM32软件I2C通信详解

news2024/11/16 11:54:20

目录

18.[江协]I2C通信详解

I2C通信介绍

软件I2C和硬件I2C的区别

I2C硬件电路规定

I2C软件设计(时序基本单元)

起始条件与终止条件

主机发送一个字节 的时序单元

主机接收一个字节 的时序单元

主机/从机 应答 基本单元

I2C完整时序(拼接基本单元)

从机设备的地址

指定地址写

当前地址读

指定地址读


I2C通信介绍

I2C总线 的英文全称是:Inter IC BUS

他有两根通信线:SCL (Serial Clock)、SDA(Serial Data) 串行时钟线和串行数据线 支持总线挂载多设备。可以是一主多从和多主多从

  1. 一主多从的意思是单片机作为主机主导I2C总线的运行,其他挂载在I2C总线上的都是从机。从机只有被主机点名之后,才能控制I2C总线。就像老师点了你的名字之后你才能说话。
  2. 而多主多从模式是:每个模块都可以突然站出来,说接下来我是主机,你们听我的。 这时候如果有其他人说我也要当主机, I2C也会有一个仲裁器来仲裁, 优先级高的胜利。失败的自动变为从机。

I2C通信属于 半双工 同步 多设备 带数据应答的 通信

而USART是 全双工 异步 点对点的通信

  • 半双工 是可以双向传输,但每次只能有一个传输方向
  • 全双工 是既可以双向传输,它又可以同时有两个传输方向。
  • 异步的好处是省下一根时钟线,节省资源。缺点是对时间要求严格,对硬件电路依赖严格。
  • 同步时钟的好处是。对时间要求不严格,对硬件电路不依赖。稳定性也比异步的好,容易使用软件来模拟时序,缺点是多一根时钟线。
  • 多设备则是在一根数据线上挂载很多的设备。在访问其中某个设备时。其他的设备对通信没有影响。

I2C通信可以理解外,通过一根时钟线和一根数据线。 来链接单片机外的外设。 并且可以读写其中指定的寄存器。实现这个外挂模块的完全控制

比如MPU6050模块,可以进行姿态测量。 它就使用了I2C通信协议 或者OLED模块,可以显示字符、图片等信息。也使用了I2C通信协议 以及AT24C02存储器模块。也是I2C的通信协议

或者DS3231 实时时钟模块。也是使用I2C通信。

因为使用通用的协议。对于开发者来说是很方便的

软件I2C和硬件I2C的区别

  • 硬件电路件I2C的波形更加规整,时钟周期和占空比非常一致。

    每个时钟周期后都有严格的延时,保证每个周期的时间相同。

    硬件电路需要专门的某些GPIO口才能实现

  • 软件I2C的波形较为不规整,每个时钟周期和空闲时间都不一致。

    软件I2C时的引脚操作会有一定的延时,因此各个时钟周期的间隔和占空比都不均匀。

    但是软件实现I2C更加的方便,随便那个GPIO口都可以实现。

I2C硬件电路规定

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

为什么呢?

因为只有一根数据线,所以采用的是半双工的协议。

在一主多从的模式下,主机的SCL线可以是推挽输出状态。来拥有对SCL的绝对控制权。 (但是仍然采用的是开漏输出+上拉电阻的模式。因为在多主机模式下会用到这个特性) 所有从机的SCL线都配置为 浮空输入 或者 上拉输入 数据的流向为 主机发送,所有的从机只能被动接收, 这样是没问题的

**但SDA就不能这样了。**因为数据线是只有一条。 主机在接收的时候是输入,在发送的时候是输出。 同样,从机的SDA也会在输入和输出之间反复切换。 如果这时使用的是推挽输出模式下。 在总线没协调好两个设备的时序的情况下。就会出现两个设备都是输出的状态。如果此时一个输出高电平。另一个输出低电平。**就会出现电源对地短路的情况。**如图:

这是应该极力避免的。

所以,在I2C这里的解决办法是,禁止所有设备为强制上拉的高电平 采用了外置弱上拉电阻 加 开漏输出的电路结构。如图:

在开漏输出模式下,每个引脚的内部结构如图:

可以看到。不管是SCL 还是SDA
在输入时 都可以随便输入。对电路不会有影响

在输出高电平时 只需要打开自己所控制的mos管,外部的上拉电阻会拉为高电平。

在输出低电平时 只需要闭合自己所控制的mos管,外部的高电平会被强制拉低接地。

所以,开漏输出不同于推挽输出的强上拉强下拉。

开漏输出 配合 上拉电阻 是弱上拉、强下拉

所以,这个模式会有一个 “线与” 的现象。即只要有任意一个或多个设备输出了低电平,总线就处于低电平。只有所有的设备都输出高电平。总线才输出高电平

所以,挂载在I2C总线上的 所有设备。 所有的GPIO 引脚 都要设置为 开漏输出的模式。 并且在SCL和 SDA两条线 添加上拉电阻

I2C软件设计(时序基本单元)

起始条件与终止条件

起始和终止,都是由主机产生的,从机不允许产生起始和终止

在I2C总线处于空闲状态时。SCL和SDA都被上拉为高电平。

当主机需要进行数据收发时,就会产生一个起始条件。 起始条件就是,时钟线不动,拉低SDA数据线。 当从机捕获到SCL时钟线为高电平。SDA数据线产生了下降沿信号时,就会进行自身的复位,等待主机点名。 然后主机会拉下SCL时钟线的电平。准备开始下一步动作。

终止条件是,主机先对SCL时钟线放手,让上拉电阻把SCL拉高为高电平,再对SDA数据线放手,产生一个上升沿。这个上升沿就会触发终止条件

此时就会恢复到最初的两个高电平的平静状态

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

主机发送一个字节 的时序单元

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

因为SCL同步时钟是主机在控制。从机并不知道什么时候时钟会消失。所以从机要尽快在SCL高电平期间读取主机所发送的电平信号(一般在主机松手的一刹那,上升沿来临时就已经读取了)。

主机也应该在SCL时钟线下降沿上尽快把数据放到SDA数据线上。 但是主机有对时钟线的主导权。即使中途有什么事情打断了主机放数据的操作。主机也可以一直拉低时钟SCL。等到把数据放到SDA上之后再松开SCL 使他恢复高电平(这也是同步时序的好处)。

在主机的主导的SCL时钟下。 SCL低电平,主机发送; 高电平,从机接收; 如此循环8次 就发送了8位数据,也就是一个字节

在发送一个字节的时序中,主机完全掌控SCL和SDA,从机只能被动的读取。

主机接收一个字节 的时序单元

与发送一个字节同理。这里实线是主机控制,虚线是从机控制。 时钟线SCL低电平期间,从机将数据位依次放到SDA数据线线上**(高位先行**),然后释放SCL, 主机将在SCL高电平期间读取数据位 所以SCL高电平期间SDA不允许有数据变化, 依次循环上述过程8次即可读取一个字节

主机在接收之前,必须释放SDA(因为总线是线与的特征)

如图:

可以看到。主机在接收前,释放了SDA数据线。 这时数据线的主导权到了某个从机的手中。 但是SCL时钟线的主导权还是在主机这里。从机只能等待时钟为下降沿时被动发送。所以也是要尽快的发送,否则错过低电平的时期就不好啦(一般在下降沿来临后就已经发送了。贴着下降沿)。 主机则是在高电平任意时刻读取就行,反正主机能控制SCL时钟线

主机/从机 应答 基本单元

  • 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答在下一个时钟接收一位数
  • 接收应答:主机在发送完一个字节之后,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)

可以看出,接收方必须在接收到一个字节之后,在下一个时钟拉低SDA数据线,如果没有拉低,那么发送方就会认为 这次发送失败,没有人接收到。

如图:接收应答时,当主机释放SDA时,从机就应该立刻把SDA拉下来。在SCL高电平期间,主机读取应答位,如果应答位为0,就代表接收到。为1 代表没有接收到

同理,主机在接受到一个字节的时候,也要发送应答。拉低电平,然后使SCL为高电平,等待从机读取。在高电平期间,从机如果收到了主机的应答,他就可以继续执行操作。如果主机没有应答,那么 从机就会乖乖释放SDA的主导权,防止干扰主机之后的工作

I2C完整时序(拼接基本单元)

I2C的完整时序主要有3种

  • 指定地址写
  • 当前地址读
  • 指定地址读

从机设备的地址

主机可以访问总线上的任何一个设备,要把每个从机都确定一个唯一的设备地址 从机设备地址,在I2C协议里分为:7位地址和 10位地址 (这里主要是讲7位地址) 在每一个I2C设备出厂时,厂商就会给他分配一个I2C 7 位地址(可以在芯片手册中查看)

比如MPU6050的7位地址是1101 000 AT24C02的7位地址是1010 000 一般不同芯片的地址是不一样的。 相同芯片的地址是一样的。

为了应对总线上挂载相同芯片的情况:一般器件地址的最后几位,是可以在电路中通过地址改变引脚的高低电平来改变的。(比如MPU6050的AD0引脚就可以决定地址。 低电平为1101 000 接高电平为 1101 001 ;AT24C02地址的最后三位,都可以由板子的A0 A1 A2来确定)

指定地址写

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

对于指定设备(从机地址),在指定地址(寄存器地址)下写入数据。

空闲状态

  • 两条总线(SCL和SDA)都是高电平。

产生起始条件

  1. 主机在SCL高电平期间拉低SDA,产生起始条件。
  2. 在起始条件之后,主机发送一个字节,该字节内容为从机地址和读写位(从机地址是7位,读写位是1位,总共8位)。

发送从机地址和读写位

  1. 发送从机地址:确定通信的对象。
  2. 发送读写位:确认接下来是写入还是读出(0表示写入,1表示读出)。
  3. 接收应答位
  4. 主机发送从机地址和读写位后,释放SDA。
  5. 从机响应后会拉低SDA,产生应答位。
  6. 应答位产生后,从机释放SDA的控制权。

发送数据

  1. 主机再次发送第二个字节,通常为寄存器地址或控制字。
  2. 接着发送第三个字节,表示要写入寄存器地址中的数据值。

产生停止条件

  1. 主机拉低SDA,为后续的上升沿做准备。
  2. 然后依次释放SCL和SDA,产生SC**L高电平期间的SDA上升沿,**表示停止条件。

示例

对于从机地址为1101000的设备,在其内部0x19地址的寄存器中写入0xAA这个数据,数据帧的过程如下:

  1. 起始条件:SCL高电平期间,SDA从高电平拉低。
  2. 发送从机地址和读写位(1101000+0)。
  3. 接收从机应答位。
  4. 发送寄存器地址(0x19)。
  5. 接收从机应答位。
  6. 发送数据值(0xAA)。
  7. 接收从机应答位。
  8. 停止条件:SCL高电平期间,SDA从低电平释放至高电平。

通过这些步骤,主机可以可靠地在从机的指定寄存器地址中写入数据

当前地址读

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

产生起始条件

  • 主机在SCL高电平期间拉低SDA,产生起始条件。

寻址和读写操作

  1. 主机首先发送一个字节,用于从机的寻址和设置读写标志位。
  2. 在本次通信中,主机发送的目标地址是1101000,读写标志位为1,表示主机接下来要读取数据。

接收从机应答位

  1. 主机发送完寻址字节后,接收从机的应答位。
  2. 从机收到第一个字节后,拉低SDA,表示应答,并将SDA的控制权交回主机。

接收数据

  1. 主机调用接收数据的时序,准备接收从机发送的数据。
  2. 从机得到允许后,在SCL低电平期间将数据写入SDA。
  3. 主机在SCL高电平期间读取SDA上的数据。
  4. 主机在SCL高电平期间依次读取8位数据,从而接收到从机发送的一个字节数据(例如:0000 1111,即0x0F)。

指针自动递增

  1. I2C通信中没有指定寄存器地址的环节,默认情况下,从机中的所有寄存器被分配到一个线性区域中。
  2. 从机内部有一个指针变量,指向某个寄存器。上电时,这个指针通常默认指向0地址。
  3. 每次 写入 或 读出 一个字节后,这个指针会自动递增,指向下一个寄存器位置。
  4. 主机读取到的数据是当前指针指向的寄存器的值。

所以一般这个时序用的不是很多

指定地址读

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

对弈指定地址读,其实是先告诉设备我要写,当寄存器指向这个地址之后,我又不写了。我要读。

写入操作

  1. 指定从机地址和读写标志位: 从机地址为1101000,读写标志位为0,表示要进行写操作。
  2. 从机应答: 从机应答后,主机发送第二个字节(0001 1001),用于指定寄存器地址。 这个数据写入到从机的地址指针中,从机的寄存器指针指向0x19位置。

重复起始 开始读操作

  1. 产生一个新的起始条件: 主机再次产生一个起始条件。
  2. 重新寻址并指定读写标志位: 主机重新发送从机地址(1101000)和读写标志位(此时读写标志位为1,表示读操作)。
  3. 主机接收数据: 从机应答后,主机开始接收一个字节的数据。 这个字节的数据是从机0x19地址下的内容。

读写操作也不一定只能一次一个字节。 在主机读或写的时候,只要主机应答,从机就不会停。直到主机给非应答,从机才会停止,然后把SDA主导权交给主机。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python单元测试】学习笔记1

文章目录 01-单元测试基础什么是单元测试常用的文件结构运行单元测试 02. 断言函数03. Test Fixtures什么是Test Fixtures模块级别的Fixtures类级别的Fixtures方法级别的Fixtures 04.Mock python单元测试学习笔记1:https://blog.csdn.net/qq_42761751/article/detai…

kali实用工具之NC

NC(netcat)被称为网络工具中的瑞士军刀,体积小巧,但功能强大。Nc主要功能是可以在两台设备上面相互交互,即侦听模式/传。 1、传输数据 在kali开启监听6666端口号: 在centos连接kali的6666端口号&#xff1a…

LeetCode --- 410周赛

题目列表 3248. 矩阵中的蛇 3249. 统计好节点的数目 3250. 单调数组对的数目 I 3251. 单调数组对的数目 II 一、矩阵中的蛇 只要按照题目要求模拟即可&#xff0c;代码如下 class Solution { public:int finalPositionOfSnake(int n, vector<string>& commands…

Camera Link 与 NI PCIe-1433 的工作原理及应用

Camera Link 是一种专为工业和科学成像应用设计的串行通信协议标准。它的主要优势在于能够提供高带宽、高可靠性的图像数据传输&#xff0c;并且具备灵活的配置选项&#xff0c;适用于多种不同的摄像机类型。Camera Link 的标准使得它在需要高速度、高分辨率图像传输的应用中得…

Java流程控制08:continue、break、goto

本节内容视频链接&#xff1a;https://www.bilibili.com/video/BV12J41137hu?p43&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5https://www.bilibili.com/video/BV12J41137hu?p43&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 java中break和continue的作用和区别 在J…

通过kuboard界面配置ingress

安装 Ingress Controller&#xff0c;Kuboard 为您提供了一种快速安装 ingress-nginx 的方法&#xff0c;步骤如下所示。 1&#xff09;导航到集群的 集群管理 --> 网络 --> IngressClass 列表页&#xff0c;如下图所示&#xff1a; 2&#xff09;点击图中的 安装 Ingre…

WordPress美化节日灯笼插件,适合春节的时候使用

源码介绍&#xff1a; WordPress美化节日灯笼插件&#xff0c;适合每年过年的时候安在网站上使用&#xff0c;这款插件可以备用着&#xff0c;一款WordPress节日灯笼美化插件&#xff0c;可以给网页自动加一个灯笼效果使用说明&#xff1a;到网站WP后台 - 插件 - 安装插件 - 上…

可复制拖拽流程图

功能&#xff1a;如上图所示&#xff0c;从左侧拖拽源拖拽出模块后&#xff0c;在右侧显示。 源码&#xff1a;

【OpenCV 】插值的方法原理,图片缩放,矫正,边界填充

图像旋转 缩放 计算机中的图像是以数组的方式储存&#xff0c;每个位置储存了像素点的像素值。对图像进行旋转缩放&#xff0c;就是对数组进行操作&#xff0c;乘以对应的矩阵&#xff0c;进行空间变换&#xff0c;而矩阵的行列式的值&#xff0c;就是缩放的倍数。 进行缩放旋…

stm32智能颜色送餐小车(ESP8266WIFI模块、APP制作、物联网模型建立、MQTTFX)

大家好啊&#xff0c;我是情谊&#xff0c;今天我们来介绍一下我最近设计的stm32产品&#xff0c;我们在今年七月份的时候参加了光电设计大赛&#xff0c;我们小队使用的就是stm32的智能送餐小车&#xff0c;虽然止步于省赛&#xff0c;但是还是一次成长的经验吧&#xff0c;那…

在IntelliJ IDEA中使用Git推送项目

去gitee网站注册用户 gitee网站地址:https://gitee.com/ github网站地址:https://github.com/ 一、创建仓库 以下以gitee为例进行介绍&#xff0c;github操作雷同。 1、创建仓库 点击页面右上方的"“并选择"创建仓库” 2、设置仓库相关信息 首先输入仓库名&…

时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU

时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU 文章目录 前言时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU 一、PO-TCN-BiGRU模型1. 时间卷积网络 (TCN)2. 双向门控循环单元 (BiGRU…

Modbus-RTU使用过程中的问题

此程序是在visual studio 2005的MFC程序中执行的&#xff0c;通过引入ModbusRTU.dll进行程序的编程&#xff0c;通过Dependency Walker工具查看ModbusRTU.dll中的静态函数如下&#xff1a; 在ModbusRTU.h文件中 MOD_API WORD RTUReadDiscreteInputs(BYTE nSlaveAddress, WORD …

接口自动化测试,介入时间以及整个流程规范是怎样的?

最近&#xff0c;小编身边有人提出一个问题&#xff1a; 背景 公司的接口自动化是从开发提测的时候开始用例设计开发的&#xff08;因为我们公司没有接口文档&#xff0c;只能等开发完成后自己抓包&#xff09;&#xff0c;也就是接口自动化开发和功能测试是同时进行的&#…

Ubuntu 基础使用

一、下载Vmware workstation 和ubuntu映像文件 二、安装虚拟机 三、安装完成之后打开程序&#xff0c;选择创建新的虚拟机 选择映射文件 编辑信息 这里尽量选择一个特定的位置 根据自己的要求设定 设置完成后等待自己安装不需要进行操作 出现登录页面表示安装成功 四、基本指令…

K8S系列——(一)、Ubuntu上安装Helm

在使用K8S搭建集群服务时&#xff0c;有时候需要用到Helm&#xff08;一个用于Kubernetes应用管理的工具&#xff09;&#xff0c;下面是在Ubuntu上安装Helm的过程。 1.更新系统软件包列表 sudo apt-get update2.安装必要的依赖项 sudo apt-get install apt-transport-https…

怎么在网络攻击中屹立不倒

在当今蓬勃发展的网络游戏产业中&#xff0c;服务器安全无疑是企业生存与发展的基石。面对互联网环境中无处不在的DDoS&#xff08;分布式拒绝服务&#xff09;与CC&#xff08;挑战碰撞&#xff09;攻击威胁&#xff0c;游戏服务器的防御能力与高效处理能力显得尤为重要。相较…

11.2.0.4 RAC 节点1重做操作系统后如何复原

环境描述&#xff1a;Redhat7.9 11.2.0.4 RAC 双节点 实验背景 群里有大佬在交流RAC中1个节点操作系统坏了如何修复&#xff0c;故有了该实验。 在正常的生产环境当中&#xff0c;有时候会遇到主机磁盘以及其他硬件故障导致主机OS系统无法启动&#xff0c;或者OS系统本身故障…

C语言 | Leetcode C语言题解之第342题4的幂

题目&#xff1a; 题解&#xff1a; bool isPowerOfFour(int n) {return n > 0 && (n & (n - 1)) 0 && n % 3 1; }

Python3 第八十八课 -- AI 绘画

目录 一. 前言 二. Windows 环境安装 三. Civitai 介绍 一. 前言 本文我们将为大家介绍如何基于一些开源的库来搭建一套自己的 AI 作图工具。 需要使用的开源库为 Stable Diffusion web UI&#xff0c;它是基于 Gradio 库的 Stable Diffusion 浏览器界面 Stable Diffusio…