基于STM32单片机模块练习——在使用MPU6050时遇到的令人头疼的问题
在使用MPU6050时遇到的令人头疼的问题
1.整个程序在一开始运行就卡死在启动文件
首先看一下,Target设置选项下的Use MicroLIB选项是不是选上勾了。
如果这个设置也解决不了问题,那么你需要检查一下程序里,是否写了printf函数的接口函数。因为MPU6050里面有
用到了这个函数,如果你没写这个函数的接口函数,就会导致系统卡死在系统文件里。
printf函数的接口函数
///重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{/* 发送一个字节数据到串口 */USART_SendData(DEBUG_USARTx, (uint8_t) ch);/* 等待发送完毕 */while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); return (ch);
}
2.while循环里的条件明明不满足了,程序却一致卡死在此循环里
检查一下,判断条件里的变量的类型是否正确。另外,如果这个变量在中断服务函数里面需要改变值,那么在定义这个变量的语句前应该加上关键字
volatile
volatile的具体描述参考
3.MPU6050在执行mpu_dmp_init()函数时,一直出现错误,且错误在run_self_test()
1)首先,看一下是不是因为你在程序初始化的时候,没有把MPU6050水平放置,至于为什么要水平放置呢?
因为在run_self_test()函数里面有一个mpu_run_self_test(gyro, accel)函数,这个函数上面有一个注释特别重要:
This function must be called with the device either face-up or face-down* (z-axis is parallel to gravity).此函数必须在设备面朝上或面朝下时调用(z轴与重力平行)
2)如果照着1)的方法还是解决不了这个问题,那么请你检查一下run_self_test函数里面的具体内容是否和下面的一模一样:
//MPU6050自测试
//返回值:0,正常
// 其他,失败
u8 run_self_test(void)
{int result;//char test_packet[4] = {0};long gyro[3], accel[3]; result = mpu_run_self_test(gyro, accel);if (result == 0x3) //这个地方要的别注意,有的例程会把0X3错误的写为0X7{/* Test passed. We can trust the gyro data here, so let's push it down* to the DMP.*/float sens;unsigned short accel_sens;mpu_get_gyro_sens(&sens);gyro[0] = (long)(gyro[0] * sens);gyro[1] = (long)(gyro[1] * sens);gyro[2] = (long)(gyro[2] * sens);dmp_set_gyro_bias(gyro);mpu_get_accel_sens(&accel_sens);accel[0] *= accel_sens;accel[1] *= accel_sens;accel[2] *= accel_sens;dmp_set_accel_bias(accel);return 0;}else return 1;
}
4.mpu_dmp_get_data(&pitch,&roll,&yaw)函数的返回值不正确(一直不是0)
MPU6050读不出来数据
如果参考以上这篇文章还是无法帮助解决问题,那么不妨试一下,把模拟iic的这部分代码换一下,也许可能就是因为iic这部分程序不正确。
模拟IIC的代码:
#include "mpuiic.h"
#include "./systick/bsp_SysTick.h"
#define Soft_I2C_SDA GPIO_Pin_3
#define Soft_I2C_SCL GPIO_Pin_4
#define Soft_I2C_PORT GPIOB
#define MPU6050_GPIO_CLK RCC_APB2Periph_GPIOB
//IO方向设置 ---PB11
#define MPU_SDA_IN() {Soft_I2C_PORT ->CRL &= 0XFFFF0FFF;Soft_I2C_PORT ->CRL |= 8<<12;} //上拉/下拉 输入模式
#define MPU_SDA_OUT() {Soft_I2C_PORT ->CRL &= 0XFFFF0FFF;Soft_I2C_PORT ->CRL |= 7<<12;} //开漏输出 输出模式/* 定义读写SCL和SDA的宏,已增加代码的可移植性和可阅读性 */
#if 1 /* 条件编译: 1 选择GPIO的库函数实现IO读写 */#define MPU6050_I2C_SCL_1() GPIO_SetBits(Soft_I2C_PORT, Soft_I2C_SCL) /* SCL = 1 */#define MPU6050_I2C_SCL_0() GPIO_ResetBits(Soft_I2C_PORT, Soft_I2C_SCL) /* SCL = 0 */#define MPU6050_I2C_SDA_1() GPIO_SetBits(Soft_I2C_PORT, Soft_I2C_SDA) /* SDA = 1 */#define MPU6050_I2C_SDA_0() GPIO_ResetBits(Soft_I2C_PORT, Soft_I2C_SDA) /* SDA = 0 */#define MPU6050_I2C_SDA_READ() GPIO_ReadInputDataBit(Soft_I2C_PORT, Soft_I2C_SDA) /* 读SDA口线状态 */
#else /* 这个分支选择直接寄存器操作实现IO读写 *//* 注意:如下写法,在IAR最高级别优化时,会被编译器错误优化 */#define MPU6050_I2C_SCL_1() Soft_I2C_PORT->BSRR = Soft_I2C_SCL /* SCL = 1 */#define MPU6050_I2C_SCL_0() Soft_I2C_PORT->BRR = Soft_I2C_SCL /* SCL = 0 */#define MPU6050_I2C_SDA_1() Soft_I2C_PORT->BSRR = Soft_I2C_SDA /* SDA = 1 */#define MPU6050_I2C_SDA_0() Soft_I2C_PORT->BRR = Soft_I2C_SDA /* SDA = 0 */#define MPU6050_I2C_SDA_READ() ((Soft_I2C_PORT->IDR & Soft_I2C_SDA) != 0) /* 读SDA口线状态 */
#endif/**********************************************
函数名称:MPU_IIC_Delay
函数功能:MPU IIC延时函数,延时2ms
函数参数:无
函数返回值:无
**********************************************/
void MPU_IIC_Delay(void)
{uint8_t i;/* 下面的时间是通过逻辑分析仪测试得到的。工作条件:CPU主频72MHz ,MDK编译环境,1级优化循环次数为10时,SCL频率 = 205KHz 循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us */for (i = 0; i < 100; i++);
}/**********************************************
函数名称:MPU_IIC_Init
函数功能:MPU IIC初始化
函数参数:无
函数返回值:无
**********************************************/
void MPU_IIC_Init(void)
{ GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(MPU6050_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE); //先使能外设IO PORTB时钟 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE); GPIO_InitStructure.GPIO_Pin = Soft_I2C_SCL|Soft_I2C_SDA; //端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHzGPIO_Init(Soft_I2C_PORT , &GPIO_InitStructure); //根据设定参数初始化GPIO GPIO_SetBits(Soft_I2C_PORT,Soft_I2C_SCL|Soft_I2C_SDA); //PB10,PB11 输出高 }//产生IIC起始信号
void MPU_IIC_Start(void)
{MPU_SDA_OUT(); //sda线输出MPU6050_I2C_SDA_1(); MPU6050_I2C_SCL_1();MPU_IIC_Delay();MPU6050_I2C_SDA_0();//START:when CLK is high,DATA change form high to low MPU_IIC_Delay();MPU6050_I2C_SCL_0();//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
void MPU_IIC_Stop(void)
{MPU_SDA_OUT();//sda线输出MPU6050_I2C_SCL_0();MPU6050_I2C_SDA_0();//STOP:when CLK is high DATA change form low to highMPU_IIC_Delay();MPU6050_I2C_SCL_1(); MPU6050_I2C_SDA_1();//发送I2C总线结束信号MPU_IIC_Delay();
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
u8 MPU_IIC_Wait_Ack(void)
{u8 ucErrTime=0;MPU_SDA_IN(); //SDA设置为输入 MPU6050_I2C_SDA_1();MPU_IIC_Delay(); MPU6050_I2C_SCL_1();MPU_IIC_Delay(); while(MPU6050_I2C_SDA_READ()){ucErrTime++;if(ucErrTime>250){MPU_IIC_Stop();return 1;}}MPU6050_I2C_SCL_0();//时钟输出0 return 0;
}
//产生ACK应答
void MPU_IIC_Ack(void)
{MPU6050_I2C_SCL_0();MPU_SDA_OUT();MPU6050_I2C_SDA_0();MPU_IIC_Delay();MPU6050_I2C_SCL_1();MPU_IIC_Delay();MPU6050_I2C_SCL_0();
}
//不产生ACK应答
void MPU_IIC_NAck(void)
{MPU6050_I2C_SCL_0();MPU_SDA_OUT();MPU6050_I2C_SDA_1();MPU_IIC_Delay();MPU6050_I2C_SCL_1();MPU_IIC_Delay();MPU6050_I2C_SCL_0();
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void MPU_IIC_Send_Byte(u8 _ucByte)
{ uint8_t i;MPU_SDA_OUT(); MPU6050_I2C_SCL_0();//拉低时钟开始数据传输/* 先发送字节的高位bit7 */for (i = 0; i < 8; i++){ if (_ucByte & 0x80){MPU6050_I2C_SDA_1();}else{MPU6050_I2C_SDA_0();}_ucByte <<= 1; /* 左移一个bit */MPU6050_I2C_SCL_1();MPU_IIC_Delay(); MPU6050_I2C_SCL_0();MPU_IIC_Delay();}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
u8 MPU_IIC_Read_Byte(unsigned char ack)
{unsigned char i,receive=0;MPU_SDA_IN();//SDA设置为输入for(i=0;i<8;i++ ){MPU6050_I2C_SCL_0(); MPU_IIC_Delay();MPU6050_I2C_SCL_1();receive<<=1;if(MPU6050_I2C_SDA_READ())receive++; MPU_IIC_Delay(); } if (!ack)MPU_IIC_NAck();//发送nACKelseMPU_IIC_Ack(); //发送ACK return receive;
}
5.读取的数据成功率低(也就是说读取10次,mpu_dmp_get_data有5次都返回1,而不是0)
1.可能是 MPU_IIC_Delay()这个函数取值不恰当,可以调整一下看看效果。
2.读取MPU6050数据卡死的总结
6.容易忽视的小问题,却恰恰最致命
例如:
STM32的PB3、PB4,分别是JTAG的JTDO和NJTRST引脚,在没关闭JTAG功能之前,在程序中是配置不了这些引脚的功能的。要配置这些引脚,首先要开启AFIO时钟,然后在AFIO的设置中,释放这些引脚。具体看STM32的参考手册中有关AFIO的部分。
RCC_APB2PeriphClockCmd(MPU6050_GPIO_CLK|RCC_APB2Periph_AFIO,ENABLE); //先使能外设IO PORTB时钟 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
/******************************************************************#define GPIO_Remap_SWJ_NoJTRST ((uint32_t)0x00300100) < Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
#define GPIO_Remap_SWJ_JTAGDisable ((uint32_t)0x00300200) < JTAG-DP Disabled and SW-DP Enabled
#define GPIO_Remap_SWJ_Disable ((uint32_t)0x00300400) !< Full SWJ Disabled (JTAG-DP + SW-DP)
******************************************************************/
STM32——GPIO重映射(GPIO_PinRemapConfig)
基于STM32单片机模块练习——在使用MPU6050时遇到的令人头疼的问题相关推荐
- 基于STM32单片机模块练习——OLED模块
基于STM32单片机模块练习--OLED模块 相关知识点 向OLED写一个字节 /*** @brief I2C_WriteByte,向OLED寄存器地址写一个byte的数据* @param addr: ...
- 基于STM32单片机光学指纹识别模块(FPM10A)全教程(基于C语言)
本文转载,其来源在参考中:1,稍加修改,因为近期使用到这个模块,故而加以整理! 1.平台 首先我使用的是 奋斗 STM32 开发板 MINI板 基于STM32单片机光学指纹识别模块(FPM10A)全教 ...
- 最简单DIY基于STM32单片机的WIFI智能小车设计方案
STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 第三篇:最简单DIY基于STM32F ...
- 基于STM32单片机的步数测量系统(免费开源)
基于STM32单片机的步数测量系统 1.1设计要求 1.2设计所需器材 1.3 设计原理 1.4核心代码 1.5结果展示 1.6资源链接 1.7硬件电路图 1.1设计要求 设计一款基于STM32的步数 ...
- 基于STM32单片机智能RFID刷卡汽车位锁设计(论文
基于STM32单片机智能RFID刷卡汽车位锁设计(论文) 摘要 在车位日益紧张的今天,如何避免私家车位被他人抢占,是令人头痛的事.日前面市的一种新型车位锁,不仅有效解决了这一问题,还可对车辆起到防盗作 ...
- 最简单DIY基于STM32单片机的蓝牙智能小车设计方案
STM32库函数开发系列文章目录 第一篇:STM32F103ZET6单片机双串口互发程序设计与实现 第二篇:最简单DIY基于STM32单片机的蓝牙智能小车设计方案 文章目录 STM32库函数开发系列文 ...
- 基于STM32单片机的密码锁(Proteus仿真+程序+报告)
3-基于STM32单片机的密码锁 功能描述如下: 由STM32F103单片机最小系统+ 4*4矩阵键盘+LCD1602液晶显示+蜂鸣器+继电器模块: 1.采用STM32F103为主控芯片. 2.通过4 ...
- B40 - 基于STM32单片机的电热蚊香蓝牙控制系统
任务 本项目进行智能电热蚊香器系统的设计与开发,将STM32开发板作为一个微控制器,结合蓝牙技术,通过手机APP软件对电热蚊香器进行灵活的控制,使电热蚊香器的功能更加人性化,更加符合当代人们对家用电器 ...
- 9、★♥★基于STM32单片机的颜色检测仪设计♥☆
9.★♥★基于STM32单片机的颜色检测仪设计♥☆ 文章目录 9.★♥★基于STM32单片机的颜色检测仪设计♥☆ 引言 1.系统概述 1.1.设计任务 1.2.设计要求 2.方案设计与论证 2.1.芯 ...
最新文章
- ap java内容_AP 计算机知识点总结
- java--面向接口编程
- influxdb 客户端工具_性能工具之Jmeter小白入门系列之六
- [css] 简述你对BFC规范的理解
- java 路径获取文件名称_java 根据文件获取文件名及路径的方法
- 支付宝「集五福」的阳谋
- 阿里二面:怎么解决MySQL死锁问题的?
- 打不开baidu晓得、百科等可是其他网页正常的解决方法
- 提交注册信息到数据库中
- 机器人周志_机器人制造基础学习日志
- 职场 软件实施工程师的地位以及发展前景
- 华中科技大学计算机考研信息汇总
- usb网卡带宽测试软件,腾达AC9与网件R6220无线性能和USB速度测试
- 磨刀不误砍柴工,掌握DEVC++的一些实用技巧
- 《JavaScript百炼成仙》 全书知识点整理
- 免费影视资源如何引流?如何通过分享影视资源引流
- 手工去除酷我音乐盒广告
- C51——简单的防盗报警器
- 记录自己学习尚硅谷javaweb2022版中遇到的一些问题
- 使用Go+WebSocket练习总结