江协科技STM32学习- P33 实验-软件I2C读写MPU6050
🚀write in front🚀
🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝💬本系列哔哩哔哩江科大STM32的视频为主以及自己的总结梳理📚
🚀Projeet source code🚀
💾工程代码放在了本人的Gitee仓库:iPickCan (iPickCan) - Gitee.com
引用:
STM32入门教程-2023版 细致讲解 中文字幕_哔哩哔哩_bilibili
Keil5 MDK版 下载与安装教程(STM32单片机编程软件)_mdk528-CSDN博客
STM32之Keil5 MDK的安装与下载_keil5下载程序到单片机stm32-CSDN博客
0. 江协科技/江科大-STM32入门教程-各章节详细笔记-查阅传送门-STM32标准库开发_江协科技stm32笔记-CSDN博客
【STM32】江科大STM32学习笔记汇总(已完结)_stm32江科大笔记-CSDN博客
江科大STM32学习笔记(上)_stm32博客-CSDN博客
STM32学习笔记一(基于标准库学习)_电平输出推免-CSDN博客
STM32 MCU学习资源-CSDN博客
stm32学习笔记-作者: Vera工程师养成记
stem32江科大自学笔记-CSDN博客
术语:
| 英文缩写 | 描述 |
| GPIO:General Purpose Input Onuput | 通用输入输出 |
| AFIO:Alternate Function Input Output | 复用输入输出 |
| AO:Analog Output | 模拟输出 |
| DO:Digital Output | 数字输出 |
| 内部时钟源 CK_INT:Clock Internal | 内部时钟源 |
| 外部时钟源 ETR:External Trigger | 时钟源 External 触发 |
| 外部时钟源 ETR:External Trigger mode 1 | 外部时钟源 External 触发 时钟模式1 |
| 外部时钟源 ETR:External Trigger mode 2 | 外部时钟源 External 触发 时钟模式2 |
| 外部时钟源 ITRx:Internal Trigger inputs | 外部时钟源,ITRx (Internal trigger inputs)内部触发输入 |
| 外部时钟源 TIx:exTernal Input pin | 外部时钟源 TIx (external input pin)外部输入引脚 |
| CCR:Capture/Comapre Register | 捕获/比较寄存器 |
| OC:Output Compare | 输出比较 |
| IC:Input Capture | 输入捕获 |
| TI1FP1:TI1 Filter Polarity 1 | Extern Input 1 Filter Polarity 1,外部输入1滤波极性1 |
| TI1FP2:TI1 Filter Polarity 2 | Extern Input 1 Filter Polarity 2,外部输入1滤波极性2 |
| DMA:Direct Memory Access | 直接存储器存取 |
正文:
0. 概述
从 2024/06/12 定下计划开始学习下江协科技STM32课程,接下来将会按照哔站上江协科技STM32的教学视频来学习入门STM32 开发,本文是视频教程 P2 STM32简介一讲的笔记。
1.🚚MP6050
本节我们来用软件I2C读写MPU6050
接线图:

由于我们这个代码使用的是软件I2C,就是用普通的GPIO口,手动翻转电平实现的协议。它并不需要STM32内部的外设资源支持。所以这里的端口其实可以任意指定,不局限于这两个端口,接在任意的两个普通的GPIO口就可以。
然后我们只需要在程序中配置并操作SCL和SDA对应的端口就行了。这算是软件I2C相比硬件I2C的一大优势,就是端口不受限,可以任意指定。
根据I2C协议的硬件规定,SCL和SDA都应该外挂一个上拉电阻,但是我们的接线这里并没有外挂上拉电阻。是因为上一节我们分析模块电路的时候提到过这个模块内部自带了上拉电阻,所以外部的上拉电阻就不需要接了。
目前这里STM32是主机,MPU6050是从机,是一主一从的模型,当然主机和从机的执行逻辑是完全不同的,我们程序中一般只关注主机端的程序。
这里由于模块内置了下拉电阻,所以引脚悬空的话就相当于接地。
MyI2C.c
由于我们本代码要使用软件I2C,所以I2C的库函数我们就不用看了。软件I2C只需要用GPIO的读写函数就行了。
初始化函数
然后初始化函数中,我们要做两个任务。第一个任务把SCL和SDA都初始化为开漏输出模式(开漏输出低电平+浮空输入也就是高阻态)。第二个任务把SCL和SDA置高电平。
⚠️⚠️⚠️注意:开漏输出并不只能输出,开漏输出模式仍然可以输入。
⚠️⚠️⚠️输入时先输出1,再直接读取输入数据寄存器就行了。

然后接下来我们就来完成I2C的六个时序基本单元。
起始条件
第一个基本单元是起始条件,这里对应写一个函数。
起始条件:SCL高电平期间,SDA从高电平切换到低电平
我们首先把SCL和SDA都确保释放,然后先拉低SDA,再拉低SCL,这样就能产生起始条件了。

在这里我们可以不断的调用SetBits和RetsetBits手动翻转高低电平。但是这样做的话,会在后面的程序中出现非常多的地方来指定这个GPIO端口号。一方面这样做语义并不是很明显,另一方面,如果我们之后需要换一个端口,就需要改动非常多的地方。所以这时我们就需要在上面做个定义,把这个端口号统一替换一个名字,这样无论是语义,还是端口的修改,都会非常方便。给端口号换一个名字,有很多方法都能实现功能。在51单片机中,我们一般使用sbit来定义端口的名称,但是sbit并不是标准C语言的语法,STM32也不支持这样做。这里一种简单的替换方法就是宏定义define。

修改引脚的时候,直接在上面修改一下宏定义,这是一种简单可行的方法,在STM32程序中也是挺常见的一个操作。
进一步的,如果觉得每次都需要定义port和pin比较麻烦,还可以把这整个函数用宏定义进行替换,并且用宏定义替换的函数还可以有参数,叫有参宏。
以我们之前讲过的OLED的程序为例:

在宏定义后面加一个括号,里面写入形参,在实际引用的时候,传入实参。
这样实际上OLED_W_SCL(1)就等价于GPIO_WriteBit(GPIOB, GPIO_Pin_8, (BitAction)(1));
补充:BitAction是什么意思?
在STM32中,用于强制将特定的操作数转换为一个位值,将一个非零值转换为逻辑高电平(1),将零值转换为逻辑低电平(0)。
在GPI0操作中,可以使用"BitAction"宏定义来设置引脚的状态,例如通过调用GPI0 writeBit()函数来设置引脚的输出状态。
GPI0x表示GPIO端口,GPI0 Pin表示具体的引脚位,而BitAction表示要设置的引脚状态。
但是这种方法在移植到其他库或者其他种类单片机时,很多人都不知道怎么修改。另外还有这种宏定义的方法,如果换到一个主频很高的单片机中,需要对软件的时序进行延时操作的时候也不太方便进一步修改。
所以综合以上缺点,在这里我们就直接一点干脆再套个函数。如果单片机主频比较快,也非常方便加一些延时,比如每次操作引脚之后,都要延时10us。

后面再调用这个W_SCL,参数给1或0就可以释放或拉低SCL了。
对于STM32F1系列,这里即使不加任何延时,这个引脚翻转速度,MPU6050也能跟得上。但是保险起见,还是延时个十微秒。
如果要把这个程序移植到别的单片机,就可以把这个函数里的操作替换为其他单片机对应的操作。比如SCL是51单片机的P10口,就可以把GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);这句替换为P10=BitValue。
操作SDA的函数
接下来封装一下操作SDA的函数:

读和写不是同一个寄存器,再定义一个函数

有了这三个函数的分装,我们就实现了函数名称、端口号的替换。同时也可以很方便的修改时序的延时。当我们需要替换端口,或者把这个程序移植到别的单片机中时,就只需要对这前四个函数里的操作对应更改。
我们回到这个函数,开始调用以上四个函数。
我们需要先把SCL和SDA都释放,也就是都输出1,然后先拉低SDA。再拉低SCL,这就是起始条件的执行逻辑。
📌📌注意:我们最好把释放SDA的放在前面。
如果起始条件之前,SCL和SDA已经是高电平了,先释放哪一个是一样的效果。

📌📌但是后面start还要兼容这里的重复起始条件sr。
如果sr最开始SCL是低电平,SDA电平不敢确定,所以保险起见,趁SCL是低电平时,先确保释放SDA再释放SCL,这时SDA和SCL都是高电平。然后再拉低SDA拉低SCL,这样start就可以兼容起始条件和重复起始条件了。

接下来继续终止条件
终止条件
终止条件:SCL高电平期间,SDA从低电平切换到高电平

果stop开始时SCL和SDA都已经是低电平了,就先释放SCL,再释放SDA就行了。但是在这个时序单元开始时,SDA并不一定是低电平。

所以为了确保之后释放SDA,能产生上升沿,我们要在时序单元开始时先拉低SDA,然后再释放SCL,释放SDA。

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

实际上除了终止条件SCL以高电平结束,所有的单元我们都会保证SCL以低电平结束,这样方便各个单元的拼接。

SCL低电平变换数据,高电平保持数据稳定,由于是高位先行,所以变换数据的时候,按照先放最高位再放次高位,依次把一个字节的每一位放在SDA线上,每放完一位后执行释放SCL拉低SCL的操作,驱动时钟运转。
Byte & 0x80 就是保留字节的高位,对其他位清0,假设Byte是xxxx xxxxx

由于调用的这个函数中的参数最后会被强制转换成bitAction类型,所以非0即1,所以最终MyI2C_W_SDA(Byte & (0x80 >> i))也相当于传了一个1

接着继续写接收一个字节
接收一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)

主机需要先释放SDA,释放SDA也相当于切换为输入模式。
SCL低电平变换数据,高电平读取数据,实际上就是一种读写分离的设计,低电平时间定义为写的时间,高电平时间定义为读的时间。
SCL高电平时,SDA下降沿为起始条件,SDA上升沿为终止条件。这个设计也保证了起始和终止的特异性,能够让我们在连续不断的波形中快速的定位起始和终止。因为起始终止和数据传输的波形有本质区别。数据传输时SCL高电平不许动SDA,起始终止条件下是SCL高电平必须动SDA

📌📌注意:I2C是在进行通信,通信是有从机的,当主机不断驱动SCL时钟时,从机就有义务去改变SDA的电平。所以主机每次循环读取SDA的时候,这个读取到的数据是从机控制的,这个数据也正是从机想要给我们发送的数据。
发送应答
然后发送应答和接收应答只要复制发送一个字节和接收一个字节的函数修改一下就可以了。
发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答


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


📌📌注意:I2C的引脚都是开漏输出+弱上拉的配置。主机输出1并不是强制SDA为高电平,而是释放SDA;I2C通信时,主机释放了SDA,从机在此时把SDA再拉低的。所以这里即使之前主机把SDA置1再读取SDA,读到的值也可能是0,读到0代表从机给了应答,读到1代表从机没给应答。
测试应答功能
想要测试应答功能时主函数可以这样调用

这样就可以测试从机给不给应答的时序
1101 000是从机的地址,可以理解为是从机的名字,最低位的0是表示“写入操作”
这样运行后显示从机可以给我们应答

我们接下来讲一下通过AD0引脚改名的功能。
通过AD0引脚改名的功能
我们可以把一根飞线连接AD0引脚和VCC, 这时MPU6050的从机地址就是1101 001了。

这个时候运行就发现从机没有给我们应答了,因为它刚刚改名成1101 001了。
这个时候把飞线拔掉,再次运行发现它又可以应答了。

这就是改名的实验现象。目前我们这个芯片只有AD0一个引脚,它就只能拥有两个名字。如果有AD0和AD1两个引脚,就可以拥有总共四个名字。如果有更多的可配置引脚,就有更多的改名机会。当我们需要一条总件挂载多个相同型号的设备时,就可以利用这个改名的功能,避免名字也就是从机地址的重复。
相关文章:
江协科技STM32学习- P33 实验-软件I2C读写MPU6050
🚀write in front🚀 🔎大家好,我是黄桃罐头,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🎁欢迎各位→点赞👍 收藏⭐️ 留言📝…...
BusHound工具的使用-调试USB
12 1.Capture(捕捉按钮)、2.Save(保存按钮)、3.Setting(设置要监听的,输入输出)、4.Device(选择要监听的设备)、5.Help(帮助按钮)、6.Exit(退出按钮)。 一、Capture页面 1.Device 表示是29设备端口,打印机。 2.Phase,各类协议,…...
Hadoop生态圈框架部署(四)- Hadoop完全分布式部署
文章目录 前言一、Hadoop完全分布式部署(手动部署)1. 下载hadoop2. 上传安装包2. 解压hadoop安装包3. 配置hadoop配置文件3.1 虚拟机hadoop1修改hadoop配置文件3.1.1 修改 hadoop-env.sh 配置文件3.3.2 修改 core-site.xml 配置文件3.3.3 修改 hdfs-site…...
Spring Boot 与 Vue 共铸卓越采购管理新平台
作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 🍅获取源码联系方式请查看文末🍅 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目…...
leetcode3. Longest Substring Without Repeating Characters
Given a string s, find the length of the longest substring without repeating characters. Example 1: Input: s “abcabcbb” Output: 3 Explanation: The answer is “abc”, with the length of 3. Example 2: Input: s “bbbbb” Output: 1 Explanation: The ans…...
Mongodb使用视图连接两个集合
您可以使用 $lookup 为两个集合创建一个视图,然后对该视图运行查询。应用程序可以查询视图,而无需构建或维护复杂的管道。 例子 创建两个样本集合 inventory 和 orders: db.inventory.insertMany( [{ prodId: 100, price: 20, quantity: 1…...
SIP是什么?
SIP(Session Initiation Protocol,会话启动协议)是一个用于建立、更改和终止多媒体会话的应用层控制协议,其中的会话可以是IP电话、多媒体会话或多媒体会议。 SIP是IETF多媒体数据和控制体系结构的核心协议(最新RFC文档…...
Day 39 || 01背包、416. 分割等和子集
01背包 题目链接:卡码网第46题 二维解题思路:需要建立一个i行k列的dp数组,i表示每个物品,k代表容量,初始化数组子一列为0,第一行从背包开始能够放入起始为价值,其他都为0。for双循环先背包后物…...
调用detr-resnet-50进行目标检测
from transformers import DetrImageProcessor, DetrForObjectDetection import torch from PIL import Imageimage = Image.open("1.jpg") torch.set_default_device("cuda"...
Chromium 中chrome.fontSettings扩展接口定义c++
一、chrome.fontSettings 使用 chrome.fontSettings API 管理 Chrome 的字体设置。 权限 fontSettings 要使用 Font Settings API,您必须在扩展程序中声明 "fontSettings" 权限 清单。例如: {"name": "My Font Settings E…...
在Unity游戏开发在面试时会面试哪些内容?
1、请描述游戏动画有几种,以及其原理。 关键帧动画:每一帧动画序列当中包含了顶点的空间位置信息以及改变量,然后通过插值运算,得出动画效果。选中某一游戏对象,创建animation,添加属性Transform࿰…...
刘艳兵-DBA022-以下关于Oracle半连接的描述,哪些是正确的?
以下关于Oracle半连接的描述,哪些是正确的? A SQL中的NOT EXISTS子查询,通常会被转换为对应的半连接。 B SQL中的IN子查询,通常会被转换为对应的半连接。 C 半连接会去重 D SQL中的EXISTS子查询,通常会被转…...
人工智能与伦理:我们应该如何平衡科技与人性?
内容概要 在这个瞬息万变的时代,人工智能的迅猛发展让我们面对前所未有的伦理困境。科技进步带来了便利,但同时也亟需我们反思如何对待人性。尤其是在实现算法透明性时,我们要确保每一个决策背后都能被理解与追溯,这不仅是对技术…...
CRON组件一个复杂的一个简单的
CRON组件一个复杂的一个简单的 一个是复杂点的一个是简单点。 1.以简单的为例使用: 父组件 import CronSimple from "/views/xxx/components/cron-simple/index.vue";components: {CronSimple}<el-dialog title"调度CRON"v-if"cronV…...
自定义日志打成jar包引入项目后不生效
背景:写了一个请求响应日志包,打包后在另一个项目使用pom引入后不生效 package com.example.qqllog.aspect;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean;…...
RK3568平台开发系列讲解(中断篇)延迟工作实验
🚀返回专栏总目录 文章目录 一、什么是延迟工作二、 struct delayed_work三、延迟工作相关接口函数3.1、初始化延迟工作函数3.2、调度/取消调度 延迟工作函数四、驱动程序编写沉淀、分享、成长,让自己和他人都能有所收获!😄 一、什么是延迟工作 延迟工作是一种将工作的执…...
RabbitMQ 的集群
大家好,我是锋哥。今天分享关于【RabbitMQ 的集群】面试题?希望对大家有帮助; RabbitMQ 的集群 RabbitMQ 是一种流行的开源消息代理,广泛用于构建分布式系统中的消息队列。随着应用程序规模的扩大,单一的 RabbitMQ 实…...
整车功能架构 --- 智能座舱
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧…...
java stream流的使用
Java中的Stream API是Java 8引入的一个重要特性,它提供了对集合对象进行各种非常便利、高效的聚合操作(aggregate operation)或大批量数据操作(bulk data operation)。Stream API借助于Lambda表达式,极大地…...
(JVM)带你一起研究JVM的语法糖功能 和 JVM的即时编译器
1. 语法糖 所谓的语法糖,其实就是指java编译器把*.java源码编译为*.class字节码的过程中,自动生成和转换的一些代码,主要是为了减轻程序员的负担,算是java编译器给我们第一个额外福利 以下代码的分析,借助了javap工具…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
