【stm32】I2C通信外设

news2024/12/23 0:10:36

【stm32】I2C通信外设

概念部分

  • 如果简单应用,选择软件I2C。如果对性能指标要求比较高 选择硬件I2C

  • 有硬件电路自动反转引脚电平,软件只需要写入控制寄存器CR和数据寄存器DR 为了实时监控时序的状态,还要读取状态寄存器SR

    • 写入控制寄存器CR,就相当于踩油门、打方向盘 控制汽车的运行

    • 读取状态寄存器SR,就像是观看仪表盘

  1. 在这里插入图片描述

  2. 首先移位寄存器和数据寄存器DR的配合是通信的核心部分

    1. 因为I2C是高位先行,所以这个移位寄存器是向左移位,在发送的时候最高位先移出去,然后是次高位,移位8次,由高到低位,依次放到SDA线上

    2. 在接受的时候,数据通过GPIO口从右边依次移进来

  3. 最后GPIO口这里 使用硬件I2C的时候,这两个对应的GPIO口 都要配置成复用开漏输出的模式

    1. 复用就是GPIO的状态是交由片上外设来控制的

    2. 开漏输出这是I2C协议要求的端口配置

    3. 这里即使是开漏输出模式,GPIO口也是可以进行输入的

  4. 然后SCL这里,时钟控制器通过GPIO去控制时钟线

    1. 这里是一主多从的模式 所以时钟这里只画了输出的方向

序列图

  1. 在这里插入图片描述

  2. 指定地址写

    1. 首先初始化之后,总线默认空闲状态,STM32默认是从模式

    2. 为了产生一个起始条件,STM32需要写入控制寄存器,在START位写1,STM32就自动产生起始条件

    3. 之后STM32由从模式转为主模式 就是多主机模型下,STM32有数据要发,就要跳出来

    4. 控制完硬件电路之后,就要检查标志位,来看看硬件有没有达到我们想要的状态

    5. 起始条件之后会发生EV5事件,可以把EV5当成标志位 这个手册这里都是用EV(Event)几这个事件来代替标志位的

      1. 因为有的状态会同时产生多个标志位,这个EV几事件是组合了多个标志位的一个大标志位

      2. 在库函数中也会有对应的,检查EV几事件是否发生的函数,可以当成一个大标志位来理解

    6. 当检测其实条件已发送时,就可以发送从机地址了,从机地址需要写到数据寄存器DR中

      1. 硬件电路就会自动把这一个字节转到移位寄存器里

      2. 再把这一个字节发送到I2C总线上

      3. 之后硬件会自动接收应答并判断,如果没有应答硬件会置应答失败的标志位

    7. 寻址完成之后,会发生EV6事件,之后是EV8_1事件

      1. 这时需要我们写入数据寄存器DR,进行数据发送了,一旦写入DR之后,因为移位寄存器也是空,所以DR会立刻转到移位寄存器进行发送
    8. 到了EV8事件,这时就是移位寄存器正在发送数据的状态,流程图上,数据1的时序就产生了

在这里插入图片描述

  1. 这个位置EV8事件没有了,对于EV8写入DR将清除该事件,所以在EV8事件末尾应该是写入了写一个数据

    1. 也就是后面的数据2

    2. 在这个时刻就被写入到寄存器里等着了

    3. 然后在数据1接收到应答之后,数据2就转入移位寄存器进行发送

    4. EV8事件就又发生了在这里插入图片描述

      1. 在第二个EV8事件末尾,数据2还正在移位发送

      2. 但此时下一个数据已经被写到数据寄存器等着了

      3. 所以EV8事件结束

    5. 一旦我们检测到EV8事件,就可以写入下一个数据了

  2. 最后当我们发送的数据写完之后

    1. 这时就没有新的数据可以写入到数据寄存器了

    2. 当移位寄存器当前的数据移位完成时,此时就是移位寄存器空数据寄存器也空的状态,就是后面的EV8_2事件

    3. 在这里插入图片描述

    4. 当检测到EV8_2时,就可以产生终止条件了,(控制寄存器CR1中STOP位进行控制停止

硬件I2C读写MPU6050

  • 软件I2C和硬件I2C的区别,在通信的底层,就是之前写的MyI2C.c

  • 把MyI2C模块移出工程

  • 利用硬件I2C外设 来替换这些注释的代码,来实现相同的功能

编码步骤

  1. 配置I2C外设,对I2C外设进行初始化,来替换MyI2C_Init

  2. 控制外设电路,实现指定地址写的时序

  3. 控制外设电路,实现指定地址读的时序

在这里插入图片描述

  1. 开启I2C外设和对应GPIO口的时钟

  2. 把I2C外设对应的GPIO口初始化为复用开漏输出

  3. 使用结构体对整个I2C外设进行配置

  4. I2C_Cmd使能I2C,这样初始化配置就完成了

对应的函数
  1. I2C_GenerateSTART 生成起始条件 Start可以通过手册对寄存器描述来了解

  2. I2C_GenerateSTOP 设置Stop位产生停止条件

  3. I2C_AcknowledgeConfig 配置ACK这一位 手册里有相关描述 在收到一个字节后是否给从机应答

  4. I2C_SendData 发送数据 实际就是把Data这个数据直接写到DR寄存器

  5. I2C_ReceiveData 接收数据 读取DR

  6. I2C_Send7bitAddress 发送地址 也可以使用I2C_SendData进行地址发送

  7. 在.h下面 库函数给了我们多种监控标志位的方案 Basic state monitoring: I2C_CheckEvent(同时判断一个或多个标志位,来确定EV几这个状态是否发生,和ppt流程是对应的)

  8. Flag-based state monitoring: 标志位的状态监控 I2C_GetFlagStatus() 可以判断某一个标志位是否置1

指定地址写一个字节的时序编码
  • 对应着软件I2C的流程和ppt时序图

  • 硬件I2C函数都不是阻塞式的 这些硬件I2C函数只管给寄存器的位置置1 或者只在DR写入函数,就结束,退出函数,不管波形是否发送完毕 所以对于这种非阻塞时的程序,在函数结束之后,我们都要等待对应的标志位,确保函数的操作执行到位

  1. 生成起始条件

  2. 等待EV5(也可以叫做主机模式已选择事件)事件的到来 使用状态监控函数 使用I2C_CheckEvent函数 等待SUCCESS

  3. 发送从机地址 接收应答 I2C_SendData 和 I2C_Send7bitAddress 都可以完成

  4. 接收应答 这里并不需要一个函数来操作 在这个库函数中发送数据都自带了接收应答的过程 同样 发送数据也自带了发送应答的过程

    1. 如果应答错误 硬件会通过标志位和中断来提示我们

    2. 所以发送地址之后不需要就收应答 直接等待事件

  5. 发送完地址之后 等待EV6事件

  6. EV8_1事件是告诉你你该写入DR发送数据了,并不需要等待这个EV8_1事件,库函数参数列表也没有EV8_1事件的参数

  7. 直接写入DR发送数据 发送RegAddress 等待EV8事件

  8. 继续调用I2C_SendData发送一个字节的数据

  9. 发送完Data之后就需要终止了,所以最后这个等待事件有所不同

    1. 在连续数据进行发送时,需要等待EV8事件

    2. 而当我们发送完最后一个字节数据时,需要等待EV8_2事件

    3. 当BTF等于1,就是移位完成了,并且没有新的数据可以发的时候,置BTF也就是EV8_2

  10. 使用终止函数

接收一位数据
  1. 在等待EV6事件之后,要清除响应和停止条件的产生

在这里插入图片描述

  1. 在这个位置,要把应答位置0,同时把停止条件生成位STOP置1 ,

  2. 虽然这时候是应该接收数据,数据都没收到,就要产生停止条件?答案确实如此,这里规定就是在接收一个字节之前,就要提前把ACK置0,同时设置停止位STOP在这里插入图片描述

  3. 因为我们目前是接收一个字节

    1. 所以在进入接收模式之后,就要立刻ACK置0,STOP置1

    2. 如果不提前在数据还么收到的时候给ACK置0,等时序到了接收第二个数据的时候,数据已经收到了,再说要置0,要给非应答,在这里插入图片描述
      ,这时就晚了,数据收到之前应到位就已经发送出去了

    3. 这时再给ACK置0,只能实在下一个数据之后给非应答,所以在 最后一个数据之前,就要给ACK置0

  4. 在EV6事件之后,配置ACK位和停止位

  5. 之后再等待EV7事件,等待EV7事件之后,数据就已经到了DR寄存器里了

  6. 可以读取DR寄存器 存到Data变量里

  7. 最后把ACK置1,默认状态下就要把ACK置1,给从机应答

    1. 在接收数据之前 临时把ACK置0,给非应答

    2. 这个流程是为了方便指定地址收多个字节

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

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

相关文章

06-kafka及异步通知文章上下架

kafka及异步通知文章上下架 1)自媒体文章上下架 需求分析 2)kafka概述 消息中间件对比 特性ActiveMQRabbitMQRocketMQKafka开发语言javaerlangjavascala单机吞吐量万级万级10万级100万级时效性msusmsms级以内可用性高(主从)高(主从&#…

【数据库】MySQL InnoDB存储引擎详解 - 读书笔记

MySQL InnoDB存储引擎详解 - 读书笔记 InnoDB 存储引擎概述InnoDB 存储引擎的版本InnoDB 体系架构内存缓冲池LRU List、Free List 和 Flush List重做日志缓冲(redo log buffer)额外的内存池 存储结构表空间系统表空间独立表空间通用表空间undo表空间临时…

力扣---反转链表 II ***

给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4 输出&#xff1a;[1,4,3,…

【QT入门】 Qt代码创建布局综合运用:仿写腾讯会议登陆界面

往期回顾&#xff1a; 【QT入门】 Qt代码创建布局之水平布局、竖直布局详解-CSDN博客 【QT入门】 Qt代码创建布局之栅格布局详解-CSDN博客 【QT入门】 Qt代码创建布局之分裂器布局详解-CSDN博客 【QT入门】 Qt代码创建布局综合运用&#xff1a;仿写腾讯会议登陆界面 一、界面分…

rust 面向对象编程特性、模式与模式匹配、高级特征

面向对象编程OOP 学习了结构体、枚举&#xff0c;它们可以包含自定义数据字段&#xff0c;也可以定义内部方法&#xff0c;它们提供了与对象相同的功能。 面向对象的四大特征&#xff1a;封装、继承、多态 通过pub标记为公有的结构体&#xff0c;在其他模块中可以访问使用这…

redis主从复制与哨兵模式

redis主从复制 Redis主从复制&#xff08;Redis replication&#xff09;是Redis提供的一种数据备份和故障转移机制。通过主从复制&#xff0c;可以将一个Redis服务器&#xff08;主节点&#xff09;的数据复制到一个或多个Redis服务器&#xff08;从节点&#xff09;。这样做…

算法设计与分析实验报告java实现(排序算法、三壶谜题、交替放置的碟子、带锁的门)

一、 实验目的 1&#xff0e;加深学生对算法设计方法的基本思想、基本步骤、基本方法的理解与掌握&#xff1b; 2&#xff0e;提高学生利用课堂所学知识解决实际问题的能力&#xff1b; 3&#xff0e;提高学生综合应用所学知识解决实际问题的能力。 二、实验任务 1、排序算法…

ctf_show笔记篇(web入门---jwt)

目录 jwt简介 web345&#xff1a; web346&#xff1a; web347&#xff1a; web348: web349&#xff1a; web350&#xff1a; jwt简介 JSON Web Token&#xff08;JWT&#xff09;通常由三部分组成 Header&#xff08;头部&#xff09;&#xff1a;包含了两部分信息&…

使用 Clickhouse 集成的表引擎同步数据方式详解

Clickhouse作为一个列式存储分析型数据库&#xff0c;提供了很多集成其他组件的表引擎数据同步方案。 官网介绍 一 Kafka 表引擎 使用Clickhouse集成的Kafka表引擎消费Kafka写入Clickhouse表中。 1.1 流程图 1.2 建表 根据上面的流程图需要建立三张表&#xff0c;分别Click…

Jenkins 安装部署

1、安装下载 官网地址&#xff1a;Jenkins 下载 war 包 1、前置环境 JDK 环境&#xff08;根据 Jenkins 版本不同&#xff0c;需要的 JDK 版本不同&#xff0c;目前需要 JDK11 的版本来支持&#xff09;Maven maven 官网下载压缩包 &#xff0c;并将其传输到服务器&#xf…

一、OpenCV(C#版本)环境搭建

一、Visual Studio 创建新项目 二、选择Windows窗体应用&#xff08;.NET Framework&#xff09; 直接搜索模板&#xff1a;Windows窗体应用(.NET Framework) 记得是C#哈&#xff0c;别整成VB(Visual Basic)了 PS&#xff1a;若搜索搜不到&#xff0c;直接点击安装多个工具和…

【Linux】线程概念及线程互斥

目录 线程概念 线程优点 线程缺点 线程异常 线程系统编程接口 线程创建及终止 线程等待 使用线程系统接口封装一个小型的C线程库并实现一个抢票逻辑 线程互斥 互斥量的接口 线程互斥实现原理 使用系统加锁接口封装LockGuard 实现自动化加锁 线程安全和可重入函数 …

Win10文件夹共享(有密码的安全共享)(SMB协议共享)

前言 局域网内&#xff08;无安全问题&#xff0c;比如自己家里wifi&#xff09;无密码访问&#xff0c;参考之前的操作视频 【电脑文件全平台共享、播放器推荐】手机、电视、平板播放硬盘中的音、视频资源 下面讲解公共网络如办公室网络、咖啡厅网络等等环境下带密码的安全…

探寻马来西亚服务器托管的优势与魅力

随着全球跨境业务的不断增加&#xff0c;境外服务器成为越来越受欢迎的选择。在这其中&#xff0c;马来西亚服务器备受关注&#xff0c;其机房通常位于马来西亚首都吉隆坡。对于客户群体主要分布在东南亚、澳大利亚和新西兰等地区的用户来说&#xff0c;马来西亚服务器是一个理…

【opencv】教程代码 —ml (主成分分析、支持向量机、非线性支持向量机)

1. introduction_to_pca.cpp 主成分分析 /*** file introduction_to_pca.cpp* brief 这个程序演示了如何使用OpenCV PCA 提取物体的方向* author OpenCV团队*/// 包含OpenCV函数库所需要的头文件 #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp&q…

JVM专题——内存结构

本文部分内容节选自Java Guide和《深入理解Java虚拟机》, Java Guide地址: https://javaguide.cn/java/jvm/memory-area.html &#x1f680; 基础&#xff08;上&#xff09; → &#x1f680; 基础&#xff08;中&#xff09; → &#x1f680;基础&#xff08;下&#xff09;…

Neo4j数据库(一)

目录 新建节点 Neo4j CQL创建具有属性的节点 多个标签到节点 单个标签到关系 MATCH命令 RETURN命令&#xff1a; Neo4j CQL - MATCH & RETURN匹配和返回 总结&#xff1a;本文介绍了Neo4j的CREATE&#xff0c;MATCH&#xff0c;RETURN的基本操作 新建节点 Neo4j创建一…

Coursera上托福专项课程02:TOEFL Speaking and Writing Sections Skills Mastery 学习笔记

TOEFL Speaking and Writing Sections Skills Mastery Course Certificate 本文是学习 https://www.coursera.org/learn/toefl-speaking-writing-sections-skills-mastery 这门课的学习笔记&#xff0c;如有侵权&#xff0c;请联系删除。 文章目录 TOEFL Speaking and Writing…

Unity 代码控制播放序列帧动画的实现

在Unity中有些应用场景的动画是通过序列帧实现的。 如下图即为一个英雄攻击的一个动画&#xff1a; 那么如何实现该序列帧动画的播放呢&#xff0c;我们可以通过代码来控制播放。 1、把以上序列帧导入编辑器中&#xff0c;并修改图片属性&#xff0c;如下图所示&#xff0c;其…

三菱上升沿和下降沿

1&#xff0c;上升沿 含义 上升沿是在接通的第一个周期执行。 2&#xff0c;下将沿 断开的第一个周期执行 M0 按下后Y0 亮 M1 松开后Y0灭