stm32TestTempl/Src/ztMpu6050.hpp
2025-04-13 23:08:43 +08:00

205 lines
10 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include "stm32f10x.h" // Device header
#include "MPU6050_Reg.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_rcc.h"
#include <cstdint>
#define MPU6050_ADDRESS 0xD0 //MPU6050的I2C从机地址
namespace zt {
class Mpu6050{
private:
/**
* 函 数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(I2Cx, ENABLE); //硬件I2C生成起始条件
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS, I2C_Direction_Transmitter); //硬件I2C发送从机地址方向为发送
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //等待EV6
I2C_SendData(I2Cx, RegAddress); //硬件I2C发送寄存器地址
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING); //等待EV8
I2C_SendData(I2Cx, Data); //硬件I2C发送数据
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED); //等待EV8_2
I2C_GenerateSTOP(I2Cx, ENABLE); //硬件I2C生成终止条件
}
/**
* 函 数MPU6050读寄存器
* 参 数RegAddress 寄存器地址范围参考MPU6050手册的寄存器描述
* 返 回 值读取寄存器的数据范围0x00~0xFF
*/
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
uint8_t Data;
I2C_GenerateSTART(I2Cx, ENABLE); //硬件I2C生成起始条件
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS, I2C_Direction_Transmitter); //硬件I2C发送从机地址方向为发送
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //等待EV6
I2C_SendData(I2Cx, RegAddress); //硬件I2C发送寄存器地址
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED); //等待EV8_2
I2C_GenerateSTART(I2Cx, ENABLE); //硬件I2C生成重复起始条件
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
I2C_Send7bitAddress(I2Cx, MPU6050_ADDRESS, I2C_Direction_Receiver); //硬件I2C发送从机地址方向为接收
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //等待EV6
I2C_AcknowledgeConfig(I2Cx, DISABLE); //在接收最后一个字节之前提前将应答失能
I2C_GenerateSTOP(I2Cx, ENABLE); //在接收最后一个字节之前提前申请停止条件
MPU6050_WaitEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED); //等待EV7
Data = I2C_ReceiveData(I2Cx); //接收数据寄存器
I2C_AcknowledgeConfig(I2Cx, ENABLE); //将应答恢复为使能,为了不影响后续可能产生的读取多字节操作
return Data;
}
/**
* 函 数MPU6050初始化
* 参 数:无
* 返 回 值:无
*/
void MPU6050_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph, ENABLE); //开启I2Cx的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph, 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_Pin=GPIO_Pin_SCL|GPIO_Pin_SDA;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOx, &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(I2Cx, &I2C_InitStructure); //将结构体变量交给I2C_Init配置I2Cx
/*I2C使能*/
I2C_Cmd(I2Cx, ENABLE); //使能I2Cx开始运行
/*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, 0x08); //加速度计配置寄存器选择满量程为±16g
}
/**
* 函 数MPU6050获取ID号
* 参 数:无
* 返 回 值MPU6050的ID号
*/
public:
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)
{
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; //数据拼接,通过输出参数返回
}
/*
获取加速度,返回值为tuple(float...) x,y,z
*/
// std::tuple<float,float,float> getAcc(){
// int16_t arr[6];
// MPU6050_GetData(arr, arr+1, arr+2, arr+3, arr+4, arr+5);
// const float change = 16384.0f;
// return std::make_tuple(float(arr[0])/change,float(arr[1])/change,float(arr[2])/change);
// }
private:
const u32 RCC_APB2Periph,RCC_APB1Periph;
const u16 GPIO_Pin_SCL,GPIO_Pin_SDA;
GPIO_TypeDef *const GPIOx;
I2C_TypeDef *const I2Cx;
public:
Mpu6050(const u32 &RCC_APB1Periph,I2C_TypeDef *const &I2Cx,const u32 &RCC_APB2Periph,GPIO_TypeDef *const& GPIOx ,const u16 &GPIO_Pin_SCL,const u16 &GPIO_Pin_SDA):RCC_APB1Periph(RCC_APB1Periph),I2Cx(I2Cx),RCC_APB2Periph(RCC_APB2Periph),GPIO_Pin_SCL(GPIO_Pin_SCL),GPIO_Pin_SDA(GPIO_Pin_SDA),GPIOx(GPIOx){
MPU6050_Init();
}
virtual ~Mpu6050(){
}
};
}