基于单片机的MPU6050六轴传感器设计

描述

一. 简介

MPU6050 是 InvenSense 公司推出的整合性 6 轴运动处理组件,其内部整合了 3 轴陀螺仪和 3 轴加速度传感器,并且含有一个IIC 接口, 可用于连接外部磁力传感器,并利用自带的数字运动处理器(DMP: Digital Motion Processor) 硬件加速引擎,通过主 IIC 接口,向应用端输出完整的 9 轴融合演算数据。

InvenSense 公司提供了一套基于DMP的运动处理驱动库,可大大降低单片机对动处理运算的负荷,同时也大大降低了编程难度。

MPU6050配合官方提供的运动处理驱动库,可以容易地获取出飞控系统融合演算数据; 同时也可以计步传感器,通过调用驱动库相应的函数,获取运动步数、运动时间等数据。

二. MPU6050原理及参数

1.芯片内部框图

MPU内部自带有7路16bit的ADC转换电路,其中3路为陀螺仪、3路为加速度计、1路为内部温度传感器。 ADC转换后的数据通过DMP处理后,存储在FIFO里。 单片机通过对芯片内部寄存器进行读写操作,完成对MPU的控制。

MPU6050

2.芯片引脚说明

MPU6050的接线比较简单,使用3.3V的工作电源,通过IIC接口(MPU6000还可用SPI接口)与MCU通信。

MPU6050

3.模块电路图

模块原理图如下,其中使用了SPX3810M稳压芯片,将5V电源转换为3.3V电压给MPU6050芯片供电,P-MOS管Q1、Q2作为电平转换电路,将芯片的IIC电平转化为5.0V电平,可兼容51单片机和STM32单片机的控制电平(注:STM32引脚需要配置为开漏状态,且需要所用引脚能兼容5.0V电压,引脚标志为FT)。 采用3.3V的单片机控制,如果不想要或者无法兼容5V电压,可将电平转换电路去掉,将IIC接口直接接单片机IIC引脚。

MPU6050

4.单片机与模块接线图

单片机IIC接口采用模拟IIC通信。

MPU6050

三. MPU6050编程及控制

因为MPU6050内部带有DMP处理单元,加上官方提供了比较完整的运动处理驱动库,大大降低了我们的编程和对数据的处理难度。 我们可以将各个运动的参数计算,如旋转矩阵、四元数(quaternion)、欧拉角格式(Euler Angle forma)的融合演算数据,通过调用运动处理驱动库函数,直接读取出数据来。 以下程序是基于正点原子ATK-MPU6050模块的开发例程为例。 在完成标准的IIC驱动程序后,先实现读寄存器和写寄存器操作;

(1)读寄存器操作

//IIC读一个字节 
//reg:寄存器地址 
//返回值:读到的数据
u8 MPU_Read_Byte(u8 reg)
{
  u8 res;
    MPU_IIC_Start(); 
  MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令  
  MPU_IIC_Wait_Ack();    //等待应答 
    MPU_IIC_Send_Byte(reg);  //写寄存器地址
    MPU_IIC_Wait_Ack();    //等待应答
    MPU_IIC_Start();
  MPU_IIC_Send_Byte((MPU_ADDR<<1)|1);//发送器件地址+读命令  
    MPU_IIC_Wait_Ack();    //等待应答 
  res=MPU_IIC_Read_Byte(0);//读取数据,发送nACK 
    MPU_IIC_Stop();      //产生一个停止条件 
  return res;    
}

(2)写寄存器操作

//IIC写一个字节 
//reg:寄存器地址
//data:数据
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Byte(u8 reg,u8 data)          
{ 
    MPU_IIC_Start(); 
  MPU_IIC_Send_Byte((MPU_ADDR<<1)|0);//发送器件地址+写命令  
  if(MPU_IIC_Wait_Ack())  //等待应答
  {
    MPU_IIC_Stop();     
    return 1;    
  }
    MPU_IIC_Send_Byte(reg);  //写寄存器地址
    MPU_IIC_Wait_Ack();    //等待应答 
  MPU_IIC_Send_Byte(data);//发送数据
  if(MPU_IIC_Wait_Ack())  //等待ACK
  {
    MPU_IIC_Stop();   
    return 1;     
  }     
    MPU_IIC_Stop();   
  return 0;
}

实现这个两个函数后,就可实现对MPU6050的各种操作了; 但是无法调用官方自带的运动处理驱动库。 首先我们在Keil工程里面增入文件“inv_mpu_dmp_motion_driver.h”、“inv_mpu_dmp_motion_driver.c”、“inv_mpu.h”、“inv_mpu.c”、“dmpKey.h”、“dmpmap.h"。

然后将在两个实现驱动库里两个基本操作函数,最后映射到驱动库的inv_mpu.h文件里面后,便可直接调用运动处理库的API了。

(3)首先实现IIC连续读取数据函数

/IIC连续读
//addr:器件地址
//reg:要读取的寄存器地址
//len:要读取的长度
//buf:读取到的数据存储区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Read_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{ 
   MPU_IIC_Start(); 
  MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令  
  if(MPU_IIC_Wait_Ack())  //等待应答
  {
    MPU_IIC_Stop();     
    return 1;    
  }
    MPU_IIC_Send_Byte(reg);  //写寄存器地址
    MPU_IIC_Wait_Ack();    //等待应答
    MPU_IIC_Start();
  MPU_IIC_Send_Byte((addr<<1)|1);//发送器件地址+读命令  
    MPU_IIC_Wait_Ack();    //等待应答 
  while(len)
  {
    if(len==1)*buf=MPU_IIC_Read_Byte(0);//读数据,发送nACK 
    else *buf=MPU_IIC_Read_Byte(1);    //读数据,发送ACK  
    len--;
    buf++; 
  }    
    MPU_IIC_Stop();  //产生一个停止条件 
  return 0;  
}

(4)实现IIC连续写数据函数

//IIC连续写
//addr:器件地址 
//reg:寄存器地址
//len:写入长度
//buf:数据区
//返回值:0,正常
//    其他,错误代码
u8 MPU_Write_Len(u8 addr,u8 reg,u8 len,u8 *buf)
{
  u8 i; 
    MPU_IIC_Start(); 
  MPU_IIC_Send_Byte((addr<<1)|0);//发送器件地址+写命令  
  if(MPU_IIC_Wait_Ack())  //等待应答
  {
    MPU_IIC_Stop();     
    return 1;    
  }
    MPU_IIC_Send_Byte(reg);  //写寄存器地址
    MPU_IIC_Wait_Ack();    //等待应答
  for(i=0;i<len;i++)
  {
    MPU_IIC_Send_Byte(buf[i]);  //发送数据
    if(MPU_IIC_Wait_Ack())    //等待ACK
    {
      MPU_IIC_Stop();   
      return 1;     
    }    
  }    
    MPU_IIC_Stop();   
  return 0;  
}

完成这两个函数后,将这两个函数映射到ipv_mpu.h里面,如图。

MPU6050

设置完成后,便可使用官方的运动处理驱动库。 其他功能性函数就不一一列出;

(5)最后实现MPU6050的初始化。

//初始化MPU6050
//返回值:0,成功
//    其他,错误代码
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的控制及数据采集

在单片机进行初始化时,先需要调用MPU_Init函数初始化后,还要调用mpu_dmp_init函数对模块进行初始化。 代码如下:

int main(void)
 { 
  float pitch,roll,yaw;     //欧拉角
  short aacx,aacy,aacz;    //加速度传感器原始数据
  short gyrox,gyroy,gyroz;  //陀螺仪原始数据
  short temp;          //温度      
  MPU_Init();          //初始化MPU6050


  while(mpu_dmp_init()); 
   while(1)
  {


    if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)
    { 
      temp=MPU_Get_Temperature();  //得到温度值
      MPU_Get_Accelerometer(&aacx,&aacy,&aacz);  //得到加速度传感器数据
      MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz);  //得到陀螺仪数据
    }
  }   
}
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分