前段时间在做平衡车,需要移植MPU6050程序。但是在网上找了挺多相关例子的,但是有时候一步步跟着做,结果还是一堆errors 或者读不出数据来,最后自己花了些时间,终于移植好了,前来分享一下。
先分享我的工程,和需要移植的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控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(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<nus*us_tick); //判断是否到达间隔
}
void delay_ms(u16 nms)
{
HAL_Delay(nms);
}
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
有没有办法快速将表格格式的ruby哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:
我给自己买了一个新的8gigUSBkey,我正在寻找一个合适的解决方案来拥有一个可移植RoR环境来学习。我在谷歌上搜索了一下,发现了一些可能性,但我很想听听一些现实生活中的经历和意见。谢谢! 最佳答案 我喜欢InstantRails,非常容易使用,无需安装程序,也不会修改您的系统环境。 关于ruby-on-rails-可移植RubyonRails环境,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/q
电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
mutationtesting遇到一个问题是它很慢,因为默认情况下您会为每个生成的突变执行完整的测试运行(测试文件或一组测试文件)。加快突变测试的一种方法是,一旦遇到单一故障(但仅在突变测试期间),就停止对给定突变体的测试运行。更好的做法是让变异测试者记住杀死最后一个变异体的第一个测试是什么,并将其首先交给下一个变异体。ruby中是否有任何东西可以做这些事情,或者我最好的选择是开始猴子修补?(是的,我知道单元测试应该很快。显示所有失败的测试在突变测试之外很有用,因为它不仅可以帮助您识别出问题,还可以查明哪里出了问题)编辑:我目前正在对测试/单元使用heckle。如果测试/单元不可能记住
我有两个类:1.Sale是ActiveRecord的子类;它的工作是将销售数据持久保存到数据库中。classSale2.SalesReport是一个标准的Ruby类;它的工作是生成和绘制有关销售的信息。classSalesReportdefinitialize(start_date,end_date)@start_date=start_date@end_date=end_dateenddefsales_in_durationSale.total_for_duration(@start_date,@end_date)end#...end因为我想使用TDD并且我希望我的测试运行得非常快,所
我正在寻找一个快速、无需配置的FTP服务器。完全像Serve的东西或Rack_dav,但对于FTP,它可以通过运行命令来发布文件夹。是否有gem或其他东西可以做这样的事情?解决方案基于Wayne的ftpdgem,我创建了一个快速且易于使用的gem,名为Purvey. 最佳答案 ftpdgem支持TLS,并带有文件系统驱动程序。与em-ftpd一样,您提供一个驱动程序,但该驱动程序不需要做太多事情。这是一个最低限度的FTP服务器,它接受任何用户名/密码,并提供临时目录中的文件:require'ftpd'require'tmpdir'c
给定两个字符串,我想确定它们是否是彼此的变位词。这是我想出的解决方案:#outputmessagesdefanagramputs"Anagram!"exitenddefnot_anagramputs"Notananagram!"exitend#mainmethodif__FILE__==$0#readtwostringsfromthecommandlinefirst,second=gets.chomp,gets.chomp#specialcase1not_anagramiffirst.length!=second.length#specialcase2anagramiffirst==s
快速求三阶矩阵的逆矩阵前言一般情况下,我们求解伴随矩阵是要注意符号问题和位置问题的(如下所示)A−1=1[ ][−[ ]−[ ]−[ ] −[ ]]=A−1=1[ ][ M11−[M12] M13−[M21] M22−[M23] M31−[M32] M33]⊤\begin{aligned}&A^{-1}=\frac{1}{[\\]}\left[\begin{array}{cccccc}&-[\\]&\\-[\\]&&-[\\]\\\\&-[\\]&\\\end{array}\right]=\\\\&A^{-1}=\frac{1}{[\\]}\left[\b
以前我们经常打趣说:***,你out了!当然了,玩笑成分居多。但是如果作为一名技术人员,现在还没有听说过ChatGPT,那么你可能真的“out”了。比尔·盖茨说,ChatGPT的重要性堪比互联网的发明,甚至它“将改变我们的世界”。ChatGPT得到科技界大佬的如此推崇,那么,ChatGPT到底是什么?ChatGPT是2022年11月底,美国OpenAI公司推出的一款人工智能聊天机器人。两个月后,ChatGPT的月活用户已经突破1亿,成为有史以来增长速度最快的消费者应用程序。ChatGPT功能极其强大,它能够通过学习和理解人类的语言进行对话,还能根据上下文进行互动,实现像人类一样的聊天交流。除了