STM32F103HAL库移植MPU6050的DMP库
前言
众所周知啊,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库相关推荐
- 六轴加速度传感器MPU6050官方DMP库到瑞萨RL78/G13的移植
2015年的电赛已经结束了.赛前接到器件清单的时候,看到带防护圈的多旋翼飞行器赫然在列,又给了一个瑞萨RL78/G13的MCU,于是自然联想到13年的电赛,觉得多半是拿RL78/G13做四旋翼的主控, ...
- 【51单片机快速入门指南】4.3.1: MPU6050调用DMP库获取四元数和欧拉角
目录 相关介绍 DMP库相关 DMP加载步骤: DMP设置数据写入 更新DMP DMP数据包结构 程序实现 DMP.c DMP.h 测试程序 四元数 实验现象 欧拉角的获取 普中51-单核-A2 ST ...
- mpu6050的dmp库调试经验-固件库和自检
dmp库终于终于在stm32上移植成功了. 我主要卡在了固件库. 首先建议参考一下 原码放送,MPU6050的DMP用STM32成功的实现,内有移植问题说明 (amobbs.com 阿莫电子论坛) 我 ...
- ESP-12F驱动MPU6050使用DMP库姿态解算
一.准备工作 主芯片采用是安信可科技的ESF-12F模组(内置ESP8266芯片),使用GPIO模拟I2C驱动MPU6050,i2c驱动部分可直接参考官方例程中的i2c_master.c文件,(附件提 ...
- 【S操作】轻松优雅库移植解决方案,arduino库移植应对方案
微信关注 "DLGG创客DIY" 设为"星标",重磅干货,第一时间送达. 为啥要用arduino?最重要的一个原因就是因为arduino完美的生态,即可以找到很 ...
- 【STM32+cubemx】0028 HAL库开发:MPU6050官方DMP的移植和使用(续上节)
上一节我们使I2C总线获取了MPU6050的三轴加速度.三轴角速度,并且介绍了一种简单的初始状态校准方法:这一节我们继续,在已有的底层驱动基础上,移植MPU6050芯片官方的DMP库,来获取角度信息. ...
- tm4驱动外接模块系列(一)--------有dmp库的mpu6050
mpu6050是嵌入式设计中一个比较常用的芯片,虽然有比它更好的芯片,但耐不住这块芯片便宜,所以使用也是非常广.它的主要功能是可以提供以它为中心的欧拉角的值和一些陀螺仪,加速度传感器的数据. 笔者根据 ...
- 【GD32F427开发板试用】二、USB库移植与双USB CDC-ACM功能开发
本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动,更多开发板试用活动请关注极术社区网站.作者:chenjie [GD32F427开发板试用]一.环境搭建与freertos移植 [GD ...
- 六轴加速陀螺仪MPU6500/MPU6050使用及DMP库移植,含记步器功能
本篇博客为博主学习使用MPU6500完成后的学习记录,故在这只做主要讲解,如有博友看完后仍不知如何使用,可在下方留言问我,或发邮件问我(dayou1024@qq.com),因邮件有QQ和微信提示,故我 ...
最新文章
- linux c不占用cpu的延时,linux下写个C语言程序,要求有0.5微秒以下的延时,要怎样写...
- SpringMVC4集成ehcache
- [Java多线程]-J.U.C.atomic包下的AtomicInteger,AtomicLong等类的源码解析
- 《JavaScript设计模式与开发实践》原则篇(3)—— 开放-封闭原则
- 删库跑路事件发生,SaaS云服务如何守护数据安全
- php递归删除文件,PHP 递归删除文件夹
- 像程序员一样思考:如何仅使用JavaScript,HTML和CSS来构建Snake
- android中intent放数据类型,Android Intent传递数据底层分析详细介绍
- IBM服务器安装与HBA卡的驱动问题
- oracle关联两个字段,oracle字符串连接函数,||使两个或多个字段拼成一个字段
- [开发工具] STM32算法的翅膀之MATLAB
- 赵小楼《天道》《遥远的救世主》深度解析(142)贫富差距化是常态,扶贫不是拉平平均值,而是强者去关注弱者
- Marshmallow 库
- 彻底搞懂javascript中的replace函数
- JS中Key-Value操作
- 学习《java程序设计》第一周学习总结
- 计算方法的稳定性 | 误差来源之舍入误差 | 数值计算基本原则
- python开发的著名网站_python开发著名网站_python开发的著名软件 - CSDN
- 大数据技术原理与应用实验五
- 自动控制原理 传递函数
热门文章
- java lftp_lftp使用详解
- Rust链接C语言Intel MKL库报错
- 10分钟看完一本书《极简主义》
- 神舟战神z7使用U盘重装系统操作教程分享
- Android【帧动画】
- 超有霸气的,有影响力的Java/C++/ASP.NET面试题
- c语言不用第三个变量 实现两个数的对调,下面程序功能是不用第三个变量,实现两个数对调操作 ....docx...
- 【Java】数组逆序操作。定义长度为10的数组,将数组元素对调并输出对调后的结果。
- 我的世界中国版配置java_我的世界中国版Java 不删档测试问题指引
- 你应该学会像程序员一样思考