前言

众所周知啊,MPU6050是一个在硬件上使用非常广泛的IC,在我们的使用中,MPU6050是一个不可缺少的东西,特别是四轴。

我们一般都是用软件模拟IIC与MPU6050进行通信,但是读到的是它的6个原始数据,这些数据对于我们初学的人来说用处不大,所以我们一般还要将其进行滤波,四元数转换等等操作得到其三个角(航向角(yaw)、横滚角(roll)和俯仰角(pitch)),这三者就能够表示当前设备的姿态。MPU6050自带DMP解算库,可以直接将我们的原始数据转换成欧拉角,但是他是非开源的,并且还是针对MSP430的,移植起来的有点难度,所以我把我的移植过程记录下来,给以后的我,大家一个参考。

正题

MPU6050只能支持IIC通信,所以我们用STM32F103的IIC模式,在STM32CUBEMX中初始化一些相关的外设,本文章用的是STM32F103C8T6,DMP的相关文件来自于正点原子的DMP文件。

开启外部晶振(外部晶振的精度更高并且受温度影响较小)

打开仿真调试IO口,这里我们选择SWD接口,引脚少,并且速度比JTAG快

IIC我们选择CUBEMX自带的硬件IIC,很多人说ST为了规避专利把硬件IIC设计得很难用,但我个人觉得还行。这里我们选择IIC即可,第一个参数I2C speed Mode我们选择FAST MODE,即40000HZ,否则MPU6050会有几率不通过自检。

如果还要加一些其他的外设功能的话自行设定即可。

串口1,参数默认即可

时钟我们配置成常规的即可

最后点击GNENERATE CODE,生成初始化代码。

在生成的文件中,我们需要添加需要用的函数,MPU6050,DMP相关的文件。

这三个文件中,MPU6050是我们此次需要关注的(另外两个是我做电机控制用的,如果您只需要移植MOU6050,则不需要关心这两个文件)

这几个文件中eMPL是官方给的DMP库,移植时可以直接输出姿态角,而mpu6050.c函数是读取加速度计和陀螺仪计的原始值的,如果不需要原始数据的话我们可以不需要将mpu6050.c和mou6050.h移植过来。

这六个文件是我们此次需要重点关注的对象

进来我们先把相关的文件加进来

添加路径

添加头文件

#include "oled.h"
#include "mpu6050.h"
#include "control.h"
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"

添加变量

float pitch,roll,yaw;        //欧拉角
short aacx,aacy,aacz;       //加速度传感器原始数据
short gyrox,gyroy,gyroz;    //陀螺仪原始数据
short temp;                 //温度

在相关初始化函数定义之后加上如下代码

while(mpu_dmp_init()){HAL_Delay(200);printf("%s\r\n","Mpu6050_DMP Init Wrong!");printf("   %d",mpu_dmp_init());}printf("%s\r\n","DMP_Mpu6050 Init OK!");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);    //得到陀螺仪数据printf("三轴角度:%f-%f-%f\r\n",pitch,roll,yaw);
//      printf("三轴加速度:%d-%d-%d\r\n",aacx,aacy,aacz);
//      printf("三轴角角度:%d-%d-%d\r\n",gyrox,gyroy,gyroz);}delay_ms(100);

在usart.c文件中配置串口输出重定向

/* USER CODE BEGIN 1 */
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xffff);return ch;
}/*** 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx* 输入参数: 无* 返 回 值: 无* 说    明:无*/
int fgetc(FILE *f)
{uint8_t ch = 0;HAL_UART_Receive(&huart3, &ch, 1, 0xffff);return ch;
}
/* USER CODE END 1 */

并在头文件中声明,这样子就不会有prinf未定义警告了。

接下来我们来说说两个重要的文件,"inv_mpu.c"和include "inv_mpu_dmp_motion_driver.c"

有几处重要的地方需要我们修改

nv_mpu.c

1.头文件

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "inv_mpu.h"
#include "inv_mpu_dmp_motion_driver.h"
#include "mpu6050.h"
#include "delay.h"
#include "usart.h"

其中,HAL库中#include "delay.h"是需要自己定义添加的,他在正点原子中就是定义了三个函数

void delay_init(u8 SYSCLK);
void delay_ms(u16 nms);
void delay_us(u32 nus);

在#include "inv_mpu.h"中我们只用到了void delay_ms(u16 nms),这个函数HAL库中有一个替代的函数, HAL_Delay(ms),我们直接用他就行了。

现在来到了最重要的一个地方

#define i2c_write   MPU_Write_Len
#define i2c_read    MPU_Read_Len
#define delay_ms    HAL_Delay
#define get_ms      mget_ms

这里DMP官方把这个函数封装起来了,   MPU_Write_Len,MPU_Read_Len,HAL_Delay,mget_ms。我们需要在IIC中去定义这三个函数(换个说法就是给IIC读写函数换个皮)

/* USER CODE BEGIN 1 */
unsigned char MPU_Write_Len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf)
{
    HAL_I2C_Mem_Write(&hi2c1, addr, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
    return 0;
}
unsigned char MPU_Read_Len(unsigned char addr,unsigned char reg,unsigned char len,unsigned char *buf)
{
    HAL_I2C_Mem_Read(&hi2c1, addr, reg, I2C_MEMADD_SIZE_8BIT, buf, len, 0xfff);
    return 0;
}
/* USER CODE END 1 */

HAL_Delay我们用STM32CUBEMX自己定义的函数,这个函数在HAL库中一个弱定义函数,我们可以根据需要自己再另外定义一个同名函数。

#define get_ms      mget_ms中  mget_ms是一个空函数,并没有执行任何程序,这里我们无需更改。

接下来我们只要更改 mpu_dmp_init函数即可,这个函数是DMP库对外的接口,这里我们把正点原子中的

MPU_IIC_Init();     //初始化IIC总线

改成

MX_I2C1_Init();     //初始化IIC总线

即可

unsigned char mpu_dmp_init(void)
{unsigned char res=0;MX_I2C1_Init();   //初始化IIC总线if(mpu_init()==0)   //初始化MPU6050{    res=mpu_set_sensors(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置所需要的传感器if(res)return 1; res=mpu_configure_fifo(INV_XYZ_GYRO|INV_XYZ_ACCEL);//设置FIFOif(res)return 2; res=mpu_set_sample_rate(DEFAULT_MPU_HZ);    //设置采样率if(res)return 3; res=dmp_load_motion_driver_firmware();     //加载dmp固件if(res)return 4; res=dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向if(res)return 5; res=dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT|DMP_FEATURE_TAP|    //设置dmp功能DMP_FEATURE_ANDROID_ORIENT|DMP_FEATURE_SEND_RAW_ACCEL|DMP_FEATURE_SEND_CAL_GYRO|DMP_FEATURE_GYRO_CAL);if(res)return 6; res=dmp_set_fifo_rate(DEFAULT_MPU_HZ); //设置DMP输出速率(最大不超过200Hz)if(res)return 7;   res=run_self_test();     //自检if(res)return 8;    res=mpu_set_dmp_state(1);  //使能DMPif(res)return 9;     }else return 10;return 0;
}

这时候我们移植的就差不多了,但是还要注意一些细节问题,比如IIC地址的位对齐问题,在HAL库中,是没有将IIC地址左移的,所以我们需要手动将我们的IIC地址左移一位,因为我的ADO给的低电平,所以地址就是0X68<<1了

const struct hw_s hw={0x68<<1,     //addr1024,     //max_fifo118,  //num_reg340,   //temp_sens-521,    //temp_offset256    //bank_size
};

很多同学可能就是在这里出了问题,因为原子家的代码是在IIC的函数中将地址左移了,所以我们定义的IIC地址没有做左移位。

而HAL库官方给的硬件IIC读取,写入API是需要左移的,这一点在这个API的注释中也写明了

DevAddress Target device address: The device 7 bits address value in datasheet must be shifted to the left before calling the interface

最后我们就移植的差不多啦,来看看现象。

STM32F103HAL库移植MPU6050的DMP库相关推荐

  1. 六轴加速度传感器MPU6050官方DMP库到瑞萨RL78/G13的移植

    2015年的电赛已经结束了.赛前接到器件清单的时候,看到带防护圈的多旋翼飞行器赫然在列,又给了一个瑞萨RL78/G13的MCU,于是自然联想到13年的电赛,觉得多半是拿RL78/G13做四旋翼的主控, ...

  2. 【51单片机快速入门指南】4.3.1: MPU6050调用DMP库获取四元数和欧拉角

    目录 相关介绍 DMP库相关 DMP加载步骤: DMP设置数据写入 更新DMP DMP数据包结构 程序实现 DMP.c DMP.h 测试程序 四元数 实验现象 欧拉角的获取 普中51-单核-A2 ST ...

  3. mpu6050的dmp库调试经验-固件库和自检

    dmp库终于终于在stm32上移植成功了. 我主要卡在了固件库. 首先建议参考一下 原码放送,MPU6050的DMP用STM32成功的实现,内有移植问题说明 (amobbs.com 阿莫电子论坛) 我 ...

  4. ESP-12F驱动MPU6050使用DMP库姿态解算

    一.准备工作 主芯片采用是安信可科技的ESF-12F模组(内置ESP8266芯片),使用GPIO模拟I2C驱动MPU6050,i2c驱动部分可直接参考官方例程中的i2c_master.c文件,(附件提 ...

  5. 【S操作】轻松优雅库移植解决方案,arduino库移植应对方案

    微信关注 "DLGG创客DIY" 设为"星标",重磅干货,第一时间送达. 为啥要用arduino?最重要的一个原因就是因为arduino完美的生态,即可以找到很 ...

  6. 【STM32+cubemx】0028 HAL库开发:MPU6050官方DMP的移植和使用(续上节)

    上一节我们使I2C总线获取了MPU6050的三轴加速度.三轴角速度,并且介绍了一种简单的初始状态校准方法:这一节我们继续,在已有的底层驱动基础上,移植MPU6050芯片官方的DMP库,来获取角度信息. ...

  7. tm4驱动外接模块系列(一)--------有dmp库的mpu6050

    mpu6050是嵌入式设计中一个比较常用的芯片,虽然有比它更好的芯片,但耐不住这块芯片便宜,所以使用也是非常广.它的主要功能是可以提供以它为中心的欧拉角的值和一些陀螺仪,加速度传感器的数据. 笔者根据 ...

  8. 【GD32F427开发板试用】二、USB库移植与双USB CDC-ACM功能开发

    本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站.作者:chenjie [GD32F427开发板试用]一.环境搭建与freertos移植 [GD ...

  9. 六轴加速陀螺仪MPU6500/MPU6050使用及DMP库移植,含记步器功能

    本篇博客为博主学习使用MPU6500完成后的学习记录,故在这只做主要讲解,如有博友看完后仍不知如何使用,可在下方留言问我,或发邮件问我(dayou1024@qq.com),因邮件有QQ和微信提示,故我 ...

最新文章

  1. linux c不占用cpu的延时,linux下写个C语言程序,要求有0.5微秒以下的延时,要怎样写...
  2. SpringMVC4集成ehcache
  3. [Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析
  4. 《JavaScript设计模式与开发实践》原则篇(3)—— 开放-封闭原则
  5. 删库跑路事件发生,SaaS云服务如何守护数据安全
  6. php递归删除文件,PHP 递归删除文件夹
  7. 像程序员一样思考:如何仅使用JavaScript,HTML和CSS来构建Snake
  8. android中intent放数据类型,Android Intent传递数据底层分析详细介绍
  9. IBM服务器安装与HBA卡的驱动问题
  10. oracle关联两个字段,oracle字符串连接函数,||使两个或多个字段拼成一个字段
  11. [开发工具] STM32算法的翅膀之MATLAB
  12. 赵小楼《天道》《遥远的救世主》深度解析(142)贫富差距化是常态,扶贫不是拉平平均值,而是强者去关注弱者
  13. Marshmallow 库
  14. 彻底搞懂javascript中的replace函数
  15. JS中Key-Value操作
  16. 学习《java程序设计》第一周学习总结
  17. 计算方法的稳定性 | 误差来源之舍入误差 | 数值计算基本原则
  18. python开发的著名网站_python开发著名网站_python开发的著名软件 - CSDN
  19. 大数据技术原理与应用实验五
  20. 自动控制原理 传递函数

热门文章

  1. java lftp_lftp使用详解
  2. Rust链接C语言Intel MKL库报错
  3. 10分钟看完一本书《极简主义》
  4. 神舟战神z7使用U盘重装系统操作教程分享
  5. Android【帧动画】
  6. 超有霸气的,有影响力的Java/C++/ASP.NET面试题
  7. c语言不用第三个变量 实现两个数的对调,下面程序功能是不用第三个变量,实现两个数对调操作 ....docx...
  8. 【Java】数组逆序操作。定义长度为10的数组,将数组元素对调并输出对调后的结果。
  9. 我的世界中国版配置java_我的世界中国版Java 不删档测试问题指引
  10. 你应该学会像程序员一样思考