This commit is contained in:
Zengtudor 2025-04-13 23:08:43 +08:00
parent 4638f385c8
commit a14b5b69de
6 changed files with 268 additions and 23 deletions

View File

@ -311,7 +311,7 @@
</ArmAdsMisc>
<Cads>
<interw>1</interw>
<Optim>3</Optim>
<Optim>1</Optim>
<oTime>0</oTime>
<SplitLS>0</SplitLS>
<OneElfS>1</OneElfS>

28
Src/MPU6050_Reg.h Normal file
View File

@ -0,0 +1,28 @@
#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

View File

@ -1,28 +1,41 @@
#include "Delay.hpp"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "ztLed.hpp"
#include "ztOLED.hpp"
#include "stm32f10x_rcc.h"
#include "ztMpu6050.hpp"
#include "ztOled.hpp"
#include <cstdint>
#include <stdio.h>
int main(){
zt::Led leda0(RCC_APB2Periph_GPIOA,GPIO_Pin_0,GPIOA);
zt::Led ledc13(RCC_APB2Periph_GPIOC,GPIO_Pin_13,GPIOC);
// zt::Led leda0(RCC_APB2Periph_GPIOA,GPIO_Pin_0,GPIOA);
// zt::Led ledc13(RCC_APB2Periph_GPIOC,GPIO_Pin_13,GPIOC);
zt::Oled oled(RCC_APB2Periph_GPIOB,GPIOB,GPIO_Pin_8,GPIO_Pin_9);
oled.ShowString(1, 1, "Hello,world!")
.ShowString(2, 1, "by Zengtudor")
.ShowString(3, 1, "From BDFS EECRPD")
.ShowString(4, 1, "time:");
.ShowString(2, 1, "by Zengtudor")
.ShowString(3, 1, "From BDFS EECRPD")
.ShowString(4, 1, "time:");
u32 delayTime = 500;
u32 time = 0;
delay_ms(500);
zt::Mpu6050 mpu(RCC_APB1Periph_I2C2,I2C2,RCC_APB2Periph_GPIOB,GPIOB,GPIO_Pin_10,GPIO_Pin_11);
int16_t arr[6],first[6];
oled.Clear();
const float change = 32767.0f/4.0f;
char c[3][50];
mpu.MPU6050_GetData(arr, arr+1, arr+2, arr+3, arr+4, arr+5);
first[0]=arr[0],first[1]=arr[1],first[2]=arr[2];
while(true){
time++;
leda0.setOn();
ledc13.setOff();
delay_ms(delayTime);
leda0.setOff();
ledc13.setOn();
delay_ms(delayTime);
oled.ShowUNum(4, 6, time);
mpu.MPU6050_GetData(arr, arr+1, arr+2, arr+3, arr+4, arr+5);
sprintf(c[0], "%.2f",float(arr[0]-first[0])/change);
sprintf(c[1], "%.2f",float(arr[1]-first[1])/change);
sprintf(c[2], "%.2f",float(arr[2]-first[2])/change);
oled.ShowString(1, 1, "id:")
.ShowUNum(1,4,mpu.MPU6050_GetID())
.ShowString(2,1,c[0])
.ShowString(3,1,c[1])
.ShowString(4,1,c[2]);
}
}

View File

@ -16,8 +16,8 @@ namespace zt{
GPIO_Init(_GPIOx, &gpioInitStructure);
}
virtual ~Led(){
GPIO_DeInit(_GPIOx);
RCC_APB2PeriphClockCmd(_RCC_APB2Periph, DISABLE);
// GPIO_DeInit(_GPIOx);
// RCC_APB2PeriphClockCmd(_RCC_APB2Periph, DISABLE);
}
Led& setOn(){
GPIO_SetBits(_GPIOx, _GPIO_Pin);

205
Src/ztMpu6050.hpp Normal file
View File

@ -0,0 +1,205 @@
#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 XYZ轴的数据使-32768~32767
* GyroX GyroY GyroZ XYZ轴的数据使-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(){
}
};
}

View File

@ -349,7 +349,6 @@ namespace zt{
return *this;
}
Oled(const u32 &RCC_APB2Periph,GPIO_TypeDef *const& GPIOx,const u16 &GPIO_PIN_SCL,const u16 &GPIO_PIN_SDA)
:_RCC_APB2Periph(RCC_APB2Periph),_GPIOx(GPIOx),_GPIO_PIN_SCL(GPIO_PIN_SCL),_GPIO_PIN_SDA(GPIO_PIN_SDA){
RCC_APB2PeriphClockCmd(_RCC_APB2Periph, ENABLE);
@ -368,8 +367,8 @@ namespace zt{
Init();
}
virtual ~Oled(){
GPIO_DeInit(_GPIOx);
RCC_APB2PeriphClockCmd(_RCC_APB2Periph, DISABLE);
// GPIO_DeInit(_GPIOx);
// RCC_APB2PeriphClockCmd(_RCC_APB2Periph, DISABLE);
}
};
}