MPU6500调试

作者回顾接触单片机一年的经历,决定重新学习MPU6500。文章介绍了MPU6500的通讯方式,包括I2C和SPI,重点学习普通SPI模式;阐述了其定义,如引脚、框架和寄存器;还讲述因开发板问题使用GPIO模拟SPI通讯,并给出相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

一、MPU6500通讯方式

1.I2C通讯

2.SPI通讯

二、MPU6500定义

1.引脚

2.框架

3.寄存器


前言

还记得刚学习单片机,内心兴奋像打开了新世界大门,一股脑买了很多电子垃圾,其中MPU6500就是其中一个。回头看接触单片机也算1年了,现在每天除了完成工作任务能力并没有长进,真是愧对之前的一腔热血,故今日从新学习。

一、MPU6500通讯方式

1.I2C通讯

 根据手册说明MPU6500支持最大400KHz波特率I2C通讯,但这次重点学习SPI操作方式,后续再对I2C进行学习,未完待续…… 

2.SPI通讯

手册中介绍了2种SPI通讯方式,普通SPI操作方式最大支持1MHz波特率通讯,另有中断SPI通讯最高通讯速率可以高达20M,目前仅对普通模式进行学习。目前手里图便宜买的开发板,硬件SPI为引出只能使用软件模拟SPI通讯,软件模拟SPI通讯极限速度在1MHz左右(目前基于F407测试)。

SPI读取和写入操作在16个或更多时钟周期(两个或更多字节)中完成,这个第一个字节包含SPI地址,随后的字节包含SPI数据。第一个第一个字节的位包含读/写位,并指示读(1)或写(0)操作。以下7位包含寄存器地址。在多字节读/写的情况下,数据是两个或多个字节:

二、MPU6500定义

1.引脚

我们这里使用的SPI通讯:

 Pin_23:SCL/SCLK(SPI_CLK)

 Pin_24:SDA/SDI(SPI_MOSI)

 Pin_22:nCS(SPI_CS)

 Pin_9-11:AOD/SDO(SPI_MISO)

 接线如下图(魔性涂鸦):

2.框架

这里留意FSYNC引脚,未使用要连接GND,反正手册这么写,后续验证:

 3.寄存器

 MPU6500寄存器总Map表如下图:

以下列举一些重要寄存器:

  • 陀螺仪偏移寄存器: 

注意XYZ的大小端,不知道官方为啥这样设计,目前看来挺反常理;

  • 采样率寄存器: 

这里可以理解为寄存器刷新速率,可能芯片内部是一定采样率,但是外部串行寄存器刷新速率需要配置,该寄存器需要配合CONGIG寄存器一起使用;

  • 配置寄存器 

 感觉FIFO_MODE最重要吧,这里感觉允许数据覆盖可能更符合大多数使用场景;

先写道这里TODO……

三、驱动

1.模拟SPI 

由于图便宜买的开发板实在垃圾,各种通讯口均未引出,故只能使用GPIO模拟SPI通讯,经测试波特率700Khz左右,只需要定义以下GPIO口即可使用,方便多路同时使用,详见以下代码,水平有限欢迎指点;

  • 构造模拟SPI通讯口(ST_CLASS_SPIX stSpix)
  • 初始化SPI
  • 通讯函数
#include "SPIX.h"


bool SPIX_TransData(ST_CLASS_SPIX* stSpi,unsigned char* u8TxDataBuffer,unsigned short u16TxLength,unsigned char* u8RxDataBuffer,unsigned short u16RxLength);
bool SPIX_ReceiveData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length);
bool SPIX_SendData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length);
void SPIX_Ready(ST_CLASS_SPIX* stSpi);
unsigned char SPIX_WriteReadByte_Mode1(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData);
unsigned char SPIX_WriteReadByte_Mode2(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData);
unsigned char SPIX_WriteReadByte_Mode3(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData);
unsigned char SPIX_WriteReadByte_Mode4(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData);
unsigned char SPIX_WriteReadByte(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData);

/*********************************************************************
* 函数描述:初始化SPI
* 输入说明:
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
void SPIX_GpioInit(ST_CLASS_SPIX* stSpi)
{
	GPIO_InitTypeDef GPIO_InitStruct = {0};

	__HAL_RCC_GPIOE_CLK_ENABLE();
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOH_CLK_ENABLE();
	__HAL_RCC_GPIOB_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();
	__HAL_RCC_GPIOD_CLK_ENABLE();

	/*Configure GPIO pins : SPIX_CLK_Pin*/
	GPIO_InitStruct.Pin = stSpi->stSpiGpio_CLK.GPIO_Pin_x;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(stSpi->stSpiGpio_CLK.GPIOx, &GPIO_InitStruct);

	/*Configure GPIO pins : SPIX_CS_Pin*/
	GPIO_InitStruct.Pin = stSpi->stSpiGpio_CS.GPIO_Pin_x;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(stSpi->stSpiGpio_CS.GPIOx, &GPIO_InitStruct);

	/*Configure GPIO pins : SPIX_MOSI_Pin */
	GPIO_InitStruct.Pin = stSpi->stSpiGpio_MOSI.GPIO_Pin_x;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	HAL_GPIO_Init(stSpi->stSpiGpio_MOSI.GPIOx, &GPIO_InitStruct);

	/*Configure GPIO pin : SPIX_MISO_Pin */
	GPIO_InitStruct.Pin = stSpi->stSpiGpio_MISO.GPIO_Pin_x;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(stSpi->stSpiGpio_MISO.GPIOx,&GPIO_InitStruct);

	/*Configure GPIO pin Output Level */
	HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_RESET);
	HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_SET);
}
/*********************************************************************
* 函数描述:模拟SPI发送固定数据接收固定数据
* 输入说明:每次最大发送接收256Byte
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
bool SPIX_TransData(ST_CLASS_SPIX* stSpi,unsigned char* u8TxDataBuffer,unsigned short u16TxLength,unsigned char* u8RxDataBuffer,unsigned short u16RxLength)
{
	bool blOutVal = true;
	unsigned short u16Cnt;
	unsigned char u8DataBuffer[256];
	if((u16TxLength > 256) || (u16RxLength > 256))
	{
		blOutVal = false;
	}
	else
	{
		//传输准备
		SPIX_Ready(stSpi);
		//使能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_RESET);
		//发送数据
		if(u16TxLength != 0)
		{
			//数据转存
			memcpy(u8DataBuffer,u8TxDataBuffer,u16TxLength%256);
			//发送
			for(unsigned short u16Cnt = 0;u16Cnt < u16TxLength;u16Cnt ++)
			{
				SPIX_WriteReadByte(stSpi,u8DataBuffer[u16Cnt]);
			}
		}
		if(u16RxLength != 0)
		{
			//接收
			if(u8RxDataBuffer != NULL)
			{
				for(u16Cnt = 0;u16Cnt < u16RxLength;u16Cnt ++)
				{
					u8RxDataBuffer[u16Cnt] = SPIX_WriteReadByte(stSpi,0xFF);
				}
			}
			else
			{
				blOutVal = false;
			}
		}
		//失能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_SET);
	}
	return blOutVal;
}

/*********************************************************************
* 函数描述:模拟SPI接收数据
* 输入说明:每次最大发送256Byte
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
bool SPIX_SendData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length)
{
	bool blOutVal = true;
	unsigned char u8TxDataBuffer[256];
	if(u16Length > 256)
	{
		blOutVal = false;
	}
	else
	{
		//数据转存
		memcpy(u8TxDataBuffer,u8DataBuffer,u16Length%256);
		//传输准备
		SPIX_Ready(stSpi);
		//使能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_RESET);
		//发送
		for(unsigned short u16Cnt = 0;u16Cnt < u16Length;u16Cnt ++)
		{
			SPIX_WriteReadByte(stSpi,u8TxDataBuffer[u16Cnt]);
		}
		//失能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_SET);
	}
	return blOutVal;
}
/*********************************************************************
* 函数描述:模拟SPI接收数据
* 输入说明:每次最大发送256Byte
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
bool SPIX_ReceiveData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length)
{
	bool blOutVal = true;
	unsigned char* u8RxDataBuffer = u8DataBuffer;
	if(u16Length > 256)
	{
		blOutVal = false;
	}
	else
	{
		//传输准备
		SPIX_Ready(stSpi);
		//使能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_RESET);
		//接收
		for(unsigned short u16Cnt = 0;u16Cnt < u16Length;u16Cnt ++)
		{
			u8RxDataBuffer[u16Cnt] = SPIX_WriteReadByte(stSpi,0xFF);
		}
		//失能
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CS.GPIOx,stSpi->stSpiGpio_CS.GPIO_Pin_x,GPIO_PIN_SET);
	}
	return blOutVal;
}
/*********************************************************************
* 函数描述:模拟传输一个字节函数
* 输入说明:
* 输出说明:
* 创建日期:2023-07-29
*********************************************************************/
unsigned char SPIX_WriteReadByte(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData)
{
	unsigned char u8ReadData = 0;
	switch(stSpi->enSpiMode)
	{
		case SPIX_MODE_1:
		{
			u8ReadData = SPIX_WriteReadByte_Mode1(stSpi,u8WriteData);
		}
		break;
		case SPIX_MODE_2:
		{
			u8ReadData = SPIX_WriteReadByte_Mode2(stSpi,u8WriteData);
		}
		break;
		case SPIX_MODE_3:
		{
			u8ReadData = SPIX_WriteReadByte_Mode3(stSpi,u8WriteData);
		}
		break;
		case SPIX_MODE_4:
		{
			u8ReadData = SPIX_WriteReadByte_Mode4(stSpi,u8WriteData);
		}
		break;
		default:
		{
			u8ReadData = 0xFF;
		}
		break;
	}
	return u8ReadData;
}
/*********************************************************************
* 函数描述:模拟SPIReady
* 输入说明:复位CLK(在传输过程不去复位提高传输上限速率)
* 输出说明:
* 创建日期:2023-07-29
*********************************************************************/
void SPIX_Ready(ST_CLASS_SPIX* stSpi)
{
	if((stSpi->enSpiMode == SPIX_MODE_1) || (stSpi->enSpiMode == SPIX_MODE_2))
	{
		//CLK空闲低电平
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
	}
	else
	{
		//CLK空闲高电平
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_SET);
	}
}
/*********************************************************************
* 函数描述:模拟SPI工作模式1(CPOL = 0 CPHA = 0)
* 输入说明:
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
unsigned char SPIX_WriteReadByte_Mode1(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData)
{
	unsigned char u8ReadData=0;
	unsigned char u8Cnt = 0;
	for(u8Cnt = 0;u8Cnt < 8;u8Cnt ++)
	{
		//SPI是高位bit先传输
		if(u8WriteData & 0x80)
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_RESET);
		}
		u8WriteData <<= 1;
		//CLK上升沿(采样)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_SET);
		u8ReadData <<= 1;
		if(HAL_GPIO_ReadPin(stSpi->stSpiGpio_MISO.GPIOx,stSpi->stSpiGpio_MISO.GPIO_Pin_x))
		{
			u8ReadData += 1;
		}
		//CLK下降沿(触发)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
	}
	return u8ReadData;
}
/*********************************************************************
* 函数描述:模拟SPI工作模式2(CPOL = 0 CPHA = 1)
* 输入说明:
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
unsigned char SPIX_WriteReadByte_Mode2(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData)
{
	unsigned char u8ReadData=0;
	unsigned char u8Cnt = 0;
	for(u8Cnt = 0;u8Cnt < 8;u8Cnt ++)
	{
		//CLK上升沿(触发)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_SET);
		//SPI是高位bit先传输
		if(u8WriteData & 0x80)
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_RESET);
		}
		u8WriteData <<= 1;
		//CLK下降沿(采样)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
		u8ReadData <<= 1;
		if(HAL_GPIO_ReadPin(stSpi->stSpiGpio_MISO.GPIOx,stSpi->stSpiGpio_MISO.GPIO_Pin_x))
		{
			u8ReadData += 1;
		}
	}
	return u8ReadData;
}
/*********************************************************************
* 函数描述:模拟SPI工作模式3(CPOL = 1 CPHA = 0)
* 输入说明:
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
unsigned char SPIX_WriteReadByte_Mode3(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData)
{
	unsigned char u8ReadData=0;
	unsigned char u8Cnt = 0;
	for(u8Cnt = 0;u8Cnt < 8;u8Cnt ++)
	{
		//SPI是高位bit先传输
		if(u8WriteData & 0x80)
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_RESET);
		}
		u8WriteData <<= 1;
		//CLK下降沿(采样)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
		u8ReadData <<= 1;
		if(HAL_GPIO_ReadPin(stSpi->stSpiGpio_MISO.GPIOx,stSpi->stSpiGpio_MISO.GPIO_Pin_x))
		{
			u8ReadData += 1;
		}
		//CLK上升沿(触发)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_SET);
	}
	return u8ReadData;
}
/*********************************************************************
* 函数描述:模拟SPI工作模式2(CPOL = 1 CPHA = 1)
* 输入说明:
* 输出说明:
* 创建日期:2023-07-27
*********************************************************************/
unsigned char SPIX_WriteReadByte_Mode4(ST_CLASS_SPIX* stSpi,unsigned char u8WriteData)
{
	unsigned char u8ReadData=0;
	unsigned char u8Cnt = 0;
	for(u8Cnt = 0;u8Cnt < 8;u8Cnt ++)
	{
		//CLK下降沿(触发)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_RESET);
		//SPI是高位bit先传输
		if(u8WriteData & 0x80)
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_SET);
		}
		else
		{
			HAL_GPIO_WritePin(stSpi->stSpiGpio_MOSI.GPIOx,stSpi->stSpiGpio_MOSI.GPIO_Pin_x,GPIO_PIN_RESET);
		}
		u8WriteData <<= 1;
		//CLK上升沿(采样)
		HAL_GPIO_WritePin(stSpi->stSpiGpio_CLK.GPIOx,stSpi->stSpiGpio_CLK.GPIO_Pin_x,GPIO_PIN_SET);
		u8ReadData <<= 1;
		if(HAL_GPIO_ReadPin(stSpi->stSpiGpio_MISO.GPIOx,stSpi->stSpiGpio_MISO.GPIO_Pin_x))
		{
			u8ReadData += 1;
		}
	}
	return u8ReadData;
}
#ifndef APP_SPIX_SPIX_H_
#define APP_SPIX_SPIX_H_

#include "main.h"


#define SPIX_MOSI_H HAL_GPIO_WritePin(SPIX_MOSI_GPIO_Port,SPIX_MOSI_Pin,GPIO_PIN_SET);
#define SPIX_MOSI_L HAL_GPIO_WritePin(SPIX_MOSI_GPIO_Port,SPIX_MOSI_Pin,GPIO_PIN_RESET);

#define SPIX_MISO_R HAL_GPIO_ReadPin(SPIX_MISO_GPIO_Port,SPIX_MISO_Pin)

#define SPIX_CLK_H HAL_GPIO_WritePin(SPIX_CLK_GPIO_Port,SPIX_CLK_Pin,GPIO_PIN_SET);
#define SPIX_CLK_L HAL_GPIO_WritePin(SPIX_CLK_GPIO_Port,SPIX_CLK_Pin,GPIO_PIN_RESET);

#define SPIX_CS_H HAL_GPIO_WritePin(SPIX_CS_GPIO_Port,SPIX_CS_Pin,GPIO_PIN_SET);
#define SPIX_CS_L HAL_GPIO_WritePin(SPIX_CS_GPIO_Port,SPIX_CS_Pin,GPIO_PIN_RESET);

typedef enum{
	SPIX_MODE_1,
	SPIX_MODE_2,
	SPIX_MODE_3,
	SPIX_MODE_4
}EN_SPIX_MODE;

typedef struct{
	GPIO_TypeDef* GPIOx;
	unsigned short GPIO_Pin_x;
}ST_SPIX_GPIO;

typedef struct{
	EN_SPIX_MODE enSpiMode;
	ST_SPIX_GPIO stSpiGpio_MOSI;
	ST_SPIX_GPIO stSpiGpio_MISO;
	ST_SPIX_GPIO stSpiGpio_CLK;
	ST_SPIX_GPIO stSpiGpio_CS;
}ST_CLASS_SPIX;

bool SPIX_TransData(ST_CLASS_SPIX* stSpi,unsigned char* u8TxDataBuffer,unsigned short u16TxLength,unsigned char* u8RxDataBuffer,unsigned short u16RxLength);
bool SPIX_ReceiveData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length);
bool SPIX_SendData(ST_CLASS_SPIX* stSpi,unsigned char* u8DataBuffer,unsigned short u16Length);

#endif /* APP_SPIX_SPIX_H_ */

这里套用别人初始化代码及MPU6500通讯代码,通讯没问题,如下图: 

2.

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值