大家好,欢迎来到IT知识分享网。
目录
前言
还记得刚学习单片机,内心兴奋像打开了新世界大门,一股脑买了很多电子垃圾,其中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.
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/127261.html