【STM32CubeMX】MPU6050移植DMP流程

  原本是想要自己的模拟I2C库,来组合时选块,对接上DMP所需接口,可是一直卡在初始化,后面改成STM32F4的硬件I2C,也是很便捷的对接上接口了。此外在也参考了网上的移植资料与记录。本文也作为学习笔记,记录下过程。

  使用到的:STM32F407VGT6+STM32CubeMX+MotionDriver6.1。末尾链接提供工程文件和DMP相关文件。

移植流程

简单概述流程

  1. 将DMP相关文件复制到项目文件下
  2. inv_mpu.h文件中定义两个宏定义
  3. 在两个文件,定义配置宏接口
  4. 根据需求,看是否需要替换器件默认的I2C地址
  5. 编译后,有两处报错,双击跳转报错行,通过注释或者更改替代即可。
  6. 导入DMP初始化库,#include "MPU6050_DMP.h"

详细概述流程

  1. 将下述6个文件复制到项目文件下。库文件末尾链接会提供,或者去官网。(简略描述官网下载流程:打开Home | TDK InvenSense,注册账号,选择左上方选项卡”Developers -> Software Downloads -> SmartMotion®“点击跳转后,可页面搜索”MPU“或者下滑就可看到MPU选项卡,就可以看到eMD 6.12下载链接)

    在这里插入图片描述

  2. inv_mpu.h文件中定义两个宏定义。宏STM32_MPU6050用于后续构建对接I2C的配置,宏MPU6050用于选择器件。

    #define STM32_MPU6050
    #define MPU6050
    
  3. inv_mpu_dmp_motion_driver.cinv_mpu.c基于宏配置。因为上述定义了STM32_MPU6050所以可以看到下述是基于该宏下编写。其实要要是不定义新配置宏,在默认的旧宏如MSP430...上做删改也行,不过麻烦些许。

    inv_mpu_dmp_motion_driver.c文件下

    // 引入新的配置
    #elif defined STM32_MPU6050
    #include "stm32f4xx_hal.h"
    #include "MyI2C.h"
    #define delayC_ms    HAL_Delay
    #define get_ms			 get_ms_null
    #define log_i(...)     do {} while (0)
    #define log_e(...)     do {} while (0)
    

    inv_mpu.c文件下

    // 引入新的配置
    #elif defined STM32_MPU6050
    #include "stm32f4xx_hal.h"
    #include "MyI2C.h"
    #define i2c_write   MyI2C_SeriesSendByte
    #define i2c_read    MyI2C_SeriesReceiveByte
    #define delay_ms    HAL_Delay
    #define get_ms      get_ms_null
    #define log_i(...)     do {} while (0)
    #define log_e(...)     do {} while (0)
    #define fabs        fabsf
    #define min(a,b) ((a<b)?a:b)
    

    在这里插入图片描述

    在这里插入图片描述

    必需要修改的宏函数有4个,i2c_writei2c_readdelay_msget_ms。其中除了delay_ms可以用HAL_Delay函数,直接代替外,另外三个函数都在MyI2C.h库,基于原型做转换了,然后因为get_ms暂时无光紧要,就暂时先实现空函数,下面是该库的部分代码:

    uint8_t MyI2C_SeriesSendByte(unsigned char slave_addr, unsigned char reg_addr,unsigned char length, unsigned char const *data)
    {
    	HAL_I2C_Mem_Write(&hi2c1, slave_addr, reg_addr, I2C_MEMADD_SIZE_8BIT, (uint8_t *)data, length,100);return 0;
    }
    uint8_t MyI2C_SeriesReceiveByte(unsigned char slave_addr, unsigned char reg_addr,unsigned char length, unsigned char *data)
    {
    	HAL_I2C_Mem_Read(&hi2c1,slave_addr,reg_addr,I2C_MEMADD_SIZE_8BIT, data,length, 100);return 0;
    }
    void get_ms_null(unsigned long *count)
    {
    }
    
  4. 根据需求,看是否需要替换器件默认的I2C地址

    根据I2C时序函数,看I2C器件地址是要7位,还是8位,因为我使用的是HAL提供的硬件I2C函数,且在函数输入时没有,左移1位,所以要替换器件的7位地址为8位(位移后的)。在inv_mpu.c文件下可以找到,将0x68修改为0xD0,有两个地方存在该定义,不清楚哪个被宏包含顶的,可以两个都修改:

    const struct hw_s hw = {
        .addr           = 0xD0,
    ......
    
  5. 编译后,有两处报错,双击跳转报错行,通过注释或者更改替代即可。

    // __no_operation();
    		__NOP;
    
    //    if (int_param)
    //        reg_int_cb(int_param);
    
  6. 导入DMP初始化库,#include "MPU6050_DMP.h"

    这个忘记是参考哪里的了,所以库代码就不放出来了,介绍存在的函数。

    int MPU6050_DMP_init(void);
    int MPU6050_DMP_Get_Date(float *pitch, float *roll, float *yaw);
    

主函数

下述是在main.c文件中,使用演示的关键代码块,非全部列出,已经省略无关的代码,请按作用添加到主函数中。

float x = 0;
float y = 0;
float z = 0;
int ret = 0;
// 初始化
do
{
    ret = MPU6050_DMP_init();
    printf("MPU6050 init, ret = %d\r\n", ret);
    HAL_Delay(100);
} while(ret);
// 获取数据
while (1)
{
    //MPU6050_DMP_Get_Date(&x,&y,&z);
    while(MPU6050_DMP_Get_Date(&x,&y,&z)!=0){}
    printf("%.2f,%.2f,%.2f\r\n",x,y,z);
}

以及工程演示图:

可以看到,初始化还是需要手动将模块放置水平,放平后自检才算完成后,整个初始化完成。

在这里插入图片描述


常见问题

下述问题来自自身遇见,和总结网上的解决办法。

  1. 编译报错Gyro driver is missing the system layer implementations.

    没有按流程定义好相关和定义配置宏,导致在编译时找不到任何1个符合的配置,就通过#else跳转#error输出错误消息。

  2. 调用MPU6050_DMP_init初始化的时候,一直返回-1

    这里我遇到的是对接的时序接口i2c_writei2c_read可能时序哪里不够严谨,导致的初始化返回失败。还有1种情况就是,器件地址问题,这得看接入的I2C的读写函数是否会左移1位也就是addr << 1,如果会,按照在DMP中默认预定义是7位地址0x68,是没问题的,如果不会则要修改成0xD0也就是预先位移了。

  3. 调用MPU6050_DMP_init初始化的时候,一直返回-9

    错误代码是表示自检失败,要将模块放置水平。不过,默认的水平比较苛刻,所以可以通过注释部分自检相关的代码了,放宽模块水平的条件。

    inv_mpu.c文件,大概2747~2754行左右。

    //#ifdef AK89xx_SECONDARY
    //    compass_result = compass_self_test();
    //    if (!compass_result)
    //        result |= 0x04;
    //#else
    //        result |= 0x04;
    //#endif
    
  4. 获取到的数据溢出,可能是fifo溢出了,改成下述,加快获取。

    //MPU6050_DMP_Get_Date(&x,&y,&z);
    while(MPU6050_DMP_Get_Date(&x,&y,&z)!=0){}
    
  5. 在能正常使用后,偶尔会出现-5,的初始化错误状态代码。

    错误码-5,按按意思是加载DMP固件出问题。其实只要重新拔插下调试器就行了。


资料链接

CupCondition.zip为项目文件,可以在CupCondition\MDK-ARM\Library下提取到上文所有库。

MotionDriver_6_1.zip为DMP的六个核心文件,也是上文提到的要复制到项目中的。

motion_driver_6.12.zip是官网下载的整体包,里面存在较多东西。

链接:https://pan.baidu.com/s/1zybNDBb3zCNYr2XTj1Wzfw  提取码:j95w

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值