STM32利用硬件I2C读取MPU6050陀螺仪数据

news2024/12/23 12:33:50

有了前面的基本配置,这节读取MPU6050的数据还算是简单,主要就是初始化时给MPU6050一些配置,取消睡眠模式,MPU6050开机是默认睡眠模式的,读写无效,所以上来就要先更改配置:

MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器:

电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪

电源管理寄存器2,保持默认值0,所有轴均不待机

采样率分频寄存器,配置采样率

配置寄存器,配置DLPF

陀螺仪配置寄存器,选择满量程为±2000°/s

加速度计配置寄存器,选择满量程为±16g

配置完MPU6050的各个功能寄存器,剩下的就是读取陀螺仪的数据了。

 函    数:MPU6050获取数据
 参    数:AccX AccY AccZ 加速度计X、Y、Z轴的数据,使用输出参数的形式返回,范     围:-32768~32767

参    数:GyroX GyroY GyroZ 陀螺仪X、Y、Z轴的数据,使用输出参数的形式返回,范           围:-32768~32767

读取加速度计X轴的高8位数据

读取加速度计X轴的低8位数据

数据拼接,通过输出参数返回

MUP6050.c文件:

#include "stm32f10x.h"                  // Device header
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS		0xD0		//MPU6050的I2C从机地址

/**
  * 函    数:MPU6050等待事件
  * 参    数:同I2C_CheckEvent
  * 返 回 值:无
  */
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t Timeout;
	Timeout = 10000;									//给定超时计数时间
	while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)	//循环等待指定事件
	{
		Timeout --;										//等待时,计数值自减
		if (Timeout == 0)								//自减到0后,等待超时
		{
			/*超时的错误处理代码,可以添加到此处*/
			break;										//跳出等待,不等了
		}
	}
}

/**
  * 函    数:MPU6050写寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 参    数:Data 要写入寄存器的数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);	//硬件I2C发送从机地址,方向为发送
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);	//等待EV6
	
	I2C_SendData(I2C2, RegAddress);											//硬件I2C发送寄存器地址
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);			//等待EV8
	
	I2C_SendData(I2C2, Data);												//硬件I2C发送数据
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);				//等待EV8_2
	
	I2C_GenerateSTOP(I2C2, ENABLE);											//硬件I2C生成终止条件
}

/**
  * 函    数:MPU6050读寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 返 回 值:读取寄存器的数据,范围:0x00~0xFF
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);	//硬件I2C发送从机地址,方向为发送
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);	//等待EV6
	
	I2C_SendData(I2C2, RegAddress);											//硬件I2C发送寄存器地址
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);				//等待EV8_2
	
	I2C_GenerateSTART(I2C2, ENABLE);										//硬件I2C生成重复起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);					//等待EV5
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);		//硬件I2C发送从机地址,方向为接收
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);		//等待EV6
	
	I2C_AcknowledgeConfig(I2C2, DISABLE);									//在接收最后一个字节之前提前将应答失能
	I2C_GenerateSTOP(I2C2, ENABLE);											//在接收最后一个字节之前提前申请停止条件
	
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);				//等待EV7
	Data = I2C_ReceiveData(I2C2);											//接收数据寄存器
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);									//将应答恢复为使能,为了不影响后续可能产生的读取多字节操作
	
	return Data;
}

/**
  * 函    数:MPU6050初始化
  * 参    数:无
  * 返 回 值:无
  */
void MPU6050_Init(void)
{
	/*开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);		//开启I2C2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);		//开启GPIOB的时钟
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);					//将PB10和PB11引脚初始化为复用开漏输出
	
	/*I2C初始化*/
	I2C_InitTypeDef I2C_InitStructure;						//定义结构体变量
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;				//模式,选择为I2C模式
	I2C_InitStructure.I2C_ClockSpeed = 50000;				//时钟速度,选择为50KHz
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;		//时钟占空比,选择Tlow/Thigh = 2
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;				//应答,选择使能
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	//应答地址,选择7位,从机模式下才有效
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;				//自身地址,从机模式下才有效
	I2C_Init(I2C2, &I2C_InitStructure);						//将结构体变量交给I2C_Init,配置I2C2
	
	/*I2C使能*/
	I2C_Cmd(I2C2, ENABLE);									//使能I2C2,开始运行
	
	/*MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器*/
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);				//电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);				//电源管理寄存器2,保持默认值0,所有轴均不待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);				//采样率分频寄存器,配置采样率
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);					//配置寄存器,配置DLPF
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);			//陀螺仪配置寄存器,选择满量程为±2000°/s
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);			//加速度计配置寄存器,选择满量程为±16g
}


/**
  * 函    数:MPU6050获取ID号
  * 参    数:无
  * 返 回 值:MPU6050的ID号
  */
uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);		//返回WHO_AM_I寄存器的值
}

/**
  * 函    数:MPU6050获取数据
  * 参    数:AccX AccY AccZ 加速度计X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 参    数:GyroX GyroY GyroZ 陀螺仪X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 返 回 值:无
  */
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ, int16_t *Temp)
{
	uint8_t DataH, DataL;								//定义数据高8位和低8位的变量
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);		//读取加速度计X轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);		//读取加速度计X轴的低8位数据
	*AccX = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);		//读取加速度计Y轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);		//读取加速度计Y轴的低8位数据
	*AccY = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);		//读取加速度计Z轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);		//读取加速度计Z轴的低8位数据
	*AccZ = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);		//读取陀螺仪X轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);		//读取陀螺仪X轴的低8位数据
	*GyroX = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);		//读取陀螺仪Y轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);		//读取陀螺仪Y轴的低8位数据
	*GyroY = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);		//读取陀螺仪Z轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);		//读取陀螺仪Z轴的低8位数据
	*GyroZ = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_TEMP_OUT_H);		//读取温度传感器的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_TEMP_OUT_L);		//读取温度传感器的低8位数据
	*Temp = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
}

MPU6050.h文件:

#ifndef __MPU6050_H
#define __MPU6050_H

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ, int16_t *Temp);

#endif

MPU6050_Reg.h文件:

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H

#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
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

#endif

main.c文件:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"

uint8_t ID;								//定义用于存放ID号的变量
int16_t AX, AY, AZ, GX, GY, GZ, TM;			//定义用于存放各个数据的变量

int main(void)
{
	/*模块初始化*/
	OLED_Init();		//OLED初始化
	MPU6050_Init();		//MPU6050初始化
	
	/*显示ID号*/
	OLED_ShowString(1, 1, "ID:");		//显示静态字符串
	ID = MPU6050_GetID();				//获取MPU6050的ID号
	OLED_ShowHexNum(1, 4, ID, 2);		//OLED显示ID号
	
	while (1)
	{
		MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ, &TM);		//获取MPU6050的数据
		OLED_ShowNum(1,8, (TM/340 + 36.5), 2);                //显示温度
		
		OLED_ShowSignedNum(2, 1, AX, 5);					//OLED显示数据
		OLED_ShowSignedNum(3, 1, AY, 5);
		OLED_ShowSignedNum(4, 1, AZ, 5);
		OLED_ShowSignedNum(2, 8, GX, 5);
		OLED_ShowSignedNum(3, 8, GY, 5);
		OLED_ShowSignedNum(4, 8, GZ, 5);
	}
}

以上文件通过编译后下载到芯片中就能得到如下图的结果了:

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

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

相关文章

SSH远程登录实操实验!

ssh远程登录协议&#xff1a;默认端口号22 以下实验7-2是服务端&#xff0c;7-1是客户端 服务器的相关信息&#xff1a; 服务名称&#xff1a;sshd 服务端主程序&#xff1a;/usr/sbin/sshd 服务端配置文件&#xff1a;/etc/ssh/sshd_config 客户端相关信息&#xff1a; …

【学习vue 3.x】(五)VueRouter路由与Vuex状态管理

文章目录 章节介绍本章学习目标 路由的基本搭建与嵌套路由模式vue路由的搭建嵌套路由模式 动态路由模式与编程式路由模式动态路由模式编程式路由 命名路由与命名视图与路由元信息命名路由命名视图路由元信息 路由传递参数的多种方式及应用场景路由传参 详解route对象与router对…

java入门-包装类

包装类 Java语言是一个面向对象的语言&#xff0c;但是Java中的基本数据类型却是不面向对象的。基本类型的数据不具备"对象"的特性&#xff08;没有属性和方法可以调用&#xff09;&#xff0c;因此&#xff0c;java为每种数据类型分别设计了对应的类&#xff0c;即*…

生成式AI定义全新座舱体验

生成式AI定义全新座舱体验 随着人工智能技术的飞速发展&#xff0c;生成式AI作为其中的佼佼者&#xff0c;正以其独特的魅力重新定义着我们的座舱体验。本文将深入探讨生成式AI的定义、特点及其在座舱体验中的应用&#xff0c;同时分析全新座舱体验的定义、特点&#xff0c;以及…

【LeetCode刷题记录】101. 对称二叉树

101 对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xf…

三维SDMTSP:GWO灰狼优化算法求解三维单仓库多旅行商问题,可以更改数据集和起点(MATLAB代码)

一、单仓库多旅行商问题 多旅行商问题&#xff08;Multiple Traveling Salesman Problem, MTSP&#xff09;是著名的旅行商问题&#xff08;Traveling Salesman Problem, TSP&#xff09;的延伸&#xff0c;多旅行商问题定义为&#xff1a;给定一个&#x1d45b;座城市的城市集…

4-b12(汉诺塔),要求给出移动过程中每根柱子上现有的圆盘数量及编号

【要求&#xff1a;】 1、假设圆盘最大数量为10&#xff0c;其余输入格式要求同前 2、要求打印初始状态下&#xff0c;起始圆柱拥有的圆盘数及每个圆盘的编号&#xff0c;在随后的每个移动步骤中&#xff0c;打印移动完成后每个圆柱的现有的圆盘数及编号&#xff08;效果如下…

基于SSM的志愿者管理系统(含源码+sql+视频导入教程+文档+PPT)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的志愿者管理系统3拥有三个角色&#xff1a; 管理员&#xff1a;用户管理、志愿组织管理、注册申请观看、活动管理、报名管理、打卡管理、公告管理等 用户&#xff1a;登录注册、…

C语言----函数

1.函数的概念 函数&#xff1a;founction c语言的程序代码都是函数组成的 c语言中的函数就是一个完成某项特定的任务的一段代码&#xff0c;这段代码有特殊的写法和调用方法 c语言中我们一般见到两种函数&#xff1a; .库函数 .自定义函数 2.库函数 有对应的头文件 #i…

咸鱼之王攻略:2024强阵容搭配

欢迎来到《咸鱼之王》的世界&#xff01;作为一款集合了策略与角色扮演元素的游戏&#xff0c;本攻略将为您提供一系列关于游戏阵容搭配和咸将选择的建议&#xff0c;帮助您在游戏中更好地获得胜利。 1.了解游戏阵营 《咸鱼之王》分为四个阵营&#xff1a;魏、蜀、吴、群。每个…

什么是 Web3 的生成式 AI?

从 Web 1.0 的静态、单向通信到 Web 2.0 的动态、用户驱动的格局&#xff0c;互联网在二十年的时间里经历了一场显着的转变。现在&#xff0c;当我们站在 Web 3.0 时代的边缘时&#xff0c;我们正在见证更具颠覆性的事物的曙光&#xff1a;生成式人工智能 (AI) 融入我们的数字世…

anything-llm的嵌入式聊天小部件

anything-llm 详情移步到官方: https://github.com/Mintplex-Labs/anything-llm anything-llm可以docker启动和本地启动 例如&#xff1a;docker 启动&#xff0c; 自行去安装docker哈 cd 到docker文件夹下&#xff0c; 窗口运行&#xff1a; docker-compose up -d --build运…

数据库基础--MySQL简介以及基础MySQL操作

数据库概述 数据库&#xff08;DATABASE&#xff0c;简称DB&#xff09; 定义:是按照数据结构来组织、存储和管理数据的仓库.保存有组织的数据的容器(通常是一个文件或一组文件) 数据库管理系统(Database Management System,简称DBMS) 专门用于管理数据库的计算机系统软件;…

[1671]jsp教材管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 JSP 教材管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql5.0&…

IP-guard WebServer 2024年两个漏洞简单分析

前言 这个漏洞看完索然无味&#xff0c;但是手上又刚好有源码&#xff0c;不看他一下又觉得可惜 权限绕过漏洞(QVD-2024-14103)简单分析 网上冲浪的时候&#xff0c;看到个买不起的CSDN专栏 这里基本上定位到是_mApplyList 出了问题&#xff0c;前面两个是ipguard webserve…

Flutter笔记:Widgets Easier组件库(4)使用按钮组

Flutter笔记 Widgets Easier组件库&#xff08;4&#xff09;&#xff1a;使用按钮组 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress…

2024五一数学建模C题保姆级分析完整思路+代码+数据教学

2024五一数学建模竞赛&#xff08;五一赛&#xff09;C题保姆级分析完整思路代码数据教学 煤炭是中国的主要能源和重要的工业原料。然而&#xff0c;随着开采深度的增加&#xff0c;地应力增大&#xff0c;井下煤岩动力灾害风险越来越大&#xff0c;严重影响着煤矿的安全高效开…

机器学习实战 —— 工业蒸汽量预测(二)

目录 文章描述背景描述数据说明数据来源实战内容2.数据特征工程2.1数据预处理和特征处理2.1.1 异常值分析2.1.2 归一化处理2.1.3 特征相关性 2.2 特征降维2.2.1 相关性初筛2.2.2 多重共线性分析2.2.3 PCA处理降维 文章描述 数据分析&#xff1a;查看变量间相关性以及找出关键变…

2024年第二十六届“华东杯”(A题)大学生数学建模挑战赛|数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 让我们来看看华东杯 (A题&#xff09;&#xff01; 问题一&a…

数组模拟双链表-java

通过数组来模拟双链表&#xff0c;并执行一些插入和删除的功能。 目录 一、问题描述 二、模拟思路 1.变量解释 2.数组初始化 3.在下标是k的结点后面插入一个结点 4.删除下标为k的结点 5.基本功能解释 三、代码如下 1.代码如下&#xff1a; 2.读入数据&#xff1a; 3…