STM32F4XX软件I2C驱动MPU6050

MPU6050

一、简介

MPU6050是一款6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角,常应用于平衡车、飞行器等需要检测自身姿态的场景。

  • 3轴加速度计(Accelerometer)
    测量X、Y、Z轴的加速度
  • 3轴陀螺仪传感器(Gyroscope)
    测量X、Y、Z轴的角速度

详细信息可参考产品说明书

二、软件I2C

这里给出STM32F4XXX软件I2C代码

#include "stm32f4xx.h"                  // Device header
#include "Delay.h"

//软件I2C,SDA和SCL引脚根据需要配置
//GPIO全在AHB1总线,这里选择PD2作SCL和PD3作SDA

/*封装I2C引脚电平函数*/
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOD, GPIO_Pin_2, (BitAction)BitValue);
	Delay_us(10);
}
void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOD, GPIO_Pin_3, (BitAction)BitValue);
	Delay_us(10);
}
uint8_t MyI2C_R_SDA()
{
	uint8_t BitValue = GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_3);//主机读取SDA引脚电平
	Delay_us(10);
	return BitValue;
}

/*I2C初始化函数,SDA和SCL同时为高电平*/
void MyI2C_Init()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOD, GPIO_Pin_2 | GPIO_Pin_3);//I2C处于空闲状态
}
/*I2C起始条件*/
void MyI2C_Start()
{
	//在SCL高电平期间,SDA从高电平切换到低电平,先拉低SDA再拉低SCL
	MyI2C_W_SDA(1);//先释放SDA
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}
/*I2C终止条件*/
void MyI2C_End()
{
	//在SCL高电平期间,SDA从低电平切换到高电平,先拉高SCL再拉高SDA
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}
/*发送一个字节*/
void MyI2C_SendByte(uint8_t Byte)
{
	//在SCL低电平期间,主机将数据依次放到SDA线上(高位先行)然后释放SCL
	for(uint8_t i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));//通过按位与将数据以高位先行的顺序写传输
		MyI2C_W_SCL(1);//从机在SCL高电平期间读取数据位
		MyI2C_W_SCL(0);//保证SCL以低电平结束确保下次数据传输
	}
}
/*接收一个字节*/
uint8_t MyI2C_ReceiveByte()
{
	//SCL低电平期间,从机将数据依次放到SDA线上(高位先行)然后释放SCL
	
	uint8_t Byte = 0x00;
	MyI2C_W_SDA(1);//为了防止主机干扰从机写入数据,需要主机释放SDA即转换为接收模式
	for(uint8_t i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);//主机在SCL高电平期间读取数据位
		if(MyI2C_R_SDA() == 1) Byte |= (0x80 >> i);
		MyI2C_W_SCL(0);
	}
	return Byte;
}
/*发送应答*/
//主机在接收完一个字节之后,在下一个时钟发送一位数据,0表示应答,1表示非应答
void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);
	MyI2C_W_SCL(1);//从机在SCL高电平期间读取应答位
	MyI2C_W_SCL(0);
}


/*接收应答*/
//主机在发送完一个字节之后,在下一个时钟接收一位数据以判断从机是否应答,0表示应答,1表示非应答
uint8_t MyI2C_ReceiveAck()
{ 
	uint8_t AckBit;
	MyI2C_W_SDA(1);//主机在接受之前要释放SDA,切换到接收状态
	MyI2C_W_SCL(1);//主机在SCL高电平期间读取应答位
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

三、MPU6050主要寄存器

  1. SMPLRT_DIV采样频率分频器
    MPU6050采样频率分频器
    用于配置采样频率的分频系数,分频越小内部AD转换越快,参照公式: 采样频率 = 陀螺仪输出时钟频率 1 + 分频值 采样频率 = \frac{陀螺仪输出时钟频率}{1+分频值} 采样频率=1+分频值陀螺仪输出时钟频率不使用低通滤波器时,陀螺仪时钟为8KHz。

  2. CONFIG配置寄存器
    MPU6050配置寄存器
    分两部分,外部同步设置和低通滤波器配置,一般只涉及到低通滤波器使数据更加平滑。

  3. GYRO_CONFIG陀螺仪配置寄存器
    MPU6050陀螺仪配置寄存器
    高三位是XYZ轴的自测使能位,中间两位是满量程选择位,低三位没用到。

  4. ACCEL_CONFIG加速度计配置寄存器
    MPU6050加速度寄存器
    加速度计配置寄存器和上面一样,只不过第三位是配置高通滤波器进行运动检测。

  5. 数据寄存器
    I2C从此处读取所需要的数据,是一个16位的有符号数,以二进制补码方式存储。读出高八位和第八位,高位左移八次或上低位数据即为原数据

  6. 电源管理寄存器
    寄存器1可用于设备复位、睡眠模式、循环模式(省电,唤醒的频率由寄存器2决定)、温度传感器失能和选择系统时钟来源(陀螺仪的晶振更加准确)。
    寄存器2可用于设置唤醒频率、分别控制6个轴进入待机模式

  7. 器件ID
    MPU6050ID
    这个寄存器只读,中间六位固定为1101 00,即I2C地址。

所有的寄存器上电默认值为0x00,除了107寄存器(0x40)和117寄存器(0x68)

四、MPU6050驱动

这里给出读一个字节的函数代码

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_Address);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();//重新指定读写位
	MyI2C_SendByte(MPU6050_Address | 0x01);//切换为读,控制权交给从机
	MyI2C_ReceiveAck();
	Data = MyI2C_ReceiveByte();//只读取一个字节
	MyI2C_SendAck(1);
	MyI2C_End();
	
	return Data;
}

对于在寄存器中写数据,需要根据寄存器地址进行操作,为方便对寄存器地址的调用这里用头文件包含所要用到的寄存器

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H
//MPU6050主要寄存器地址
#define	MPU6050_SMPLRT_DIV		0x19		//器件采样频率分频器寄存器
#define	MPU6050_CONFIG			0x1A		//器件配置寄存器
#define	MPU6050_GYRO_CONFIG		0x1B		//器件陀螺仪配置寄存器
#define	MPU6050_ACCEL_CONFIG	0x1C		//器件加速度配置寄存器

#define	MPU6050_ACCEL_XOUT_H	0x3B		//器件加速度数据寄存器
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41		//器件温度数据寄存器
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43		//器件陀螺仪数据寄存器
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

#define	MPU6050_PWR_MGMT_1		0x6B		//电源管理寄存器1
#define	MPU6050_PWR_MGMT_2		0x6C		//电源管理寄存器2
#define	MPU6050_WHO_AM_I		0x75		//器件ID

#endif

要在MPU6050寄存器中写数据,首先要解除睡眠模式,这里给出MPU6050初始化代码

void MPU6050_Init()
{
	MyI2C_Init();
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//解除睡眠模式,同时配置x轴陀螺仪时钟
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x01);//不需要循环模式同时不需要待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//设置10分频
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);//不需要外部同步,低通滤波设置为110
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//不需要自测,选择最大量程
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//不需要自测,选择最大量程,不需要高通滤波
}

初始化之后,陀螺仪就不断的产生数据存在寄存器中,不断读取数据寄存器数值即可

//读取寄存器数据值
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
	uint8_t DataH, DataL;
	//寄存器中的值是16位有符号数,以二进制补码形式存储
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);//高8位
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低8位
	*AccX = (DataH << 8) | DataL;//拼接为16位原数据
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	*AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	*AccZ = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	*GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	*GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	*GyroZ = (DataH << 8) | DataL;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电子档案数据迁移什么意思?电子档案数据迁移流程

电子档案数据迁移是指将现有的电子档案数据从一个系统或存储设备迁移到另一个系统或存储设备的过程。这个过程可以包括将数据从旧的存储介质转移到新的存储介质&#xff0c;或将数据从一个系统迁移到另一个系统。电子档案数据迁移通常是为了更好地管理和保护档案数据&#xff0…

推荐一款搜索文件夹中内容的软件--FileSeek

介绍一个在文件夹中搜索文件内容的软件FileSeek 软件中一些功能较为清晰&#xff0c;不懂的话翻一下就行&#xff0c;我觉得使用其普通功能就可以解决大多数问题&#xff0c;就是在文件夹中查找文件中的内容。这帮助我们进行内容筛选有很大的帮助。例如上诉案例就是在ctf中我们…

【Flutter】三个Channel(Android-java / Ios-swift)

Channel 实现与原生通信 【1】MethodChannel flutter MethodChannel官方文档 通过MethodChannel来传递数据&#xff0c;调用方法 案例 分别调用Android和Ios原生的获取电量的方法 Flutter端 实例一个MethodChannel&#xff0c; 唯一标识name&#xff0c;定义方法名称get…

linux大文件IO

在Linux中处理大文件&#xff08;通常指大小超过2GB的文件&#xff09;时&#xff0c;需要使用特定的系统调用和标志&#xff0c;以确保程序能够正确地处理大文件的读写。这主要是因为在32位系统上&#xff0c;传统的文件偏移量和文件大小使用off_t类型表示&#xff0c;它通常是…

RabbitMQ的自动应答和手动应答,解决重试死循环

RabbitMQ的自动应答和手动应答&#xff0c;解决重试死循环 1.应答模式 RabbitMQ 中的消息应答模式主要包括两种&#xff1a;自动应答&#xff08;Automatic Acknowledgement&#xff09;和手动应答&#xff08;Manual Acknowledgement&#xff09;。 1、自动应答&#xff1a;…

ctfshow web入门 文件上传web162--web167

web162 session文件包含条件竞争 直接包含不传马了 我们上传的文件如果不符合要求&#xff0c;就会被删除&#xff0c;导致成功上传无法访问&#xff0c;没有用。但是如果我们上传的速度比服务器删的速度快&#xff0c;就可以了。 上传.user.ini GIF89a auto_append_file/tmp/…

医院预约系统微信小程序APP前后端

医院预约系统具体功能介绍&#xff1a;展示信息、可以注册和登录&#xff0c; 预约&#xff08;包含各个科室的预约&#xff0c;可以预约每个各个医生&#xff09;&#xff0c;就诊引导包含预约的具体信息&#xff0c;包含就诊时间、就诊科室、就诊医生以及就诊人信息、和支付状…

Unity之Unity面试题(三)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;三&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…

2025考研数学汤家凤基础班百度网盘视频+强化班PDF讲义持续更新

如果25考研想全程跟张宇老师&#xff0c;可以参考下面这个表格来使用资料&#xff1a; 2025考研数学全程课&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1e6wA4OiH_EJpZPXPxoHYwg 提取码&#xff1a;om45 考研数学 考研数学无非就是汤家凤老师&#xff0c;张宇老师…

政安晨:【深度学习神经网络基础】(五)—— 霍普菲尔德神经网络和玻尔兹曼机

目录 简述 霍普菲尔德神经网络 训练霍普菲尔德神经网络 Hopfield-Tank神经网络 玻尔兹曼机 总之 政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&am…

Linux安装Oracle11g(无图形界面下的静默安装)

Oracle11g安装文档-Linux静默安装 环境准备安装数据库配置监听器创建数据库测试打开防火墙 环境准备 创建组和用户 [rootlocalhost ~]# groupadd oinstall #创建oinstall组 [rootlocalhost ~]# groupadd dba  #创建dba组 [rootlocalhost ~]# useradd -g oinstall -G dba -m…

【快捷部署】016_Ollama(CPU only版)

&#x1f4e3;【快捷部署系列】016期信息 编号选型版本操作系统部署形式部署模式复检时间016Ollama&#xff08;CPU only&#xff09;latestCentOS 7.XDocker单机2024-04-10 注意事项&#xff1a; 1、目前镜像及大模型下载速度尚可&#xff0c;但由于容量较大&#xff0c;所以…

K8S:常用资源对象操作

文章目录 一、使用Replication Controller(RC)、Replica Set(RS) 管理Pod1 Replication Controller&#xff08;RC&#xff09;2 Replication Set&#xff08;RS&#xff09; 二、Deployment的使用1 创建2 滚动升级3 回滚Deployment三、 Pod 自动扩缩容HPA1 使用kubectl autosc…

thinkphp5关联预载入with指定字段属性查询

一、thinkphp5.0 如果要指定属性查询&#xff0c;可以使用&#xff1a; $list User::field(id,name)->with([profile>function($query){$query->field(email,phone);}])->select([1,2,3]); foreach($list as $user){// 获取用户关联的profile模型数据dump($user…

典型新能源汽车热管理系统方案分析

目前行业具有代表性的热管理系统有PTC电加热方案、热泵方案&#xff08;特斯拉八通阀热泵、吉利直接式热泵&#xff09;、威马的柴油加热方案以及以理想为代表的插电式混动车方案。 小鹏P7整车热管理方案分析&#xff08;PTC电加热方案&#xff09; 小鹏P7作为小鹏汽车的第2款…

NzN的数据结构--插入排序

排序排序我要Disney&#xff0c;今天我们先来看看经典排序算法里的插入排序&#xff0c;先三连后看才是好习惯&#xff01;&#xff01;&#xff01; 目录 一、排序的概念及应用 1. 排序的概念 2. 排序的应用 3. 常见的排序算法 二、插入排序 1. 基本思想 2. 直接插入排…

pyside6的QSpinBox自定义特性初步研究(二)

当前的需求是&#xff0c;蓝色背景的画面&#xff0c;需要一个相对应色系的QSpinBox部件。已有的部件风格是这样的&#xff0c;需要新的部件与之般配。 首先新建一个QDoubleSpinBox&#xff0c;并定义其背景色和边框&#xff1a; QDoubleSpinBox { color: white; border:1px…

Vue3---基础1(认识,创建)

变化 相对于Vue2&#xff0c;Vue3的变化&#xff1a; 性能的提升 打包大小减少 41% 初次渲染快 55%&#xff0c;更新渲染快133% 内存减少54% 源码的升级 使用 proxy 代替 defineProperty 实现响应式 重写虚拟 DOM 的实现和 Tree-shaking TypeScript Vue3就可以更好的支持TypeSc…

Python:如何对FY3D TSHS的数据集进行重投影并输出为TIFF文件以及批量镶嵌插值?

完整代码见 Github&#xff1a;https://github.com/ChaoQiezi/read_fy3d_tshs&#xff0c;由于代码中注释较为详细&#xff0c;因此博客中部分操作一笔带过。 01 FY3D的HDF转TIFF 1.1 数据集说明 FY3D TSHS数据集是二级产品(TSHS即MWTS/MWHS 融合大气温湿度廓线/稳定度指数/…

ssm“最多跑一次”微信小程序

采用技术 ssm“最多跑一次”微信小程序的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统实现的功能 本次设计任务是要设计一个“最多跑一次”微信小程序&#xff0c;…