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

STM32—I2C通信外设

1.I2C外设简介

  • STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担
  • 支持多主机模型(可变多主机)
  • 支持7位/10位地址模式(11110......)
  • 支持不同的通讯速度,标准速度(高达100 kHz),快速(高达400 kHz)
  • 支持DMA(多字节读写)
  • 兼容SMBus协议,SMBus(System Management Bus),是系统管理总线,SMBus是基于I2C总线改进而来的,主要用于电源管理系统中,SMBus和I2C非常像
  • STM32F103C8T6 硬件I2C资源:I2C1、I2C2

硬件12C也有很多独有的优势:执行效率比较高,可以节省软件资源,功能比较强大,可以实现完整的多主机通信模型,时序波形规整,通信速率快,等等

如果你只是简单应用,可以选择比较灵活的软件I2C,如果你对性能指标要求比较高,就可以考虑一下硬件I2C

2.I2C框图

左边是这个外设的通信引脚SDA和SCL,这就是12C通信的两个引脚,这个SMBALERT是SMBus用的,12C用不到,不用管的,那像这种外设模块引出来的引脚,般都是借用GPIO口的复用模式与外部世界相连的,

首先上面这一块,是SDA,也就是数据控制部分,这里数据收发的核心部分,是这里的数据寄存器和数据移位寄存器,当我们需要发送数据时,可以把一个字节数据写到数据寄存器DR,当移位寄存器没有数据移位时,这个数据寄存器的值就会进一步转到移位寄存器里,我们就可以直接把下一个数据放到数据寄存器里等着了,一旦前一个数据移位完成,下一个数据就可以无缝衔接,继续发送,当数据由数据寄存器转到移位寄存器时,就会置状态寄存器的TXE位为1,表示发送奇存器为空,这就是发送的流程

那在接收时,也是这路,输入的数据,一位一位地从引脚移入到移位寄存器里,当一个字节的数据收齐之后,数据就整体从移位寄存器转到数据寄存器,同时置标志位RXNE,表示接收寄存器非空,这时我们就可以把数据从数据寄存器读出来了

至于什么时候收,什么时候发,需要我们写入控制寄存器的对应位进行操作,对于起始条件、终止条件、应管位什么的,这里也都有控制电路可以完成

下面这里还有两个功能,个是比较器和自身地址寄存器、双地址寄存器,另一个是帧错误校验计算和帧错误校验寄存器,

  • 比较器和地址寄存器这是从机模式使用的,刚才说了STM32的I2C是基于可变多主机模型设计的,STM32不进行通信的时候,就是从机,既然作为从机,它就应该可以被别人召唤,想被别人召唤,它就应该有从机地址吧,就可以由这个自身地址寄存器指定,我们可以自定一个从机地址,写到这个寄存器,当STM32作为从机,在被寻址时,如果收到的寻址通过比较器判断,和自身地址相同,那STM32就作为从机,响应外部主机的召唤,并且这个STM32支持同时响应两个从机地址,所以就有自身地址寄存器和双地址寄存器,这一块,我们需要在多主机的模型下来理解
  • 右边这部分这是STM32设计的一个数据校验模块,当我们发送一个多字节的数据帧时,在这里硬件可以自动执行CRC校验计算,CRC是一种很常见的数据校验算法,它会根据前面这些数据,进行各种数据运算,然后会得到一个字节的校验位,附加在这个数据的后面,在接收到这一帧数据后,STM32的硬件也可以自动执行校验的判定,如果数据在传输的过程中出错了,CRC校验算法就通不过,硬件就会置校验错误标志位,告诉你数据错了,使用的时候注意点,这个校验过程就跟串口的奇偶校验差不多,也是用于进行数据有效性验证的

下面SCL的这部分,时钟控制,是用来控制SCL线的,在这个时钟控制寄存器写对应的位,电路就会执行对应的功能,然后控制逻辑电路,也是黑盒子,写入控制寄存器,可以对整个电路进行控制,读取状态寄存器,可以得知电路的工作状态,之后是中断,当内部有一些标志位置1之后,可能事件比较紧急,就可以申请中断,如果我们开启了这个中断,那当这个事件发生后,程序就可以跳到中断函数来处理这个事件了

最后是DMA请求与响应,在进行很多字节的收发时,可以配合DMA来提高效率

3.I2C基本结构

首先移位寄存器和数据寄存器DR的配合,是通信的核心部分,这里因为l2C是高位先行,所以这个移位寄存器是向左移位,在发送的时候,最高位先移出去,然后是次高位,等等,一个SCL时钟,移位一次,移位8次,这样就能把一个字节,由高位到低位,依次放到SDA线上了

那在接收的时候呢,数据通过GPIO口从右边依次移进来,最终移8次,一个字节就接收完成了

之后GPI0口这里,使用硬件I2C的时候,这两个对应的GPIO口,都要配置成复用开漏输出的模式,复用,就是GPIO的状态是交由片上外设来控制的,开漏输出,这是12C协议要求的端口配置

然后SCL这里时钟控制器通过GPIO去控制时钟线,这里我简化成一主多从的模型了,所以时钟这里只画了输出的方向,实际上前面这里,如果是多主机的模型,时钟线也是会进行输入的

然后继续,SDA的部分,输出数据,通过GPIO,输出到端口,输入数据,也是通过GPIO,输入到移位寄存器,那这两个箭头连接在GPIO的哪个位置呢,

4.主机发送

当STM32想要执行指定地址写的时候,就要按照这个主发送器传送序列图来进行,这里有7位地址的主发送和10位地址的主发送,他们的区别就是,7位地址,起始条件后的一个字节是寻址,10位地址,起始条件后的两个字节都是寻址,其中前一个字节,这里写的是帧头,内容是5位的标志位11110+2位地址+1位读写位,然后后一个字节,内容就是纯粹的8位地址了,两个字节加一起,构成10位的寻址,这是10位地址的寻址方式

7位主发送这个时序呢,流程是起始,从机地址,应答,后面是数据1,应答,数据2,应答等等,最后是P,停止,因为12C协议只规定了起始之后必须是寻址,至于后面数据的用途,并没有明确的规定,这些数据可以由各个芯片厂商自己来规定,比如MPU6050规定就是寻址之后,数据1为指定寄存器地址,数据2为指定寄存器地址下的数据,之后的数据N,就是从指定寄存器地址开始依次往后写,这就是一个典型的指定地址写的时序流程

然后我们从头来看一下,首先,初始化之后,总线默认空闲状态,STM32默认是从模式,为了产生一个起始条件,STM32需要写入控制寄存器,手册中在这个控制寄存器CR1中,有个STAKT位,在这一位写1,就可以产生起始条件了,当起始条件发出后,这一位可以由硬件清除,所以,只要在这一位写1,STM32就自动产生起始条件了

之后,STM32由从模式转为主模式,也就是多主机模型下,STM32有数据要发,就要跳出来,这个意思,然后,控制完硬件电路之后,就要检查标志位,来看看硬件有没有达到我们想要的状态,在这里,起始条件之后,会发生EV5事件,这个EV5事件,你就可以把它当成是标志位,这个手册这里都是用EV(Event)几这个事件来代替标志位的,为什么要设计这个EV几,EV几事件,而不直接说产生什么标志位呢,这是因为,有的状态会同时产生多个标志位,所以这个EV几事件,就是组合了多个标志位的一个大标志位,在库函数中也会有对应的,检查EV几事件是否发生的函数,所以就当成是一个大标志位来理解就行了

当我们检测起始条件已发送时(EV5),就可以发送一个字节的从机地址了,从机地址需要写到数据寄存器DR中,写入DR之后硬件电路就会自动把这一个字节转到移位寄存器里,再把这一个字节发送到12C总线上,之后硬件会自动接收应答并判断,如果没有应答,硬件会置应答失败的标志位,然后这个标志位可以申请中断来提醒我们,当寻址完成之后,会发生EV6事件(地址发送结束),EV6事件结束后,是EV8_1事件,EV8_1事件就是TxE标志位=1,移位寄存器空,数据寄存器空,这时需要我们写入数据寄存器DR进行数据发送了,一旦写入DR之后,因为移位寄存器也是空,所以DR会立刻转到移位寄存器进行发送,这时就是EV8事件,移位寄存器韭空,数据寄存器空,这时就是移位寄存器正在发数据的状态,所以流程这里,数据1的时序就产生了,

在EV8后面没有了,写入DR密存器将清除该事件,所以按理说,这个位置应该是写入了下一个数据,也就是后面这个数据2,在这个时刻就被写入到数据寄存器里等着了,然后接收应答位之后,数据2就转入移位寄存器进行发送,此时的状态是移位寄存器非空,数据寄存器空,所以这时,这个EV8事件就又发生了,之后这个位置,数据2还正在移位发送,但此时下一个数据,已经被写到数据寄存器等着了,所以这个时候EV8事件消失,按照这个流程来,一旦我们检测到EV8事件,就可以写入下一个数据了,

最后,当我们想要发送的数据写完之后,这时就没有新的数据可以写入到数据寄存器了,当移位寄存器当前的数据移位完成时,此时就是移位寄存器空,数据寄存器也空的状态,这个事件就是这里的EV8_2,下面解释,EV8_2是TxE=1,也就是数据寄存器空,BTF (Bvte Transfer Finished),这个是字节发送结束标志位,所以在这里,当检测到EV8_2时,就可以产生终止条件了,显然,应该在控制寄存器里有相应的位可以控制

5.主机接收

主机接收的流程,这里有7位主接收和10位主接收,从这个7位主接收的时序看,这里时序的流程是起始,从机地址+读,接收应答,然后就是,接收数据,发送应答,接收数据,发送应答,最后一个数据,给非应答,之后终止,可以看出,这个时序应该是当前地址读的时序

下面10位地址的当前地址读,就复杂一些,这里是,起始,发送帧头,这个帧头里的读写位,应该还是写的,因为后面还要跟着发送第二个字节的地址,之后继续发送第二个字节的8位地址,这样才能进行寻址,然后要想转入读的时序,必须再发送重复起始条件,发送帧头,这次帧头的读写位就是读的了,因为发送读的指令之后,必须要立刻转入读的时序,所以这第二个字节的地址就没有了,直接转入接收数据的时序,这是10位地址的操作流程

7位:首先,写入控制寄存器的START位,产生其实条件,然后等待EV5事件,EV5事件就代表起始条件已发送,之后是寻址,接收应答,结束后产生EV6事件,EV6事件代表,寻址已完成,之后数据1这块,代表数据正在通过移位寄存器进行输入,EV6_1事件,下面解释是没有对应的事件标志,只适于接收1个字节的情况,这个EV6_1,可以看到,数据1其实还正在移位,还没收到呢,所以这个事件就没有标志位,之后当这个时序单元完成时,硬件会自动根据我们的配置,把应答位发送出去

如何配置是否要给应答呢,也是看手册:控制寄存器CR1里,这里有一位ACK:应答使能,如果写1,在接收到一个学节后就返回一个应答,写0就是不给应答,当这个时序单元结束后,就说明移位寄存器就已经成功移入一个字节的数据1了,这时,移入的一个字节就整体转移到数据奇存器,同时置RXNE标志位,表示数据寄存器非空,也就是收到了一个字节的数据,这个状态就是EV7事件,RXNE=1,数据寄存器非空,读DR寄存器清除该事件,也就是,收到数据了,当我们把数据读走之后,这个事件就没有了,上面这里,EV7事件没有了,说明此时数据1被读走,当然数据1还没读走的时候,数据2就可以直接移入移位寄存器了,之后,数据2移位完成收到数据2,产生EV7事件,读走数据2,EV7事件没有了,最后,当我们不需要继续接收时,需要在最后一个时序单元发生时,提前把刚才说的应答位控制寄存器ACK置0,并且设置终止条件请求,这就是EV7-1事件,和EV7一样后面加了一句,设置ACK=0和STOP请求,也就是我们想要结束了,之后,在这个时序完成后,由于设置了ACK=0,所以这里就会给出非应答,最后由于设置STOP位,所以产生终止条件,这样接收一个字节的时序就完成了

6.软件/硬件波形对比

相关文章:

STM32—I2C通信外设

1.I2C外设简介 STM32内部集成了硬件I2C收发电路,可以由硬件自动执行时钟生成、起始终止条件生成、应答位收发、数据收发等功能,减轻CPU的负担支持多主机模型(可变多主机)支持7位/10位地址模式(11110......)支持不同的通…...

Java-测试-Mockito 入门篇

之前很长一段时间我都认为测试就是使用SpringBootTest类似下面的写法&#xff1a; SpringBootTest class SysAuthServiceTest {AutowiredSysRoleAuthMapper sysRoleAuthMapper;Testpublic void test() {QueryWrapper<SysRoleAuth> queryWrapper new QueryWrapper<&g…...

【jupyter notebook】环境部署及pycharm连接虚拟机和本地两种方式

Python数据处理分析简介 Python作为当下最为流行的编程语言之一 可以独立完成数据分析的各种任务数据分析领域里有海量开源库机器学习/深度学习领域最热门的编程语言在爬虫&#xff0c;Web开发等领域均有应用 与Excel&#xff0c;PowerBI&#xff0c;Tableau等软件比较 Excel有…...

TypeScript异常处理

1.异常的概念 程序运行中意外发生的情况就成为异常 例子&#xff1a; //除法运算function chu(num1:number,num2:number){if(num20){//throw 抛出异常throw new Error(除数不能为零)}let num:numbernum1/num2console.log(num) }//程序出现异常后会停止运行// 捕获异常try{ /…...

go的学习笔记

中文标准库文档:https://studygolang.com/pkgdoc 第一段代码 所有代码的主文件都是main.go,下面的代码直接在项目里面创建main.go运行 package main // 声明文件所在的包,每个go文件必须有归属的包import "fmt" // 引入程序需要的包,为了使用包下的函数,比如Print…...

卷积和转置卷积的输出尺寸计算

卷积和转置卷积的输出尺寸计算 卷积 h是输出的高&#xff0c;h是输入的高&#xff0c;k_h是卷积核的高 w类似stride1 h h - k_h padding*2 1通用公式 stride1就是上面的公式 h (h - k_w 2*padding stride)//stride 一些常见的卷积 高宽不变的卷积&#xff1a;kernel…...

vue3+ts 使用amCharts展示地图,1.点击左侧国家,可以高亮并放大右侧地图对应的国家。 2.展示数据球。

效果图展示&#xff1a; 1.点击左侧国家&#xff0c;可以高亮并放大右侧地图对应的国家。 2.展示数据球。 下载依赖 yarn add amcharts/amcharts5其中&#xff0c;props.countryData的数据格式为 [{ “country”: “加拿大”, “code”: “CA”, “deviceCount”: 1 },{ “c…...

汽车无钥匙启动功能工作原理

移‌动管家无钥匙启动‌是一种科技化的汽车启动方式&#xff0c;它允许车主在不使用传统钥匙的情况下启动车辆。这种技术通过智能感应系统实现&#xff0c;车主只需携带智能钥匙&#xff0c;当靠近车辆时&#xff0c;车辆能够自动解锁并准备启动。启动车辆时&#xff0c;车主无…...

C++标准的一些特性记录:C++11的auto和decltype

文章目录 auto容器遍历配合lambda表达式decltype两者对引用类型的处理是相同的decltype保留const,而auto不会保留const在C++11中,引入了两个新的关键字,auto和decltype两个关键字,都是用于做类型推断。但是使用的场景有些区别。 auto 容器遍历 auto这个关键字,我个人在编…...

【Elasticsearch系列四】ELK Stack

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

【新手上路】衡石分析平台使用手册-认证方式

认证方式​ 用户登录衡石系统时&#xff0c;系统需要对输入的用户名和密码进行验证&#xff0c;保证系统的安全。衡石提供 CAS、SAML2、OAUTH2等多种单点登录认证方式。在 SSO 单点登录中&#xff0c;衡石是服务提供者 SP&#xff08;Service Provider&#xff09;为用户提供所…...

数字电路与逻辑设计-触发器功能测试及其应用

一、实验目的 1&#xff0e;验证基本RS、JK、D、T和T’触发器的逻辑功能及使用方法&#xff1b; 2&#xff0e;能进行触发器之间的相互转换&#xff1b; 3&#xff0e;学习触发器的一些应用。 二、实验原理 触发器具有两个能够自行保持的稳定状态&#xff0c;用以表示逻辑状…...

【网站架构部署与优化】web服务与http协议

文章目录 HTMLHTML 概述HTML 语法规则HTML 文件结构头标签中常用标签静态网页与动态网页1. 静态网页2. 动态网页3. 动态网页语言 HTTP协议概述主要的HTTP版本包括&#xff1a;HTTP方法GET与POST方法的比较 HTTP状态码分类及常见状态码HTTP常见状态码 HTTP 请求流程分析1. 请求报…...

【字符函数】strcpy函数(字符串复制函数)+strcat函数(字符串追加)+strcmp函数(字符串比较)【笔记】

1.复制函数--------------strcpy函数 函数使用 char*strcpy&#xff08;char* destination, const char* source&#xff09; strcpy函数用于拷贝字符串&#xff0c;即将一个字符串中的内容拷贝到另一个字符串中&#xff08;会覆盖原字符串内容&#xff09;。它的参数是两个指…...

codetop字符串刷题,刷穿地心!!不再畏惧!!暴打面试官!!

主要供自己回顾与复习&#xff0c;题源codetop标签字符串近半年&#xff0c;会不断更新 1.有效的括号字符串2.括号生成3.最长单词4.字符串转换整数(atoi)5.整数转罗马数字6.罗马数字转整数7.比较版本号8.最长公共前缀9.面试题17.15.最长单词10.验证IP地址11.面试题01.06.字符串…...

快速体验Linux发行版:DistroSea详解与操作指南

DistroSea 是一个功能强大的在线平台&#xff0c;允许用户在无需下载或安装的情况下&#xff0c;通过浏览器直接测试多种Linux和BSD发行版。该平台非常适合Linux爱好者、系统管理员和开发者&#xff0c;提供一个简便的方式来体验各种操作系统而无需影响本地设备。 为什么选择D…...

Java设计模式—面向对象设计原则(二) --------> 里氏代换原则 LSP (完整详解,附有代码+案列)

文章目录 里氏代换原则3.2.1 概述3.2.2 改进上述代码 里氏代换原则 里氏代换原则&#xff1a;Liskov Substitution Principle&#xff0c;LSP 3.2.1 概述 里氏代换原则是面向对象设计的基本原则之一。 里氏代换原则&#xff1a;任何基类可以出现的地方&#xff0c;子类一定…...

使用ShardingSphere实现MySql的分库分表

目录 一 什么是ShardingSphere分库分表 二 代码实现 1.导入相关依赖 2.配置相关参数 3.创建学生类以及mapper接口 4.实现 StandardShardingAlgorithm接口自定义分片算法 唐洋洋我知道你在看!!!嘿嘿 一 什么是ShardingSphere分库分表 我们平时在设计数据库的时候&#xf…...

为什么 Feign 要用 HTTP 而不是 RPC?

一、引言 在现代微服务架构中&#xff0c;服务之间的通信是至关重要的环节。Feign 是一种常用的声明式 HTTP 客户端工具&#xff0c;它简化了服务间的调用过程。然而&#xff0c;在服务通信的领域中&#xff0c;除了基于 HTTP 的方式&#xff0c;还有 RPC&#xff08;Remote Pr…...

OJ在线评测系统 前端开发设计优化通用菜单组件二 调试用户自动登录

通用的菜单组件开发二 接下来要完善 权限功能 就是只有登录后才能进入题目查看界面 用户只能看到我们有权限的菜单 我们要在路由文件里面去操作 原理是控制路由设置隐藏 只要用户没有权限 就过滤掉隐藏 全局权限管理 实现想清楚有那些权限 /*** 权限定义*/ const ACCES…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...