Skip to content

IIC 控制MPU6050 来实现姿态的读取

这个芯片已经是被用了很多年的芯片了,我收拾自己东西的时候发现有十几个模块,想必自己零零散散,想调试这颗芯片,但是却止步于开始。最近打算看看调试一下,算是弥补一下曾经的努力吧

读取信息就是常规的调用函数,读取位置就好。 下面贴几个相关的寄存器信息

ACCEL 传感器

alt textalt text

温度传感器

alt textalt text

GYRO 寄存器

alt textalt text

1. 硬件连接

如下图所示,和mpu6050模块连接,只需接2根IIC的线即可。

alt text

2. CubeMX生成代码

可以看到,配置了4个部分

  1. 外部时钟
  2. SWD 接口
  3. 串口输出
  4. IIC 通讯

alt text

3. 编写代码

3.1 串口打印相关函数

c
#include <stdio.h>
 //重定向c库函数printf到串口USARTx,重定向后可使用printf函数
 int fputc(int ch, FILE *f)
 {
     /* 发送一个字节数据到串口USARTx */
     HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
     return (ch);
 }
 
 void ShowHex(uint8_t *buf,uint8_t len)
{
    uint8_t i;
    printf("hex = ");
    for( i = 0; i < len; i++){
        printf(" %02X",buf[i]); //使用前导0补齐
        //printf(" %2X",buf[i]);  //使用前导空格补齐
        //printf(" %X",buf[i]);  //输出最短的16进制格式
    }
    printf( "\r\n");
}

3.2 MPU芯片初始化的代码

2024年3月21日 现在的这个版本比较简陋,需要后续完善一些信息。但基本功能能够实现,先上传来保存一份

c
void MPU6050_INIT()
{
    
    //延时
    HAL_Delay(100);
    uint8_t SendAddress = 0x6b;
    uint8_t SendData  = 0x00; //解除休眠状态
    HAL_I2C_Mem_Write(&hi2c1,0xD1,SendAddress,1,&SendData,1,0xff);
    
    SendAddress = 0x19;//采样率分频器
    SendData = 0x07;
    HAL_I2C_Mem_Write(&hi2c1,0xD1,SendAddress,1,&SendData,1,0xff);
    
    SendAddress = 0x1A;//低通滤波器
    SendData = 0x06;
    HAL_I2C_Mem_Write(&hi2c1,0xD1,SendAddress,1,&SendData,1,0xff);
    
    SendAddress = 0x1B;//陀螺仪
    SendData = 0x08;   //± 500 °/s
    HAL_I2C_Mem_Write(&hi2c1,0xD1,SendAddress,1,&SendData,1,0xff);
    
    SendAddress = 0x1C;//加速度计
    SendData = 0x00;   //± 2g
    HAL_I2C_Mem_Write(&hi2c1,0xD1,SendAddress,1,&SendData,1,0xff);
    
}

3.3 main函数

main函数主要实现了IIC的读取,以及处理,打印相关数据,整个代码实现了将采集的信息真实的打印出来,后面计算角度还需要再增加相关代码,后续再写一篇吧

c

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USART1_UART_Init();
    uint8_t MPU_Data[] = {0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00,0X00, 0X00};
    uint8_t preg1_Data  = 0x3B;
    double ACCEL_XOUT = 0.0,ACCEL_YOUT =0.0,ACCEL_ZOUT=0.0;
    double GYRO_XOUT = 0.0,GYRO_YOUT =0.0,GYRO_ZOUT=0.0;
    
    MPU6050_INIT();
  while (1)
  {
      
      HAL_I2C_Mem_Read(&hi2c1, 0xD1,preg1_Data,I2C_MEMADD_SIZE_8BIT,MPU_Data,14,50);
      //ShowHex(MPU_Data,14);
      float Temp = (MPU_Data[6]<<8)|MPU_Data[7];
      if(Temp>32768) Temp-=65536;
      Temp=(36.53+Temp/340);
      
      short int ACCEL_XOUT1 = ((MPU_Data[0]<<8)|MPU_Data[1]);ACCEL_XOUT = (double)ACCEL_XOUT1/16384;
      short int ACCEL_YOUT1 = ((MPU_Data[2]<<8)|MPU_Data[3]);ACCEL_YOUT = (double)ACCEL_YOUT1/16384;
      short int ACCEL_ZOUT1 = ((MPU_Data[4]<<8)|MPU_Data[5]);ACCEL_ZOUT = (double)ACCEL_ZOUT1/16384;
      
      short int GYRO_XOUT1 = ((MPU_Data[8]<<8)|MPU_Data[9]);GYRO_XOUT = (double)GYRO_XOUT1/65.5;
      short int GYRO_YOUT1 = ((MPU_Data[10]<<8)|MPU_Data[11]);GYRO_YOUT = (double)GYRO_YOUT1/65.5;
      short int GYRO_ZOUT1 = ((MPU_Data[12]<<8)|MPU_Data[13]);GYRO_ZOUT = (double)GYRO_ZOUT1/65.5;
      
      //printf("temp = %0.2f",Temp);
      printf("x= %0.2f,y= %0.2f,z= %0.2f",GYRO_XOUT,GYRO_YOUT,GYRO_ZOUT);//加速度计
      //printf("x= %0.2f,y= %0.2f,z= %0.2f",ACCEL_XOUT,ACCEL_YOUT,ACCEL_ZOUT);//陀螺仪
      printf("\r\n");
      HAL_Delay(200);
  }
}

4. 后记

6050 这个芯片已经是停产的芯片了,在新的设计中则不推荐使用,但是作为学习而言,其资料相对丰富,算是一个还可以的选择

这个芯片很早就买了,感觉像是一座高山一样挡在前面,什么卡尔曼滤波,什么四位元数,有空还是得好好整理这个资料,弥补一下自己曾经的努力吧