前段时间在做平衡车,需要移植MPU6050程序。但是在网上找了挺多相关例子的,但是有时候一步步跟着做,结果还是一堆errors 或者读不出数据来,最后自己花了些时间,终于移植好了,前来分享一下。
先分享我的工程,和需要移植的MPU6050的程序
完整工程 + MPU6050移植程序
提取码:3ycr
效果演示
接下来进入正题:
一、首先在CubeMX中创建工程
1. 先正常配置RCC、SYS和时钟树。
2. 我这里选择PB6和PB7读MPU6050用、打开了串口1、并且我打开了4个脚给OLED用。
3. 然后生成工程好了。
二、程序移植
1. 我们把下载到的MPU6050程序添加到工程中,加入.c文件,并且把头文件路径也添加进来。
2. #include "头文件"
代码放这里
#include "mpu6050.h"//MPU6050驱动库
#include "inv_mpu.h"//陀螺仪驱动库
#include "inv_mpu_dmp_motion_driver.h" //DMP姿态解读库读库
#include "XMF_OLED_STM32Cube.h" //OLED头文件
#include "stdio.h" //使用printf用
此时编译会发现报很多错
三、修改程序
1. 把这下面几个文件,用main.h 代替 sys.h 和 stm32f10x.h
2. 然后再main.h文件下加入下面这些
代码放这里
typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
3. 自己创建delay.c 和 delay.h 文件 加入工程,包含头文件路径.分别在里面加入下面这些代码
delay.h
#ifndef __DELAY_H
#define __DELAY_H
#include "main.h"
void delay_ms(u16 nms);
void delay_us(u32 nus);
#endif
delay.c
#include "delay.h"
void delay_us(u32 nus)
{
uint32_t us_tick=SystemCoreClock / 1000000UL;
uint32_t start,now,JianGe,reload;
start=SysTick->VAL; //把最开始获得的计数值作为基准值
reload = SysTick->LOAD;
do{
now=SysTick->VAL; //获取当前值
JianGe = start > now ? start - now : reload + start - now;
}while(JianGe
4. 把mpuiic.c里面的下图内容注释掉
5.接下来编译就可以通过啦
四、在main.c下面加入串口重定向,以及 MPU6050的一些变量 ,再加入读数据的函数就大功告成啦 !
代码放这里
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
float pitch,roll,yaw; //欧拉角:俯仰角,滚转角,偏航角
short aacx,aacy,aacz; //加速度传感器原始数据 加速度
short gyrox,gyroy,gyroz; //陀螺仪原始数据 角速度
short temp; //MPU温度
uint8_t str_buff[64];
uint8_t str_buff1[64]="俯仰角:"; //pitch
uint8_t str_buff2[64]="偏航角:"; //yaw
uint8_t str_buff3[64]="翻滚角:"; //roll
uint8_t str_buff4[64]="温度值:";
struct MPU6050 //MPU6050结构体
{
u8 flag; //采集成功标志位
u8 speed; //上报速度
}mpu6050; //唯一结构体变量
读数据的一些函数 放再这下面 有MPU_Read 和 DATA_Report 两个函数
代码放这里
void MPU_Read(void)
{
if(mpu_dmp_get_data(&pitch,&roll,&yaw)==0)//dmp处理得到数据,对返回值进行判断
{
// temp=MPU_Get_Temperature(); //得到温度值
MPU_Get_Accelerometer(&aacx,&aacy,&aacz); //得到加速度传感器数据
MPU_Get_Gyroscope(&gyrox,&gyroy,&gyroz); //得到陀螺仪数据
mpu6050.speed++; //上报速度自加
if(mpu6050.speed == 4) //上报速度阈值设置
{
mpu6050.flag = 1; //采集成功标志位设置为有效
mpu6050.speed = 0; //上报速度归零
}
}
else //采集不成功
{
mpu6050.flag = 0; //采集成功标志位设置为无效
}
}
/**
* @brief MPU6050数据上报
* @param 无
* @retval 无
*/
void DATA_Report(void)
{
if(mpu6050.flag == 1) //采集成功时
{
if(temp<0) //对数据正负判断,判断为负时
{
temp=-temp; //对负数据取反
}
else //判断为正时
{
}
// sprintf((char *)str_buff,"%d.%d",temp/100,temp%10);
// OLED_ShowString(60,0,str_buff);
// printf("temp:%d.%d --- ",temp/100,temp%10); //通过串口1输出温度
temp=pitch*10; //赋temp为pitch
if(temp<0) //对数据正负判断,判断为负时
{
temp=-temp; //对负数据取反
}
else //判断为正时
{
}
sprintf((char *)str_buff,"%d.%d",(temp)/10,(temp)%10);
OLED_ShowString(60,0,str_buff);
// OLED_ShowString(65,6,str_buff);
// printf("pitch:%d.%d --- ",temp/10,temp%10); //通过串口1输出pitch
temp=roll*10; //赋temp为roll
if(temp<0) //对数据正负判断,判断为负时
{
temp=-temp; //对负数据取反
}
else //判断为正时
{
}
sprintf((char *)str_buff,"%d.%d",temp/10,temp%10);
OLED_ShowString(60,4,str_buff);
// printf("roll:%d.%d --- ",temp/10,temp%10);//通过串口1输出roll
temp=yaw*10; //赋temp为yaw
if(temp<0) //对数据正负判断,判断为负时
{
temp=-temp; //对负数据取反
// OLED_ShowString(100,6,"-");
}
else //判断为正时
{ //OLED_ShowString(100,6,"+");
}
sprintf((char *)str_buff,"%d.%d",temp/10,temp%10);
OLED_ShowString(60,2,str_buff);
// sprintf((char *)str_buff,"%f",yaw);
// OLED_ShowString(60,0,str_buff);
// printf("yaw:%d.%d\r\n",temp/10,temp%10);//通过串口1输出yaw
// printf("gyrox:%d,gyroy:%d,gyroz:%d,aacx:%d,aacy:%d,aacz:%d\r\n",gyrox,gyroy,gyroz,aacx,aacy,aacz);//上报角速度数据,角加速度数据
mpu6050.flag = 0; //采集成功标志位设置为无效
}
else ; //防卡死
}
五、最后把这两个函数放在while(1)里调用就可以读出数据啦 !
如果想改SDA 和 SCL 的引脚 ,修改这里
第一次写博客,有些写得不好的地方请大家指正 谢谢大家 0.0