STM32学习笔记(10_1)- I2C通信协议

news2024/11/22 9:06:20

无人问津也好,技不如人也罢,都应静下心来,去做该做的事。

最近在学STM32,所以也开贴记录一下主要内容,省的过目即忘。视频教程为江科大(改名江协科技),网站jiangxiekeji.com

本期开始学习 I2C通信,会分两大块来介绍,第一块, 就是介绍协议规则,然后用软件模拟的形式来实现协议;第二块, 就是介绍STM32的 I2C外设, 然后用硬件来实现协议。

I2C:高位先行,只有在SCL高电平时才会读取SDA的电平

本期的内容其实就是对MPU6050芯片内部的寄存器进行读写,写入到配置寄存器,就可以对外挂的这个模块进行配置;读出数据寄存器,就可以获取外挂模块的数据。最终,我们读出的数据会显示在这个OLED上。而STM32对MPU6050的读写是通过I2C来进行的。

因为I2C是同步时序,软件模拟协议也非常方便,所以这里会先介绍软件模拟 I2C。

本期会使用MPU6050陀螺仪、加速度传感器来学习 I2C。

 I2C的完整时序,主要有指定地址写、当前地址读和指定地址读这3种。I2C指定地址写简单来说就是SCL高电平时、SDA下降沿开始传输,传输的第一个字节为从机的7位地址+1位读写位(置0表示要写入),然后是1位应答位(RA,置0表示应答),传输的第二个字节为从机的寄存器地址或者是指令控制字,然后也是1位应答位,传输的第三个字节为主机想写入从机的数据,然后也是1位应答位,这时若不想传输了,则SCL高电平时、SDA上升沿停止传输。

当前地址读就是SCL高电平时、SDA下降沿作为起始条件开始传输,传输的第一个字节为从机的7位地址+1位读写位(这里置1表示读取),然后是1位应答位(RA,置0表示应答),传输的第二个字节为从机的数据,然后是1位非应答位(SA,置1),这时SCL高电平、SDA上升沿作为停止条件停止传输。

指定地址读就是指定地址写去掉写数据的部分+当前地址读,SCL高电平时、SDA下降沿作为起始条件开始传输,传输的第一个字节为从机的7位地址+1位读写位(置0表示要写入),然后是1位应答位(RA,置0表示应答),传输的第二个字节为从机的寄存器地址或者是指令控制字,然后也是1位应答位(置0),然后接重复起始条件Sr(即再来一次起始条件),传输的第三个字节为从机的7位地址+1位读写位(置1表示要读取),然后再接收1位应答位(置0),传输的第四个字节为从机的数据,然后1位非应答位(SA,置1),然后SCL高电平、SDA上升沿作为停止条件停止传输。

I2C通信

下图左一是MPU6050,可以进行姿态测量,使用了I2C通信协议;左二是OLED模块,可以显标字符、图片等信息,也是I2C协议;左三是AT24C02,存储器模块;第4个图片,是DS3231,实时时钟模块,也是使用I2C协议。

本期只会用到一主多从,一主多从就是单片机作为主机,主导I2C总线的运行,挂载在I2C总线的所有外部模块都是从机,从机只有被主机点名之后才能控制I2C总线。

作为通信协议,它必须要在硬件和软件上,都作出规定。硬件规定就是你的电路该怎么连接、端口的输入输出模式都是啥样的。软件上的规定就是,你的时序是怎么定义的,字节如何传输、高位先行还是低位先行、一个完整的时序由哪些部分构成。

硬件电路

下图便是一主多从模型,任何时候,都是主机完全掌控SCL线。另外在空闲状态下,主机可以主动发起对SDA的控制,只有在从机发送数据和从机应答的时候,主机才会转交SDA的控制权给从机。从机对于SCL时钟线,在任何时刻都只能被动的读取。

I2C的设计是,禁止所有设备输出强上拉的高电平,采用外置弱上拉电阻加开漏输出的电路结构。不采用推挽输出是为防止时序混乱导致SDA上出现电源短路 的情况。右边的图是内部的具体结构说明,SCLK信号进来,都可以通过一个数据缓沖器或者是施密特触发器,进行输入。输出只能是开漏输出。

 软件部分

I2C时序基本单元

在I2C总线处于空闲状态时,SCL和SDA都处于高电平状态。当从机捕获到这个SCL高电平,SDA下降沿信号时,就会进行自身的复位,等待主机的召唤。

起始之后,就到发送部分。高位先行,SCL低电平时,主机如果想发送0,就拉低SDA到低电平;如果想发送,就放手,SDA回弹到高电平。在SCL低电平时,SDA可以变化,但在SCL高电平时,SDA不允许变化。

接收部分

 应答

I2C完整时序

 I2C的完整时序,主要有指定地址写、当前地址读和指定地址读这3种。首先把每个从设备都确定一个唯一的设备地址,主机在起始条件之后,要先发送一个字节叫一下从机名字,所有从机都会收到第一个字节,和自己的名字进行比较,如果一样,就说明,主机现在在叫我,那我就响应之后主机的读写操作。

指定地址写

从机设备地址,在I2C协议标准里分为7位地址和10位地址,我们目前只讲7位地址的模式。那在每个I2C设备出厂时,厂商都会为它分配一个7位的地址,这个地址具体是什么,可以在芯片手册里找到。一般不同型号的芯片地址都是不同的,相同型号的芯片地址都是一样的,那如果有相同的芯片挂载在同一条总线怎么办呢?这就需要用到地址中的可变部分了,一般器件地址的最后几位是可以在电路中改变的,比如MPU6050地址的最后一位,就可以由这个板子上的AD0脚确定。这个引脚接低电平,那它的地址就是1101 000;这个引脚接高电平,那它的地址就是1101 001。

下面以几个波形来详细解释I2C的完整时序。

空闲状态,SCL和SDA都是高电平。然后主机需要给从机写入数据的时候,首先,SCL高电平期间,拉低SDA,产生起始条件(Start,S)。在起始条件之后,跟着的时序,必须是发送一个字节的时序。字节的内容,必须是从机地址+读写位,正好从机地址7位,读写位是1位,加起来是一个字节,8位。发送从机地址,就是确定通信的对象。比如这个波形下,主机寻找的从机地址就是1101 000,这个就是MPU6050的地址,然后最低位,表示读写位,0表示,之后的时序主机要进行写入操作。1表示,之后的时序主机要进行读出操作。紧跟着的单元,就得是接收从机的应答位(Receive Ack,RA),在这个时刻,主机要释放SDA。最终高电平期间,主机读取SDA,发现是0,就说明,我进行寻址,有人给我应答了。应答结束后,我们要继续发送一个字节。第二个字节,就可以送到指定设备的内部了,从机设备可以自己定义第二个字节和后续字节的用途,一般第二个字节可以是寄存器地址或者是指令控制字等。比如MPU6050定义的第二个字节就是寄存器地址;比如AD转换器,第二个字节可能就是指令控制字;比如存储器,第二个字节可能就是存储器地址。图中的第二个字节在MPU6050里,就表示我要操作0x19地址下的寄存器了。接着同样,是从机应答。同样的流程在来一遍,主机发送第三个字节。这个字节就是主机想要写入到0x19地址下寄存器的内容了,比如这里就表示,我要在0x19地址下,写入0xAA。最后是接收应答位,然后也是1位应答位,如果主机不需要继续传输了,就可以产生停止条件(Stop,P)。在停止条件之前,先拉低SDA,为后续SDA的上升沿作准备,然后释放SCL,再释放SDA,这样就产生了SCL高电平期间,SDA的上升沿。这样一个完整的数据帧就完成了。这个数据帧的目的就是,对于指定从机地址为1101 000的设备,在其内部0x19地址的寄存器中,写入0xAA这个数据

当前地址读

这就是当前地址读的时序,如果主机想要读取从机的数据,就可以执行这个时序。

那最开始,还是SCL高电平期间, 拉低SDA,产生起始条件。然后,主机必须首先调用发送一个字节,来进行从机的寻址和指定读写标志位,比如图示的波形,表示本次寻址的日标是1101 000的设备,同时,最后一位读写标志为1,表示主机接下来想要读取数据。然后,接收一下从机应答位,从机应答0,代表从机收到了第一个字节。应答后,第二个字节数据的传输方向就要反过来,因为发了读的命令,所以主机要把SDA的控制权交给从机。主机调用接收一个字节的时序,进行接收操作,这段时间,从机可以在SCL低电平期间写入SDA,然后主机在SCL高电平期间读取SDA。那最终,主机在SCL高电平期间依次读取8位,就接收到了从机发送的一个字节数据。由于这里主机并没有指定读取的地址,所以就要用到当前地址指针。在从机中会有一个单独的指针变量,这个指针上电默认,一般指向0地址,并且,每写入一个字带和读出一个字节后,这个指针就会自动自增一次,那么在调用当前地址读的时序时,主机没有指定要读哪个地址,从机就会返回当前指针指向的寄存器的值,那假设,我刚调用了这个指定地址写的时序,在0x19的位置写入了0xAA,那么指针就会+1,移动到0x1A的位置,我再调用这个当前地址读的时序,返回的就是0x1A地址下的值。如果在调用一次,返回的就是0x1B地址下的值。由手当前地址读并不能指定读的地址,所以用的不多

指定地址读

从中间红线分开,左边是指定地址写,但是去掉了写数据的那部分;右边是当前地址读。

因为我们刚指定了地址,所以再调用当前地址读,就是指定地址读,也叫复合格式。所以这个时序会复杂点。

首先,最开始仍然是启动条件,然后发送一个字节,进行寻址。这里指定从机地址是1101 000,读写标志位是0,代表我要进行写的操作。经过从机应答后,再发送第二个字节,用来指定地址,这个数据就写入到了从机的地址指针里了。也就是说从机接收到第二个数据后,它的寄存器指针就指向了0x19这个位置。

这时再来一个起始条件,这个Sr(Start Repeat)的意思就是重复起始条件,这时还不能开始发送数据,因为指定读写标志位只能是跟着起始条件的第一个字节,所以如果想切换读写方向。只能再来个起始条件,然后起始条件后,重新寻址并且指定读写标志位,此时读写标志位是1,代耒我要开始读了,接着主机开始读,这个字节是不是就是0x19地址下的数据。在读完一个字节之后,一定要给从机发个非应答,(Send Ack,SA),非应答就是该主机应答的时候,主机不把SDA拉低。

两个程序现象

一是软件 I2C读写MPU6050 

对MPU6050芯片内部的寄存器进行读写,写入到配置寄存器,就可以对外挂的这个模块进行配置;读出数据寄存器,就可以获取外挂模块的数据。最终,我们读出的数据会显示在这个OLED上。最上面的是ID号,图中这个MPU6050的ID号固定为0x68,可以读取这个ID号用来测试 I2C读取数据的功能是不是正常,不同批次的MPU6050,ID号会有所不同。然后下面,左边3个,是加速度传感器的输出数据,分别是X轴、Y轴和Z轴的加速度,右边3个,是陀螺仪传感器的输出数据,分别是X轴、Y轴和Z轴的角速度。

二是硬件 I2C读写MPU6050

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

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

相关文章

JMeter+Grafana+influxdb 配置出现transaction无数据情况解决办法

JMeterGrafanainfluxdb 配置出现transaction无数据情况解决办法 一、问题描述二、解决方法 一、问题描述 如下图所示出现application有数据但是transaction无数据情况 二、解决方法 需要做如下设置 打开变量设置如下图打开两个选项 然后再进行后端监听器的设置 如下图所…

【VUE】ruoyi框架自带页面可正常缓存,新页面缓存无效

ruoyi框架自带页面可正常缓存,新页面缓存无效 背景: 用若依框架进行开发时,发现ruoyi自带的页面缓存正常,而新开发的页面即使设置了缓存,当重新进入页面时依旧刷新了接口。 原因:页面name与 getRouters …

3个 JavaScript 字符串截取方法

在 JavaScript 中,可以使用 substr()、slice() 和 substring() 方法截取字符串. substring() substring() 方法返回一个字符串在开始索引到结束索引之间的一个子集,或从开始索引直到字符串的末尾的一个子集。语法如下: str.substring(inde…

GT收发器64B66B设计(1)IP核配置和example design

文章目录 前言一、IP核配置1.1、编码方式1.2、字节对齐和逗号码 二、example design 前言 在前面我们基于GT收发器进行了PHY层设计,其中采用的编码方式为8B10B,为进一步提高传输效率,从本文开始,将采用基于GT高速收发器采用64B66…

DC/DC选型:了解电感参数的基本含义

电感是一种相对简单的元件,它由缠绕在线圈中的绝缘线组成。但当单个元件组合在一起,用来创建具有适当尺寸、重量、温度、频率和电压的电感,同时又能满足目标应用时,复杂性就会增加。 选择电感时,了解电感数据手册中标…

京西商城——基于viewset视图集开发评论接口

在使用GenericAPIView和Mixins开发时,确实可以大大提高编码的速度以及减少代码量,但是在一个视图里并不能实现5个基础的请求方法,要用两个视图类来完成。所以我们可以使用viewset(视图集)来将两个视图类合并 如果要使…

Docker实战教程 第2章 Docker基础

3-1 Docker介绍 什么是Docker 虚拟化,容器 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上&…

职场聚餐:搭建沟通桥梁,促进团队凝聚力

在职场中,聚餐作为一种非正式的社交活动,不仅能够增进同事间的了解,还有助于提升团队凝聚力。本文将探讨职场聚餐的重要性以及如何组织一场成功的职场聚餐。 一、职场聚餐的重要性 1. 搭建沟通桥梁:职场聚餐为员工提供了一个轻松愉…

Java中线程详解

文章目录 相关概念多线程概念实现方式继承Thread类实现Runnable接口比较 常用方法线程安全产生的原因解决思想同步同步代码块同步方法Lock锁机制 死锁概念避免 状态线程间的通讯介绍方法 相关概念 并行:在同一时刻,有多个任务在多个CPU上同时执行并发&a…

【JAVASE】学习类与对象的创建和实例化

✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 目标: 1. 掌握类的定义方式以及对象的实例化 2. …

QML嵌套页面的实现学习记录

StackView是一个QML组件,用于管理和显示多个页面。它提供了向前和向后导航的功能,可以在堆栈中推入新页面,并在不需要时将页面弹出。 ApplicationWindow {id:rootvisible: truewidth: 340height: 480title: qsTr("Stack")// 抽屉:…

语义分割交互式智能标注工具 | 澳鹏数据标注平台

随着人工智能应用的大规模落地,数据标注市场在高速增长的同时,也面临着标注成本的挑战。据IDC报告显示:数据标注在AI应用开发过程中所耗费的时间占到了25%,部分医学类应用一条数据的标注成本甚至高达20元。数据精度的高要求、强人…

【Django学习笔记(五)】JQuery介绍

JQuery介绍 前言正文1、JQuery 快速上手1.1 下载 JQuery1.2 应用 JQuery 2、寻找标签(直接)2.1 ID选择器2.2 样式选择器2.3 标签选择器2.4 层级选择器2.5 多选择器2.5 属性选择器 3、寻找标签(间接)3.1 找到上一个兄弟3.2 找父子 …

浪潮分布式存储AS13000G6-M36改扩配后管理界面不能识别和标记硬盘的处理方法

AS13000G6 改配出问题的场景 浪潮分布式存储AS13000G6-M36渠道备货的分布式存储通常是流量机型,实际出货可能会涉及改配 集群部署完以后建议在系统视图下查看一下盘是否能识别 这个是正常的情况,可以正确管理到盘,硬盘侧边有绿色的指示灯。 如图是管理…

【Linux】进程控制详解

目录 前言 进程创建 认识fork 写时拷贝 再谈fork 进程终止 进程退出码 用代码来终止进程 常见的进程终止的方式 exit _exit 进程等待 进程等待的必要性 进程等待的方式 wait waitpid 详解status参数 详解option参数 前言 本文适合有一点基础的人看的&#…

计算机笔记(3)续20个

41.WWW浏览器和Web服务器都遵循http协议 42.NTSC制式30帧/s 44.三种制式电视:NTSC,PAL,SECAM 45.IP,子网掩码白话文简述: A类地址:取值范围0-127(四段数字(127.0.0.0&#xff09…

Oil Deposits (DFS BFS)

//新生训练 #include <iostream> #include <algorithm> #include <cstring> #include <queue> using namespace std; using PII pair<int, int>; const int N 205; int n, m; int dis[N][N]; int dx[] {0, 0, -1, 1, -1, 1, -1, 1}; int dy[]…

JAVAEE之Spring, Spring Boot 和Spring MVC的关系以及区别

1.Spring, Spring Boot 和Spring MVC的关系以及区别 Spring: 简单来说, Spring 是⼀个开发应⽤框架&#xff0c;什么样的框架呢&#xff0c;有这么⼏个标签&#xff1a;轻量级、⼀ 站式、模块化&#xff0c;其⽬的是⽤于简化企业级应⽤程序开发 Spring的主要功能: 管理对象&am…

《pytorch深度学习实战》学习笔记第1章

第1章 深度学习和pytorch库简介 1.1 深度学习革命 机器学习依赖特征工程。而深度学习是从原始数据中自动找出这样的特征。 1.2 pytorhc深度学习 pytorch是一个python程序库。pytorch为深度学习提供了入门指南。pytorch的核心数据结构——张量&#xff0c;为一个多维数组&…

slowhttp攻击漏洞原理解析和防御,以及LiqunKit 综合漏洞利用工具详细使用

slowhttp攻击漏洞原理解析和防御,以及LiqunKit 综合漏洞利用工具详细使用。 Slowhttp攻击是一种拒绝服务(DoS)攻击,它利用了HTTP协议的一些特性来耗尽服务器资源,导致服务器对正常请求的响应变慢或无法响应。这种攻击的特点是长时间占用服务器的连接,而不是发送大量流量…