简介

2024-6-18-更新 我们要实现PID算法,需要反馈值。那么,这个值,我们该怎么获取呢? 这里我拿平衡小车举个例子。我们的平衡小车;既然想要做到平衡且不倒的话,就需要把它的三轴角速度和三轴加速度的值放到PID算法中,然后得出值再运用到PWM,最后通过PWM来控制电机调动。(MPU6050可以胜任)
所以我们的思路如下:

  1. I2C来获取MPU6050的六轴数据Data
  2. 把获取的Data 传输到 PID算法中获取反馈值 Tes
  3. 再把Tes用与PWM中
  4. PWM调控电机模块(我称为Motor)
    那么事不宜迟,开始吧!!!
    fighting

    MPU6050模块

    何为MPU6050?

    MPU6050
    1.MPU6050是一个6轴姿态传感器(3轴加速度计和3轴陀螺仪传感器),可以测量芯片自身X、Y、Z轴的加速度、角度参数(角速度),通过数据融合,可以得到姿态角(由上图所示)。并且我们可以看到横向的是x轴,而纵向的为y轴,垂直与芯片的为z轴,这里我们可以类比中学时期的立体几何坐标图

姿态角
2. 以立创给的图为例,飞机机身对应三个轴的夹角,机头下倾或者上仰,这个轴的夹角叫俯仰(pitch)。飞机机身左翻滚或者右翻滚,这个轴的夹角叫做滚转(roll),飞机机身向左转向或者向右转向,这个轴的夹角叫做偏航(raw)。(2024-6-18 记得插入解释视频)

续—-欧拉角是为表示姿态的一种参数。为了保持飞机的姿态平稳(无人机也是)我们必须得到一个精确且问题的角;(此处—-江协科技有提过)一种传感器不能获得精确且稳定的欧拉角,要获得精确稳定的欧拉角,需要多个传感器进行数据融合。常见的数据融合算法有互补滤波、卡尔曼滤波等。

提示: 加速度只有静态稳定性,不具有动态稳定新性;而陀螺仪传感器只有动态稳定性,而不具有静态稳定性。 具体请看:”https://blog.csdn.net/qq_44852376/article/details/130470815
此CSDN博客的基本介绍,我就不在此处一一介绍了

MPU6050模块的基本参数

1. 16位ADC采集传感器的模拟信号,量化范围:-32768~32767。

2. 加速度计满量程范围选择:±2、±4、±8、±16(g) g表示重力加速度1g=9.8m/s²

3. 陀螺仪满量程选择:±250、±500、±1000、±2000(°/sec) 每秒钟旋转了多少度(如果测量的物体运动非常剧烈,可以把满量程选择大一些,如果运动比较平缓,可以选择更小的量程,这样分辨率会更大。)

4. 可配置的数字低通滤波器(在这个芯片可以配置寄存器来选择对输出的数据进行低通滤波)

5. 可配置的时钟源和可配置的采样分频(为AD转换和芯片内部其他电路提供时钟,控制分频系数,可以控制AD转化的快慢。)

6. I2C从机地址:当AD0=0时,地址为1101000,当AD0=1时,地址为1101001,AD0是板子引出来的引脚,可以调节I2C从机地址的最低位。(16位表示时,有两种方式,①是把1101000转成16进制0x68,但是因为还有一位读写位,一般使用(0x68<<1)|读写位。读1写0。②把0x68左移一位后的数据当作从机地址,也就是0xD0,再或上读写位。写就发送0xD0,读就发送0xD1。 这里读写位很重要。后面写代码具体用到

MPU6050读写

2024-6-19 更新

软件读写MPU6050

Tips: 这里我就不写头文件了,头文件同样写在HardWare中

1. MyI2C.c\HardWare

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "stm32f10x.h"                  // Device header
#include "Delay.h"


/***********************

以下三个操作是来封装读写操作的:
1、 SCL写操作

2、 SDA写操作

3、 SDA读操作

移植到别的单片机时,只需要对以下四个函数进行修改即可。

************************/

void MyI2C_W_SCL(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_10, (BitAction)BitValue);
Delay_us(10);
}


void MyI2C_W_SDA(uint8_t BitValue)
{
GPIO_WriteBit(GPIOB,GPIO_Pin_11, (BitAction)BitValue);
Delay_us(10);
}


uint8_t MyI2C_R_SDA(void)
{
uint8_t BitValue;
BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
Delay_us(10);
return BitValue;
}

/****************************************

通过GPIO口模拟I2C通讯,其中Out_PP --- 开漏输出也可以接收数据

开漏输出是低电平 + 高阻态

****************************************/
void MyI2C_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //这里是开漏输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);

//初始化结束后,给端口配置高电压
GPIO_SetBits(GPIOB,GPIO_Pin_10 | GPIO_Pin_11);
}


/************************

六个基本单元之一: 起始条件
SDA先拉低 ,SCL后拉低

*************************/
void MyI2C_Start(void)
{
MyI2C_W_SDA(1);
MyI2C_W_SCL(1);
MyI2C_W_SDA(0);
MyI2C_W_SCL(0);

}


/************************

六个基本单元之一: 终止条件
SCL拉高,SDA后拉高

除了终止时 SCL以高电平结束,所有其他的都是以SCL低电平结束

*************************/
void MyI2C_Stop(void)
{
MyI2C_W_SDA(0);
MyI2C_W_SCL(1);
MyI2C_W_SDA(1);
}


/************************

六个基本单元之一: 发送数据

*************************/
void MyI2C_SendByte(uint8_t Byte)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
MyI2C_W_SDA(Byte & (0x80 >> i)); //依次从高位到低位接收
MyI2C_W_SCL(1); //发送数据后 先拉高
MyI2C_W_SCL(0); //最终拉低
}

}


/************************

六个基本单元之一: 接收数据

接收读写都是 读写分离 低电平时谁发送,谁就将Bit写上,谁接收谁就释放SCL

低电平为写的时间,高电平为读的时间

*************************/
uint8_t MyI2C_ReceiveByte(void)
{
uint8_t i,Byte = 0x00;
MyI2C_W_SDA(1);
for (i = 0; i < 8; i++)
{
MyI2C_W_SCL(1);
if (MyI2C_R_SDA() == 1)
{
Byte |= (0x80 >> i);
}
MyI2C_W_SCL(0);
}
return Byte;
}


/************************

六个基本单元之一: 发送应答

*************************/
void MyI2C_SendACK(uint8_t AckBit)
{
MyI2C_W_SDA(AckBit); //依次从高位到低位接收
MyI2C_W_SCL(1); //发送数据后 先拉高
MyI2C_W_SCL(0); //最终拉低
}


/************************

六个基本单元之一: 发送应答

*************************/
uint8_t MyI2C_ReceiveACK(void)
{
uint8_t AckBit; //定义应答位变量
MyI2C_W_SDA(1); //接收前,主机先确保释放SDA,避免干扰从机的数据发送
MyI2C_W_SCL(1); //释放SCL,主机机在SCL高电平期间读取SDA
AckBit = MyI2C_R_SDA(); //将应答位存储到变量里
MyI2C_W_SCL(0); //拉低SCL,开始下一个时序模块
return AckBit; //返回定义应答位变量
}

2.MPU6050_Reg.h\Hardware

作用:把寄存器地址写在同一个头文件中,方便调用并且增强代码可读性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

3. MPU6050.c\Hardware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include "stm32f10x.h"                  // Device heade
#include "MyI2C.h"

//这里的定义是为了方便更改接收地址
#define MPU6050_ADDRESS 0xD0
/***************************************

指定地址写:
1、先写给从机地址
2、写给指定寄存器地址
3、传输数据Data

在这里,MyI2C_ReceiveACK(); 是从机接收应答,为0时表示,从机接收到,反之,没有接收到。

****************************************/

void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
MyI2C_Start(); //开启时序
MyI2C_SendByte(MPU6050_ADDRESS); //指定MPU6050地址写
MyI2C_ReceiveACK();
MyI2C_SendByte(RegAddress); //找到指定地址
MyI2C_ReceiveACK();
MyI2C_SendByte(Data); //写入数据
MyI2C_ReceiveACK();
MyI2C_Stop();
}

/***************************************

指定地址读:
1、先写给从机地址
2、写给指定寄存器地址
在这里,MyI2C_ReceiveACK(); 是从机接收应答,为0时表示,从机接收到,反之,没有接收到。

MyI2C_SendACK(1); 表示主机不给从机应答

****************************************/
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
uint8_t Data;

MyI2C_Start(); //开启时序
MyI2C_SendByte(MPU6050_ADDRESS); //指定MPU6050地址写
MyI2C_ReceiveACK();
MyI2C_SendByte(RegAddress); //找到指定地址
MyI2C_ReceiveACK();

MyI2C_Start();//转入读的时序,要重新起始
MyI2C_SendByte(MPU6050_ADDRESS | 0x01);//先传输MPU6050的地址 ,读地址要或上 0x01
MyI2C_ReceiveACK();
Data = MyI2C_ReceiveByte();
MyI2C_SendACK(1);
MyI2C_Stop();

return Data;
}



/***************************

初始化MPU6050

****************************/

void MPU6050_Init(void)
{
MyI2C_Init(); //先初始化底层的I2C
/*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
}

//使用指针的地址传递参数
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; //数据拼接,通过输出参数返回

}

硬件与MPU6050进行通讯

Tips: STM32自带有2个I2C硬件资源,分别是I2C1,I2C2,并且它们的外设时钟挂在在APB1时钟总线上;在这里,那些软件模拟的I2C的应答呀,SCL,SDA写读都被标准库封装成函数,我们直接调用即可。无需再写一个底层I2C。

MPU6050\Hardware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "stm32f10x.h"                  // Device header
#include "MPU6050_Reg.h"

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


//等待事件监控函数
void MPU6050_WaitEven(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
uint32_t Time = 10000;
while(I2C_CheckEvent(I2Cx,I2C_EVENT) != SUCCESS)
{
Time--;
if (Time == 0)
{
return;
}
}
}



/**
* 函 数:MPU6050写寄存器
* 参 数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
* 参 数:Data 要写入寄存器的数据,范围:0x00~0xFF
* 返 回 值:无
*/
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
I2C_GenerateSTART(I2C2,ENABLE); //替换软件写的I2C_Start()
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //监控事件5是否成功结束

I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter); //硬件I2C发送从机地址,方向为发送
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //事件6

I2C_SendData(I2C2,RegAddress);
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING); //事件8

I2C_SendData(I2C2,Data);
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //事件8v2就是事件主机传输结束

I2C_GenerateSTOP(I2C2,ENABLE); //结束传输
}

/**
* 函 数:MPU6050读寄存器
* 参 数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
* 返 回 值:读取寄存器的数据,范围:0x00~0xFF
*/
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
uint8_t Data;
I2C_GenerateSTART(I2C2,ENABLE); //替换软件写的I2C_Start()
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //监控事件5是否成功结束

I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter); //硬件I2C发送从机地址,方向为发送
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //事件6

I2C_SendData(I2C2,RegAddress);
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED); //事件8v2 设置为当传输结束后

//重新指定I2C2模式
I2C_GenerateSTART(I2C2,ENABLE); //替换软件写的I2C_Start()
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_MODE_SELECT); //监控事件5是否成功结束

I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Receiver); //硬件I2C发送从机地址,方向为发送
MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //事件6

//这里我们需要在检测事件前,进行ACK为失能,并且stop生效,否则就会多读一个字符
I2C_AcknowledgeConfig(I2C2,DISABLE);
I2C_GenerateSTOP(I2C2,ENABLE);

MPU6050_WaitEven(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED); //等待EV7
Data = I2C_ReceiveData(I2C2); //获取数据

//最后要把ACK使能,因为我们在配置的时候默认ACK使能
I2C_AcknowledgeConfig(I2C2,ENABLE);

return Data;
}

uint8_t MPU6050_GetID(void)
{
return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}


/**
* 函 数:MPU6050初始化
* 参 数:无
* 返 回 值:无
*/
void MPU6050_Init(void)
{
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

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);

I2C_InitTypeDef I2C_InitStructure;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //默认接收一个数据给应答,如果想修改,可以使用I2C的函数进行修改
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 50000;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; //时间占空比 两个比很接近,随便给哪给都行
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_OwnAddress1 = 0x00; //用于指定stm32自身地址,被其他主机呼叫,现在用不到,即随便给一个

I2C_Init(I2C2,&I2C_InitStructure);
I2C_Cmd(I2C2,ENABLE); //使能I2C2

//先初始化底层的I2C
/*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
}

//使用指针的地址传递参数
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; //数据拼接,通过输出参数返回
}

读取MPU6050实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"

uint8_t ID;
int16_t AX,AY,AZ,GX,GY,GZ;


int main(void)
{
OLED_Init();
MPU6050_Init();
OLED_ShowString(1,1,"ID:");
ID = MPU6050_GetID();
OLED_ShowHexNum(1,4,ID,2);


while(1)
{
MPU6050_GetData(&AX,&AY,&AZ,&GX,&GY,&GZ);
OLED_ShowSignedNum(2,1,AX,5);
OLED_ShowSignedNum(3,1,AY,5);
OLED_ShowSignedNum(4,1,AZ,5);
OLED_ShowSignedNum(2,9,GX,5);
OLED_ShowSignedNum(3,9,GY,5);
OLED_ShowSignedNum(4,9,GZ,5);

}
}

Tips: 这里的AX,AY,AZ分别代表着x轴上的加速度,y轴上的加速度,z轴上的加速度。而GX,GY,GZ代表的x轴的角速度,y轴的角速度,z轴的角速度。