一、MPU6500基本功能简介
MPU-6500是一个6轴运动跟踪设备,它结合了一个3轴陀螺仪、3轴加速度计和一个数字运动处理器与设备的所有寄存器通信使用I2C在400kHz或SPI在1MHz执行。设备的所有寄存器通信使用I2C在400kHz或SPI在1MHz执行。(具体介绍在MPU6500产品规格介绍中有,我就不手动翻译了)
二、Cubemax配置
这里我使用的是STM32F427IHx,进入CubeMAX配置时钟树,主频率168MHz。
然后开启SPI5与MPU6500进行通讯,SPI模式使用双线全双工模式,帧格式Motorola,、数据帧大小为8Bit、高位数据在前、分频因子为128分频、CPOL为高电平、在偶数边沿采集数据。
根据编译手册SPI5寄存器地址可知SPI5挂在APB2总线下,配置波特率buad=84MHz(APB2主频)/128(分频倍率)=656.25KBits/s。因为MPU6500的SPI接收在1MHz内,所以分频后要小于1M(buad=84MHz(APB2主频)/64(分频倍率)=1.3125MBits/s)
SPI有四种模式,根据MPU6500的SPI时序图知,SCLK空闲时为高电平,数据在第二个跳变沿采集(上升沿)。所以我这里使用的是CPHA=1,CPOL=1模式。
如果将 CPHA(时钟相位)位置 1,则 SCK 引脚上的第二个边沿(如果复位 CPOL 位,则为下降沿;如果将 CPOL 位置 1,则为上升沿)对 MSBit 采样。即,在第二个时钟边沿锁存数据。如果复位 CPHA 位,则 SCK 引脚上的第一个边沿(如果将 CPOL 位置 1,则为下降 沿;如果复位 CPOL 位,则为上升沿)对 MSBit 采样。即,在第一个时钟边沿锁存数据。 CPOL(时钟极性)和 CPHA(时钟相位)位的组合用于选择数据捕获时钟边沿。
手册里写的不易理解,我使用了广漠飘羽的SPI四种模式讲解,链接如下
https://www.cnblogs.com/gmpy/p/12461461.html
这里注意在SPI定义时候NSS线需要通过根据接线定义。按照硬件我定义NSS的是PF6引脚,我的PF6引脚使用推挽输出,无上拉下拉。
三、程序
在Cubemax配置完成就可以直接生成程序,SPI的配置我们不用改。
接下来经行命令发送和数据的读取,根据MPU6500产品手册,需要发数据两个或多个8位字节。在需要书写命令时候要将第一位第一个字节置0(reg&0x7F)。需要读取数据的时候要将第一位第一个字节置1(reg | 0x80)。
//MPU6500单次写命令
uint8_t mpu_write_byte(uint8_t const reg, uint8_t const data)
{
MPU_NSS_LOW; //开始通讯
tx = reg & 0x7F; //使第一位为0(写模式)
HAL_SPI_TransmitReceive(&MPU_HSPI, &tx, &rx, 1, 55); //写入命令地址
tx = data;
HAL_SPI_TransmitReceive(&MPU_HSPI, &tx, &rx, 1, 55); //写入数据
MPU_NSS_HIGH; //结束通讯
return 0;
}
//MPU6500单次读取单字节数据
uint8_t mpu_read_byte(uint8_t const reg)
{
MPU_NSS_LOW;
tx = reg | 0x80; //使地址第一位为1(读模式)
HAL_SPI_TransmitReceive(&MPU_HSPI, &tx, &rx, 1, 55); //写入需要读取的地址
HAL_SPI_TransmitReceive(&MPU_HSPI, &tx, &rx, 1, 55); //为读取的数据提供存储空间
MPU_NSS_HIGH;
return rx;
}
注意每次通讯NSS拉低开始通讯,拉高结束通讯。
接下来进行MPU6500初始化函数的书写
uint8_t mpu_device_init(void)
{
HAL_Delay(100);
id = mpu_read_byte(MPU6500_WHO_AM_I);
uint8_t i = 0;
uint8_t MPU6500_Init_Data[10][2] = {{ MPU6500_PWR_MGMT_1, 0x80 }, /* 重置设备*/
{ MPU6500_PWR_MGMT_1, 0x03 }, /* 陀螺仪时钟源设置 */
{ MPU6500_PWR_MGMT_2, 0x00 }, /* 启动 Acc & Gyro */
{ MPU6500_CONFIG, 0x04 }, /* 低通滤波 频率41Hz */
{ MPU6500_GYRO_CONFIG, 0x18 }, /* +-2000dps */
{ MPU6500_ACCEL_CONFIG, 0x10 }, /* +-8G */
{ MPU6500_ACCEL_CONFIG_2, 0x02 }, /* 使能低通滤波器 设置 Acc 低通滤波 */
{ MPU6500_USER_CTRL, 0x20 },}; /* 使能 AUX */
for (i = 0; i < 10; i++)
{
mpu_write_byte(MPU6500_Init_Data[i][0], MPU6500_Init_Data[i][1]);
HAL_Delay(1);
}
mpu_set_gyro_fsr(3);
mpu_set_accel_fsr(2);
ist8310_init();
mpu_offset_call();
return 0;
}
后续还有MPU6500原始数据转换成四元数,由于篇幅问题,我放到下一期。
第一次发表,经验不足,如有错误恳请广大网友指出。