MPU6050篇——(MPU6050的介绍及IIC时序)

一、MPU6050的简介

        MPU6050是全球首例 9 轴运动处理传感器。它集成了 3 轴 MEMS 陀螺仪,3 轴 MEMS 加速度计,以及一个可扩展的数字运动处理器 DMP(Digital Motion Processor),可用 I2C 接口连接一个第三方的数字传感器,比如磁力计。扩展之后就可以通过其 I2C 或 SPI 接口 输出一个 9 轴的信号(SPI 接口仅在 MPU-6000 可用)。MPU-60X0 也可以通过其 I2C 接口 连接非惯性的数字传感器,比如压力传感器。

        MPU-60X0 对陀螺仪和加速度计分别用了三个 16 位的 ADC,将其测量的模拟量转化 为可输出的数字量。为了精确跟踪快速和慢速的运动,传感器的测量范围都是用户可控的, 陀螺仪可测范围为±250,±500,±1000,±2000°/秒(dps),加速度计可测范围为±2,±4, ±8,±16g。

         一个片上 1024 字节的 FIFO,有助于降低系统功耗。

         和所有设备寄存器之间的通信采用 400kHz 的 I2C 接口或 1MHz 的 SPI 接口(SPI 仅 MPU-6000 可用)。对于需要高速传输的应用,对寄存器的读取和中断可用 20MHz 的 SPI。 另外,片上还内嵌了一个温度传感器和在工作环境下仅有±1%变动的振荡器。

        芯片尺寸 4×4×0.9mm,采用 QFN 封装(无引线方形封装),可承受最大 10000g 的冲 击,并有可编程的低通滤波器。

         关于电源,MPU-60X0 可支持 VDD 范围 2.5V±5%,3.0V±5%,或 3.3V±5%。另外 MPU-6050 还有一个 VLOGIC 引脚,用来为 I2C 输出提供逻辑电平。VLOGIC 电压可取 1.8±5%或者 VDD。

二、MPU6050框图

三、模块的初始化工作

        1.初始化IIC接口

        MPU6050的通信方式就是IIC,所以初始时应先初始化IIC。

        2.复位MPU6050

        主要目的是使MPU6050内部所有寄存器恢复默认值,然后通过对电源管理寄存器1(0X6B)的第七位写1实现,及向MPU6050写入0x80使其复位。复位完成,电源管理寄存器1恢复默认值位0x40。通过寄存器手册可以知道此时为低功耗模式(SLEEP被置1),如果我们想正常使用陀螺仪,所以我们还得设置该寄存器为0x00来唤醒MPU6050,使其进入到正常工作状态。代码如下:

MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);	//复位MPU6050
delay_ms(100);
MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);	//唤醒MPU6050 

 其中延时100ms是为了确保复位完成。

        3.设置角速度(0X1B)和加速度传感器(0X1C)满量程范围以及采样率(0X19)

	MPU_Write_Byte(MPU_GYRO_CFG_REG,0X18);//设置陀螺仪满量程范围  
	MPU_Write_Byte(MPU_ACCEL_CFG_REG,0x00);//设置加速度传感器满量程范围 
	MPU_Set_Rate(50);						//设置采样率50Hz

0X1B寄存器如下:设置量程范围为第3、4位,0,±250°/S1,±500°/S2,±1000°/S3,±2000°/S;我们设置为3,即±2000°/S,也就是0x18。

0X1C寄存器如下:设置量程范围为AFS_SEL[1:0]这两个位0,±2g1,±4g2,±8g3,±16g;我们一般设置为0,即±2g,也就是0x00。

 0X19存器如下:采样频率计算公式为:采样频率 = 陀螺仪输出频率 / (1+SMPLRT_DIV)。

则SMPLRT_DIV = 陀螺仪输出频率/采样频率 - 1;阅读寄存器说明手册可知,MPU6050的陀螺输出频率可达8kHz,加速度计为1kHz,而且可以通过分频来降低频率。采样频率就是通过陀螺仪输出频率分频得到的。陀螺仪采样率通过采样率分频寄存器(0x19)控制。如果要得到50Hz的采样率,当我们要设定50Hz时,SMPLRT_DIV  = 1000/50 -1  = 19,那么分频值就是19。只要设置寄存器的值为19,就可以使得DMP以50Hz来更新寄存器中的数据,只要按时读取寄存器就可以了。

        数字低通滤波器(DLPF)则通过配置寄存器(0x1A)设置,一般设置 DLPF 为带宽的 1/2 即可。

//设置MPU6050的采样率(假定Fs=1KHz)
//rate:4~1000(Hz)
//返回值:0,设置成功
//    其他,设置失败 
u8 MPU_Set_Rate(u16 rate)
{
	u8 data;
	if(rate>1000)rate=1000;
	if(rate<4)rate=4;
	data=1000/rate-1;
	data=MPU_Write_Byte(MPU_SAMPLE_RATE_REG,data);	//设置数字低通滤波器
 	return MPU_Set_LPF(rate/2);	//自动设置LPF为采样率的一半
}

最终代码也就如上。

4.4.设置其他参数

我们还需要配置的参数有:

  • 关闭中断
  • 关闭 AUX IIC 接口
  • 禁止 FIFO
  • 设置陀螺仪采样率
  • 设置数字低通滤波器(DLPF)等。

中断的关闭:我们不用中断方式读取数据,所以可以关闭中断。寄存器地址(0X38)

在寄存器手册上可以看见,要想使能中断,则相应为置1,否则为0,故我们写0x00。

MPU_Write_Byte(MPU_INT_EN_REG,0X00);	//关闭所有中断

AUX IIC接口的关闭:

        我们也没用到 AUX IIC 接口外接其他传感器,所以也关闭这个接口。如下所示,分别通过用户控制寄存器(0x6A)控制。和中断一样,为1则使能,故置0;

MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);	//I2C主模式关闭

禁止FIFO: 

         MPU6050 可以使用 FIFO 存储传感器数据,由于我们没有使用,所以关闭所有 FIFO 通道。如下所示,通过 FIFO 使能寄存器(0x23)控制,默认都是 0(即禁止 FIFO),所以用默认值就可以了。

MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);	//关闭FIFO

 而数字低通滤波器:数字低通滤波器(DLPF)则通过配置寄存器(0x1A)设置,一般设置 DLPF 为带宽的 1/2 即可。上面也设置了。最后总体代码如下:

u8 MPU_Init(void)
{ 
	u8 res; 
	MPU_IIC_Init();//初始化IIC总线
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X80);	//复位MPU6050
    delay_ms(100);
	MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X00);	//唤醒MPU6050 
	MPU_Set_Gyro_Fsr(3);					//陀螺仪传感器,±2000dps
	MPU_Set_Accel_Fsr(0);					//加速度传感器,±2g
	MPU_Set_Rate(50);						//设置采样率50Hz
	MPU_Write_Byte(MPU_INT_EN_REG,0X00);	//关闭所有中断
	MPU_Write_Byte(MPU_USER_CTRL_REG,0X00);	//I2C主模式关闭
	MPU_Write_Byte(MPU_FIFO_EN_REG,0X00);	//关闭FIFO
	MPU_Write_Byte(MPU_INTBP_CFG_REG,0X80);	//INT引脚低电平有效
	res=MPU_Read_Byte(MPU_DEVICE_ID_REG); 
	if(res==MPU_ADDR)//器件ID正确
	{
		MPU_Write_Byte(MPU_PWR_MGMT1_REG,0X01);	//设置CLKSEL,PLL X轴为参考
		MPU_Write_Byte(MPU_PWR_MGMT2_REG,0X00);	//加速度与陀螺仪都工作
		MPU_Set_Rate(50);						//设置采样率为50Hz
 	}else return 1;
	return 0;
}

下一章继续讲解MPU6050。这里附上IIC代码:

mpuiic.c

#include "mpuiic.h"
#include "delay.h"

//MPU IIC 延时函数
void MPU_IIC_Delay(void)
{
	delay_us(2);
}


//初始化IIC
void MPU_IIC_Init(void)
{					     
  GPIO_InitTypeDef  GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//先使能外设IO PORTC时钟 
		
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;	 // 端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
  GPIO_Init(GPIOB, &GPIO_InitStructure);				 //根据设定参数初始化GPIO 
	
  GPIO_SetBits(GPIOB,GPIO_Pin_8|GPIO_Pin_9);			//PB8,PB9输出高	
}


//产生IIC起始信号
void MPU_IIC_Start(void)
{
	MPU_SDA_OUT();     //sda线输出
	MPU_IIC_SDA=1;	  	  
	MPU_IIC_SCL=1;
	MPU_IIC_Delay();
 	MPU_IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	MPU_IIC_Delay();
	MPU_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}	  


//产生IIC停止信号
void MPU_IIC_Stop(void)
{
	MPU_SDA_OUT();//sda线输出
	MPU_IIC_SCL=0;
	MPU_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	MPU_IIC_Delay();
	MPU_IIC_SCL=1;  
	MPU_IIC_SDA=1;//发送I2C总线结束信号
	MPU_IIC_Delay();							   	
}


//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 MPU_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	MPU_SDA_IN();      //SDA设置为输入  
	MPU_IIC_SDA=1;MPU_IIC_Delay();	   
	MPU_IIC_SCL=1;MPU_IIC_Delay();	 
	while(MPU_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			MPU_IIC_Stop();
			return 1;
		}
	}
	MPU_IIC_SCL=0;//时钟输出0 	   
	return 0;  
} 


//产生ACK应答
void MPU_IIC_Ack(void)
{
	MPU_IIC_SCL=0;
	MPU_SDA_OUT();
	MPU_IIC_SDA=0;
	MPU_IIC_Delay();
	MPU_IIC_SCL=1;
	MPU_IIC_Delay();
	MPU_IIC_SCL=0;
}


//不产生ACK应答		    
void MPU_IIC_NAck(void)
{
	MPU_IIC_SCL=0;
	MPU_SDA_OUT();
	MPU_IIC_SDA=1;
	MPU_IIC_Delay();
	MPU_IIC_SCL=1;
	MPU_IIC_Delay();
	MPU_IIC_SCL=0;
}	


//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void MPU_IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	MPU_SDA_OUT(); 	    
    MPU_IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        MPU_IIC_SDA=(BitAction)((txd&0x80)>>7);
        txd<<=1; 	  
		MPU_IIC_SCL=1;
		MPU_IIC_Delay(); 
		MPU_IIC_SCL=0;	
		MPU_IIC_Delay();
    }	 
} 


//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 MPU_IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	MPU_SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        MPU_IIC_SCL=0; 
        MPU_IIC_Delay();
		MPU_IIC_SCL=1;
        receive<<=1;
        if(MPU_READ_SDA)receive++;   
		MPU_IIC_Delay(); 
    }					 
    if (!ack)
        MPU_IIC_NAck();//发送nACK
    else
        MPU_IIC_Ack(); //发送ACK   
    return receive;
}

mpuiic.h

#ifndef __MPUIIC_H
#define __MPUIIC_H
#include "sys.h"


	   		   
//IO方向设置
#define MPU_SDA_IN()  {GPIOB->CRH &= 0XFFFFFF0F;GPIOB->CRH |= (u32)8<<4;}
#define MPU_SDA_OUT() {GPIOB->CRH &= 0XFFFFFF0F;GPIOB->CRH |= (u32)3<<4;}


//IO操作函数	 
#define MPU_IIC_SCL    PBout(8) 		//SCL
#define MPU_IIC_SDA    PBout(9) 		//SDA	 
#define MPU_READ_SDA   PBin(9) 		//输入SDA 

//IIC所有操作函数
void MPU_IIC_Delay(void);				//MPU IIC延时函数
void MPU_IIC_Init(void);                //初始化IIC的IO口				 
void MPU_IIC_Start(void);				//发送IIC开始信号
void MPU_IIC_Stop(void);	  			//发送IIC停止信号
void MPU_IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 MPU_IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 MPU_IIC_Wait_Ack(void); 				//IIC等待ACK信号
void MPU_IIC_Ack(void);					//IIC发送ACK信号
void MPU_IIC_NAck(void);				//IIC不发送ACK信号
  
#endif
  • 26
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,要读取MPU6050的欧拉角,需要先通过I2C接口向其发送初始化指令,然后读取其原始数据并进行数据格式转换。以下是使用STM32单片机模拟I2C时序读取MPU6050欧拉角的步骤: 1. 初始化I2C接口,设置I2C时钟频率和从设备地址。 2. 按照MPU6050的寄存器地址顺序依次向其发送读取指令,并读取返回的数据。 3. 对原始数据进行格式转换,将其转换为欧拉角的单位。 4. 使用欧拉角的公式将原始数据转换为欧拉角值。 以下是示例代码: ```c #include "stm32f4xx.h" #include "i2c.h" #include "mpu6050.h" // 初始化I2C接口 void MPU6050_Init(void) { I2C_Init(); } // 读取MPU6050的欧拉角 void MPU6050_ReadEuler(float *pitch, float *roll, float *yaw) { uint8_t buf[14]; int16_t ax, ay, az, gx, gy, gz; float fpitch, froll, fyaw; // 依次读取MPU6050的14个寄存器数据 I2C_ReadData(MPU6050_ADDRESS, MPU6050_RA_ACCEL_XOUT_H, buf, 14); // 将原始数据转换为加速度和角速度值 ax = (int16_t)((buf[0] << 8) | buf[1]); ay = (int16_t)((buf[2] << 8) | buf[3]); az = (int16_t)((buf[4] << 8) | buf[5]); gx = (int16_t)((buf[8] << 8) | buf[9]); gy = (int16_t)((buf[10] << 8) | buf[11]); gz = (int16_t)((buf[12] << 8) | buf[13]); // 将加速度和角速度值转换为欧拉角值 fpitch = atan2(ax, sqrt(ay * ay + az * az)) * 180 / PI; froll = atan2(ay, sqrt(ax * ax + az * az)) * 180 / PI; fyaw = atan2(gy, sqrt(gx * gx + gz * gz)) * 180 / PI; // 将欧拉角值返回 *pitch = fpitch; *roll = froll; *yaw = fyaw; } ``` 注意,以上示例代码仅供参考,具体实现细节还需要根据实际情况进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值