江科大6050移植失败小记(M0G3507/M0L1306配置6050)

#姿态解析# #代码移植#

前言:

移植代码去配置6050,移植别人的代码,总是不成功,直接诸塞在6050初始化里面,看了b站和博客大佬的代码,试了很多仍有同一个问题在移植上面,然后找大佬检查了一下,读取IIC一直卡死在里面,通过debug查看发现一直卡在延时里面,导致I6050和其他代码都寄寄。

也就是这个文件出了问题(这里的延时就是用的普通延时,没有用滴答定时器写)

#include "Delay.h"

#define TIME_FREQ       32000000

/**
  *@brief          延时函数  1S
  *@param          s    延时次数
  *@retval	       无
  */
void Delay_s(uint32_t s)
{
	while(s)
	{
		s--;
		delay_cycles(TIME_FREQ);//1s
	}
}
/**
  *@brief          延时函数  1MS
  *@param          ms    延时次数
  *@retval	       无
  */
void Delay_ms(uint32_t ms)
{
	while(ms)
	{
		ms--;
		delay_cycles(TIME_FREQ/1000);//1ms
	}
}
/**
  *@brief          延时函数  1US
  *@param          us    延时次数
  *@retval	       无
  */
void Delay_us(uint32_t us)
{
	uint32_t i;
	while(us)
	{
		delay_cycles(TIME_FREQ/1000000);//1us
	}
}

怎么说呢,其实很抽象,这个代码看起来平平无奇,乍一看确实没啥毛病奥,但是就是卡6050的延时。其实就改成最简单的版本就好了,就像下面这样。

#include "delay.h"

/**
  *@brief          延时函数  1S
  *@param          s    延时次数
  *@retval	       无
  */
void Delay_s(uint32_t s)
{
	while(s)
	{
		s--;
		delay_cycles(320000);//1s
	}
}

/**
  *@brief          延时函数  1MS
  *@param          ms    延时次数
  *@retval	       无
  */
void Delay_ms(uint32_t ms)
{
	while(ms--)
	{
		
		delay_cycles(32000);//1ms
	}
}

/**
  *@brief          延时函数  1US
  *@param          us    延时次数
  *@retval	       无
  */
void Delay_us(uint32_t us)
{
	
	while(us--)
	{
		delay_cycles(32);//1us
	}
}

代码改完后发现裸板太不行了,接线乱七八糟还容易短路,然后又画了俩板(1306和3507)

 🆗,这下前期搭建完成,代码编译,然后就能显示了,ok,搞定。

换了块G3507的版,试了一下,效果也是非常的ok!(只显示了部分值)

   

解决了这个问题之后,我又将我手上搞到的的6050程序看了一遍,发现代码大致都是差不多的,分江协和嘉立创的代码移植(嘉立创的先不列出来了,有点问题,后面再加上来)

代码(移植江科大):代码是在b站UP主奔跑到太阳升起评论区拿的,几乎不做改变,下面列出我的实际使用代码

1.mpu050.c

#include "ti_msp_dl_config.h"
#include "myi2C.h"
#include "MPU6050_Reg.h"
#include "OLED.h"
#define MPU6050_ADDRESS		0xD0		//MPU6050的I2C从机地址

/**
  * 函    数:MPU6050写寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 参    数:Data 要写入寄存器的数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{
	MyI2C_Start();						//I2C起始
	MyI2C_SendByte(MPU6050_ADDRESS);	//发送从机地址,读写位为0,表示即将写入
	MyI2C_ReceiveAck();					//接收应答
	MyI2C_SendByte(RegAddress);			//发送寄存器地址
	MyI2C_ReceiveAck();					//接收应答
	MyI2C_SendByte(Data);				//发送要写入寄存器的数据
	MyI2C_ReceiveAck();					//接收应答
	MyI2C_Stop();						//I2C终止
}

/**
  * 函    数:MPU6050读寄存器
  * 参    数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述
  * 返 回 值:读取寄存器的数据,范围:0x00~0xFF
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	  
	MyI2C_Start();						//I2C起始
	MyI2C_SendByte(MPU6050_ADDRESS);	//发送从机地址,读写位为0,表示即将写入
	
	MyI2C_ReceiveAck();					//接收应答
	MyI2C_SendByte(RegAddress);			//发送寄存器地址
	MyI2C_ReceiveAck();					//接收应答
	
	MyI2C_Start();						//I2C重复起始
	MyI2C_SendByte(MPU6050_ADDRESS | 0x01);	//发送从机地址,读写位为1,表示即将读取
	MyI2C_ReceiveAck();					//接收应答
	Data = MyI2C_ReceiveByte();			//接收指定寄存器的数据
	MyI2C_SendAck(1);					//发送应答,给从机非应答,终止从机的数据输出
	MyI2C_Stop();						//I2C终止

	return Data;
}

/**
  * 函    数:MPU6050初始化
  * 参    数:无
  * 返 回 值:无
  */
void MPU6050_Init(void)
{
	MyI2C_Init();									//先初始化底层的I2C
	
	/*MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器*/
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);		//电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);		//电源管理寄存器2,保持默认值0,所有轴均不待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);		//采样率分频寄存器,配置采样率
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);			//配置寄存器,配置DLPF
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);	//陀螺仪配置寄存器,选择满量程为±2000°/s
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);	//加速度计配置寄存器,选择满量程为±16g
	OLED_ShowString(2, 5,"2");
}

/**
  * 函    数:MPU6050获取ID号
  * 参    数:无
  * 返 回 值:MPU6050的ID号
  */
uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);		//返回WHO_AM_I寄存器的值
}

/**
  * 函    数:MPU6050获取数据
  * 参    数:AccX AccY AccZ 加速度计X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 参    数:GyroX GyroY GyroZ 陀螺仪X、Y、Z轴的数据,使用输出参数的形式返回,范围:-32768~32767
  * 返 回 值:无
  */
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
	uint8_t DataH, DataL;								//定义数据高8位和低8位的变量
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);		//读取加速度计X轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);		//读取加速度计X轴的低8位数据
	*AccX = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);		//读取加速度计Y轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);		//读取加速度计Y轴的低8位数据
	*AccY = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);		//读取加速度计Z轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);		//读取加速度计Z轴的低8位数据
	*AccZ = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);		//读取陀螺仪X轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);		//读取陀螺仪X轴的低8位数据
	*GyroX = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);		//读取陀螺仪Y轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);		//读取陀螺仪Y轴的低8位数据
	*GyroY = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);		//读取陀螺仪Z轴的高8位数据
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);		//读取陀螺仪Z轴的低8位数据
	*GyroZ = (DataH << 8) | DataL;						//数据拼接,通过输出参数返回
}

2.mpu6050.h

#ifndef __MPU6050_H
#define __MPU6050_H
#include "myi2C.h"
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);

#endif

3.mpu6050——reg.h

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H

#define	MPU6050_SMPLRT_DIV		0x19
#define	MPU6050_CONFIG			0x1A
#define	MPU6050_GYRO_CONFIG		0x1B
#define	MPU6050_ACCEL_CONFIG	0x1C

#define	MPU6050_ACCEL_XOUT_H	0x3B
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

#define	MPU6050_PWR_MGMT_1		0x6B
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

#endif

4.myiic.c

#include "ti_msp_dl_config.h"
#include "delay.h"
#include "OLED.h"
#include "ti/driverlib/dl_gpio.h"
//打开SDA引脚(输出)
void SDA_OUT(void)   
{
    DL_GPIO_initDigitalOutput(MPU6050_SDA_IOMUX);     
	DL_GPIO_setPins(MPU6050_PORT, MPU6050_SDA_PIN);	   
    DL_GPIO_enableOutput(MPU6050_PORT, MPU6050_SDA_PIN); 
}
//关闭SDA引脚(输入)
void SDA_IN(void)
{

    DL_GPIO_initDigitalInputFeatures(MPU6050_SDA_IOMUX,
		 DL_GPIO_INVERSION_DISABLE, DL_GPIO_RESISTOR_PULL_UP,
		 DL_GPIO_HYSTERESIS_DISABLE, DL_GPIO_WAKEUP_DISABLE);


}



/**
  * 函    数:I2C写SCL引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SCL的电平,范围0~1
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SCL为低电平,当BitValue为1时,需要置SCL为高电平
  */
void MyI2C_W_SCL(uint8_t BitValue)
{
    if(BitValue)
        DL_GPIO_setPins(MPU6050_PORT , MPU6050_SCL_PIN );
    else
        DL_GPIO_clearPins(MPU6050_PORT , MPU6050_SCL_PIN );
	Delay_us(5);	//延时8us,防止时序频率超过要求
}

/**
  * 函    数:I2C写SDA引脚电平
  * 参    数:BitValue 协议层传入的当前需要写入SDA的电平,范围0~0xFF
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SDA为低电平,当BitValue非0时,需要置SDA为高电平
  */
void MyI2C_W_SDA(uint8_t BitValue)
{
    SDA_OUT();
    if(BitValue)
        DL_GPIO_setPins(MPU6050_PORT , MPU6050_SDA_PIN );
    else
        DL_GPIO_clearPins(MPU6050_PORT , MPU6050_SDA_PIN );
	Delay_us(5);					//延时8us,防止时序频率超过要求
}

/**
  * 函    数:I2C读SDA引脚电平
  * 参    数:无
  * 返 回 值:协议层需要得到的当前SDA的电平,范围0~1
  * 注意事项:此函数需要用户实现内容,当前SDA为低电平时,返回0,当前SDA为高电平时,返回1
  */
uint8_t MyI2C_R_SDA(void)
{
	uint8_t b;
    uint32_t BitValue;
    SDA_IN();
	BitValue = DL_GPIO_readPins(MPU6050_PORT ,MPU6050_SDA_PIN );		//读取SDA电平
    {
        if(BitValue)   b=1;
        else           b=0;
    }
	Delay_us(5);		//延时8us,防止时序频率超过要求
	return b;	        //返回SDA电平
}

/**
  * 函    数:I2C初始化
  * 参    数:无
  * 返 回 值:无
  * 注意事项:此函数需要用户实现内容,实现SCL和SDA引脚的初始化
  */
void MyI2C_Init(void)
{
    SYSCFG_DL_GPIO_init();
	/*设置默认电平*/
	DL_GPIO_setPins(MPU6050_PORT , MPU6050_SDA_PIN  |
		MPU6050_SCL_PIN );//设置PA8和PA9引脚初始化后默认为高电平(释放总线状态)
	 OLED_ShowString(2, 2,"1");//能进去
}

/*协议层*/

/**
  * 函    数:I2C起始
  * 参    数:无
  * 返 回 值:无
  */
void MyI2C_Start(void)
{
    SDA_OUT();
	MyI2C_W_SDA(1);				//释放SDA,确保SDA为高电平
	MyI2C_W_SCL(1);				//释放SCL,确保SCL为高电平
	MyI2C_W_SDA(0);				//在SCL高电平期间,拉低SDA,产生起始信号
	MyI2C_W_SCL(0);				//起始后拉低SCL,为了占用总线,方便总线时序的拼接
}

/**
  * 函    数:I2C终止
  * 参    数:无
  * 返 回 值:无
  */
void MyI2C_Stop(void)
{
    SDA_OUT();
	MyI2C_W_SDA(0);							//拉低SDA,确保SDA为低电平
	MyI2C_W_SCL(1);							//释放SCL,使SCL呈现高电平
	MyI2C_W_SDA(1);							//在SCL高电平期间,释放SDA,产生终止信号
}

/**
  * 函    数:I2C发送一个字节
  * 参    数:Byte 要发送的一个字节数据,范围:0x00~0xFF
  * 返 回 值:无
  */
void MyI2C_SendByte(uint8_t Byte)
{
    SDA_OUT();
	uint8_t i;
	for (i = 0; i < 8; i ++)				//循环8次,主机依次发送数据的每一位
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));	//使用掩码的方式取出Byte的指定一位数据并写入到SDA线
		MyI2C_W_SCL(1);						//释放SCL,从机在SCL高电平期间读取SDA
		MyI2C_W_SCL(0);						//拉低SCL,主机开始发送下一位数据
	}
}

/**
  * 函    数:I2C接收一个字节
  * 参    数:无
  * 返 回 值:接收到的一个字节数据,范围:0x00~0xFF
  */
uint8_t MyI2C_ReceiveByte(void)
{
    SDA_OUT();
	uint8_t i, Byte = 0x00;	//定义接收的数据,并赋初值0x00
	MyI2C_W_SDA(1);			//接收前,主机先确保释放SDA,避免干扰从机的数据发送
	for (i = 0; i < 8; i ++)	//循环8次,主机依次接收数据的每一位
	{
        SDA_IN();
		MyI2C_W_SCL(1);						//释放SCL,主机机在SCL高电平期间读取SDA
		if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}	//读取SDA数据,并存储到Byte变量
	//当SDA为1时,置变量指定位为1,当SDA为0时,不做处理,指定位为默认的初值0
		MyI2C_W_SCL(0);						//拉低SCL,从机在SCL低电平期间写入SDA
	}
	return Byte;							//返回接收到的一个字节数据
}

/**
  * 函    数:I2C发送应答位
  * 参    数:Byte 要发送的应答位,范围:0~1,0表示应答,1表示非应答
  * 返 回 值:无
  */
void MyI2C_SendAck(uint8_t AckBit)
{
    SDA_OUT();
	MyI2C_W_SDA(AckBit);					//主机把应答位数据放到SDA线
	MyI2C_W_SCL(1);							//释放SCL,从机在SCL高电平期间,读取应答位
	MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块
}

/**
  * 函    数:I2C接收应答位
  * 参    数:无
  * 返 回 值:接收到的应答位,范围:0~1,0表示应答,1表示非应答
  */
uint8_t MyI2C_ReceiveAck(void)
{
    SDA_OUT();
	uint8_t AckBit;							//定义应答位变量
	MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送
	MyI2C_W_SCL(1);							//释放SCL,主机机在SCL高电平期间读取SDA
    SDA_IN();
	AckBit = MyI2C_R_SDA();					//将应答位存储到变量里
	MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块
	return AckBit;							//返回定义应答位变量
}

5.myiic.h

#ifndef __MYI2C_H
#define __MYI2C_H
#include "stdint.h"

void MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_R_SDA(void);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);
void MyI2C_W_SCL(uint8_t BitValue);
void MyI2C_W_SDA(uint8_t BitValue);


#endif

6.main.c

#include "OLED.h"
#include "ti_msp_dl_config.h"
#include "delay.h"
#include "LED.h"
#include "bluetooth.h"
#include "stdio.h"
#include "mpu6050.h"
int16_t AccX,AccY,AccZ,GyroX,GyroY,GyroZ;
				 int main(void)
				{

								SYSCFG_DL_init();
								OLED_Init();
								OLED_CLS();
								bluetooth_Init();
								 
               

                               //这几个是字模显示,记得屏蔽
								OLED_ShowChinese(1,16*4,2);//学
							    OLED_ShowChinese(1,16*5,3);//习
								OLED_ShowChinese(1,16*6,4);//中
								OLED_ShowChinese(1,16*7,5);//,
					            OLED_ShowChinese(3,16*4,7);//勿
								OLED_ShowChinese(3,16*5,8);//打
								OLED_ShowChinese(3,16*6,9);//扰
								//有需要字模的相关代码,可以找我要
								MPU6050_Init();
					
													
									while (1)
										{
	                                                                                                                                                                                         
                                Delay_ms(1);//根据设置的采样率,不可设置延时过大

				MPU6050_GetData(&AccX,&AccY,&AccZ,&GyroX,&GyroY,&GyroZ);
                OLED_ShowString(2,1,"cX:"); 
			    OLED_ShowString(3,1,"cY:");
				OLED_ShowString(4,1,"cZ:"); 
				OLED_ShowString(2,9,"oX:"); 
			    OLED_ShowString(3,9,"oY:");
				OLED_ShowString(4,9,"oZ:"); 
				OLED_ShowSignedNum(2,4,AccX,4);OLED_ShowSignedNum(2,12,GyroX,4);
				OLED_ShowSignedNum(3,4,AccY,4);OLED_ShowSignedNum(3,12,GyroY,4);
				OLED_ShowSignedNum(4,4,AccZ,4);OLED_ShowSignedNum(4,12,GyroY,4);											


											
								   	}
			    	}
				

看了一下其他的几个代码,江科大的较于嘉立创写的简单一些,一下就成了,要是自己配制的没问题的话。

接着继续在搞嘉立创的6050移值,有一点点的小问题如果有大佬看到了,希望可以指点一二

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
江科大自化协软件模拟I2C读写MPU6050的过程可以分为两个主要步骤。首先,需要学习I2C协议规则,并使用软件模拟的方式实现协议。这包括了了解I2C协议的引脚配置、时序要求等相关内容。其次,需要学习STM32的I2C外设,并使用硬件实现协议。这一步骤可以进一步学习STM32的I2C外设和协议的硬件实现方式。\[1\]\[2\] 在软件模拟I2C读写MPU6050的过程中,可以采用多层的模块架构。最底层是I2C协议层,主要关注引脚配置、时序要求等与协议相关的内容。其次是MPU6050的驱动层,主要关注如何读写寄存器、配置寄存器以及读取数据等与驱动相关的内容。最后是主函数应用层,通过调用MPU6050的驱动函数获取数据,并根据需要进行进一步的功能设计。\[3\] 因此,江科大自化协软件模拟I2C读写MPU6050的过程包括学习I2C协议规则、软件模拟实现协议,以及学习STM32的I2C外设并使用硬件实现协议。在软件模拟过程中,需要关注引脚配置、时序要求等与协议相关的内容。在硬件实现过程中,需要学习STM32的I2C外设和协议的硬件实现方式。最后,通过多层的模块架构,实现对MPU6050的读写操作,并根据需要进行进一步的功能设计。 #### 引用[.reference_title] - *1* *2* *3* [【STM32学习】——I2C通信协议&MPU6050姿态传感器&软件I2C读写MPU6050](https://blog.csdn.net/weixin_51658186/article/details/129821841)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值