Ladies and gentlemen,下面讲一下“镜子里的屏幕”相关MPU-6050的问题。在这个DIY上要用到 MPU-6050 陀螺仪,以前没有接触过它。查了很多资料,在网上很容易就可以找到了需要的代码,但都是STM32F1的相关代码,需要做的就是把代码移植到自己要用的开发板上。
PS:本篇以及下一篇帖子一样拥有视频讲解,且更为详细,欢迎大家观看。视频地址链接:https://v.youku.com/v_show/id_XMzgyMjA5MzA4NA==.html
这个小东西还真是有些复杂,原谅楼主偷了个懒,看到dmp有些懵逼,就直接获得的原始数据,通过对原始数据的分析实现了一部分功能。
一.硬件结构
MPU6050 模块的硬件原理图如图所示。

它的硬件非常简单,SDA与 SCL被引出方便与外部 I2C 主机连接,看图中的右上角,可知该模块的 I2C 通讯引脚 SDA 及 SCL 已经连接了上拉电阻,因此它与外部 I2C 通讯主机通讯时直接使用导线连接起来即可;模块自身的 I2C 设备地址可通过 AD0引脚的电平控制,当 AD0 接地时,设备地址为 0x68(七位地址),当 AD0 接电源时,设备地址为 0x69(七位地址)。另外,当传感器有新数据的时候会通过 INT 引脚通知 STM32。
二.原理介绍
说一下对他的理解。其实也不是特别的复杂,MPU-6050就是一个I2C器件,就像一个微控制器,通过它得到原始的数据信息,经过分析就知道当前的姿态,可以把他想象成一个黑箱,不需要懂他,只需要会使用它就行。首先得了解他的寄存器,知道如何初始化,读取,写入等等。都是套路其实,看着照葫芦画瓢就行。
三.硬件设计
VCC —— 3.3V
GND —— GND
SCL —— PB10
SDA —— PB11
AD0 —— 悬空或接地
四.软件设计
MPU-6050采用I2C通信,在STM32中,有硬件和软件I2C两种方式,大部分情况下,不使用硬件I2C,而是通过软件I2C模拟。因为STM32的硬件I2C非常复杂,更重要的是不稳定,故不推荐使用。所以这里通过软件模拟来实现,有兴趣的同学可以研究一下STM32的硬件I2C。
//开始信号
void i2c_Start(void)
{
I2C_SDA_1();
I2C_SCL_1();
__nop();
I2C_SDA_0();
__nop();
I2C_SCL_0();
__nop();
}
//停止信号
void i2c_Stop(void)
{
I2C_SDA_0();
I2C_SCL_1();
__nop();
I2C_SDA_1();
}
//发送一个字节
void i2c_SendByte(uint8_t _ucByte)
{
uint8_t i;
/* 先发送字节的高位bit7 */
for (i = 0; i < 8; i++)
{
if (_ucByte & 0x80)
{
I2C_SDA_1();
}
else
{
I2C_SDA_0();
}
__nop();
I2C_SCL_1();
__nop();
I2C_SCL_0();
if (i == 7)
{
I2C_SDA_1();
}
_ucByte <<= 1; // 左移一个bit
__nop();
}
}
//读取一个字节
uint8_t i2c_ReadByte(u8 ack)
{
uint8_t i;
uint8_t value;
/* 读到第1个bit为数据的bit7 */
value = 0;
for (i = 0; i < 8; i++)
{
value <<= 1;
I2C_SCL_1();
__nop();
if (I2C_SDA_READ())
{
value++;
}
I2C_SCL_0();
__nop();
}
if(ack==0)
i2c_NAck();
else
i2c_Ack();
return value;
}
//是否产生应答信号ACK
uint8_t i2c_WaitAck(void)
{
uint8_t re;
I2C_SDA_1();
__nop();
I2C_SCL_1();
__nop();
if (I2C_SDA_READ()) // CPU读取SDA口线状态
{
re = 1;
}
else
{
re = 0;
}
I2C_SCL_0();
__nop();
return re;
}
//产生一个应答信号ACK
void i2c_Ack(void)
{
I2C_SDA_0();
__nop();__nop();
I2C_SCL_1();
__nop();__nop();
I2C_SCL_0();
__nop();__nop();
I2C_SDA_1();
}
//产生1个NACK信号
void i2c_NAck(void)
{
I2C_SDA_1();
__nop();__nop();
I2C_SCL_1();
__nop();__nop();
I2C_SCL_0();
__nop();__nop();
}******************************分割线***********************************
下面开始写MPU-6050的代码。
// 写数据到MPU6050寄存器
void MPU6050_WriteReg(u8 reg_add,u8 reg_dat)
{
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_SendByte(reg_dat);
i2c_WaitAck();
i2c_Stop();
}
//从MPU6050寄存器读取数据
void MPU6050_ReadData(u8 reg_add,unsigned char*Read,u8 num)
{
unsigned char i;
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS);
i2c_WaitAck();
i2c_SendByte(reg_add);
i2c_WaitAck();
i2c_Start();
i2c_SendByte(MPU6050_SLAVE_ADDRESS+1);
i2c_WaitAck();
for(i=0;i<(num-1);i++){
*Read=i2c_ReadByte(1);
Read++;
}
*Read=i2c_ReadByte(0);
i2c_Stop();
}
//初始化MPU6050芯片
void MPU6050_Init(void)
{
int i=0,j=0;
//在初始化之前要延时一段时间,若没有延时,则断电后再上电数据可能会出错
for(i=0;i<1000;i++)
{
for(j=0;j<1000;j++)
{
;
}
}
MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_1, 0x00); //解除休眠状态
MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV , 0x07); //陀螺仪采样率,1KHz
MPU6050_WriteReg(MPU6050_RA_CONFIG , 0x06); //低通滤波器的设置,截止频率是1K,带宽是5K
MPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG , 0x00); //配置加速度传感器工作在2G模式,不自检
MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG, 0x18); //陀螺仪自检及测量范围,典型值:0x18(不自检,2000deg/s)
}
//读取MPU6050的角加速度数据
void MPU6050ReadGyro(short *gyroData)
{
u8 buf[6];
MPU6050_ReadData(MPU6050_GYRO_OUT,buf,6);
gyroData[0] = (buf[0] << 8) | buf[1];
gyroData[1] = (buf[2] << 8) | buf[3];
gyroData[2] = (buf[4] << 8) | buf[5];
}
//读取原始温度
void MPU6050ReadTemp(short *tempData)
{
u8 buf[2];
MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);
*tempData = (buf[0] << 8) | buf[1];
}
// 读取MPU6050的温度数据,转化成摄氏度
void MPU6050_ReturnTemp(float *Temperature)
{
short temp3;
u8 buf[2];
MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);
temp3= (buf[0] << 8) | buf[1];
*Temperature=((double) temp3/340.0)+36.53;
}这里需要注意,所得到的加速度数据是未经过处理的原始数据,在使用过程中需要分析其中规律。还有就是陀螺仪检测的温度会受自身芯片发热的影响,严格来说它测量的是自身芯片的温度,所以用它来测量气温是不太准确的。
再说一个问题,MPU-6050的姿态算法是有专门的算法的,官方已经给出,那就是DMP算法,DMP更加接近于实际应用,大家可以了解了解。
到这里关于MPU-6050的设计就可以了,在下一篇将介绍RTC时钟和OLED的设计原理和过程。共同学习,共同进步!!!!
我要赚赏金
