前言
使用的开发软件为STM32CubeIDE,主控是STM32F103C8T6。前后用了两个GY-91模块才弄成,第一个GY-91模块挂羊头卖狗肉,读取WHO_AM_I寄存器的时候发现值是0x70,而MPU9250的WHO_AM_I寄存器的值是0x71或者0x73。查资料以后发现MPU6500的WHO_AM_I寄存器的值才是0x70,所以第一个模块也不可能读到磁力计的数据,因为MPU6500内部没有AK8963磁力计连接,为此我还困扰了好几天,换成新的总算是可以了。
希望大家在买模块或者芯片的时候擦亮眼睛,不要买到抹掉丝印的翻新货。
硬件配置
使用STM32CubeIDE进行配置如下所示
GPIO配置
使用SPI1和USART1,SPI1连接MPU9250,USART1用作DEBUG调试信息输出。另外,在使用STM32CubeMX配置的时候,一定要记得配置System Core/SYS里的Debug选项,使用JTAG就配置为JTAG,使用SWD就配置为Serial Wire,不然是不能下载和调试的。
SPI配置
这里我没有去测试SPI最高速度能到多少,有兴趣的朋友可以试试。
硬件连接
参照下表
MCU | MPU9250 |
---|---|
MISO | SDA |
MOSI | SDO |
SCK | SCL |
PB10(CS) | nCS |
nCS表示低电平选中
参考
https://github.com/desertkun/MPU9250
https://blog.csdn.net/liuyifanliu/article/details/99309839
以上两个方案第一个是用HAL库写的,第二个使用标准库写的,主要参考其中对寄存器的读写。其中第一个方案在读取AK8963时没有读取ST2寄存器,可能会导致读不出数据,也可能因为某些原因读不出陀螺仪的数据,第二个我没有做调试,这边就不再赘述这两个方案了。
文档
应当可以在网络上找到产品说明和寄存器说明两个文档,如果找不到,我也已经在文章末尾放上了我自己的Github仓库链接也可以在里面找到这两个文档,主要开发过程就靠这两个文档支撑。
代码及说明
代码
代码如下,大部分说明会以注释的方式在代码中呈现
mpu9250.h
#ifndef __MPU9250_H
#define __MPU9250_H
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "spi.h"
#include <stdlib.h>
#define MPU9250_CS_GPIO GY_CS_GPIO_Port
#define MPU9250_CS_PIN GY_CS_Pin
#define MPU9250_SPI hspi1
#define MPU9250_TIMEOUT_S 0x0100
#define MPU9250_TIMEOUT_L 0x1000
// MPU9250 registers
#define SMPLRT_DIV (uint8_t)0x19
#define CONFIG (uint8_t)0x1A
#define GYRO_CONFIG (uint8_t)0x1B
#define ACCEL_CONFIG (uint8_t)0x1C
#define ACCEL_CONFIG_2 (uint8_t)0x1D
#define INT_PIN_CFG (uint8_t)0x37
#define USER_CTRL (uint8_t)0x6a
#define I2C_MST_CTRL (uint8_t)0x24
#define I2C_MST_DELAY_CTRL (uint8_t)0x67
//--------------------i2c slv0-------------------------------//
#define I2C_SLV0_ADDR (uint8_t)0x25
#define I2C_SLV0_REG (uint8_t)0x26
#define I2C_SLV0_CTRL (uint8_t)0x27
#define I2C_SLV0_DO (uint8_t)0x63 //output reg
//--------------------AK8963 reg addr------------------------//
#define AK8963_I2C_ADDR (uint8_t)0x0C //AKM addr
#define AK8963_WHOAMI_REG (uint8_t)0x00 //AKM ID addr
#define AK8963_WHOAMI_ID (uint8_t)0x48 //ID
#define AK8963_ST1_REG (uint8_t)0x02 //Data Status1
#define AK8963_ST2_REG (uint8_t)0x09 //Data reading end register & check Magnetic sensor overflow occurred
#define AK8963_ST1_DOR (uint8_t)0x02
#define AK8963_ST1_DRDY (uint8_t)0x01 //Data Ready
#define AK8963_ST2_BITM (uint8_t)0x10
#define AK8963_ST2_HOFL (uint8_t)0x08 // Magnetic sensor overflow
#define AK8963_CNTL1_REG (uint8_t)0x0A
#define AK8963_CNTL2_REG (uint8_t)0x0B
#define AK8963_CNTL2_SRST (uint8_t)0x01 //soft Reset
#define AK8963_ASAX (uint8_t)0x10 //X-axis sensitivity adjustment value
#define AK8963_ASAY (uint8_t)0x11 //Y-axis sensitivity adjustment value
#define AK8963_ASAZ (uint8_t)0x12 //Z-axis sensitivity adjustment value
//--------------------9axis reg addr-----------------------//
#define ACCEL_XOUT_H (uint8_t)0x3B
#define ACCEL_XOUT_L (uint8_t)0x3C
#define ACCEL_YOUT_H (uint8_t)0x3D
#define ACCEL_YOUT_L (uint8_t)0x3E
#define ACCEL_ZOUT_H (uint8_t)0x3F
#define ACCEL_ZOUT_L (uint8_t)0x40
#define TEMP_OUT_H (uint8_t)0x41 //temperture
#define TEMP_OUT_L (uint8_t)0x42
#define GYRO_XOUT_H (uint8_t)0x43
#define GYRO_XOUT_L (uint8_t)0x44
#define GYRO_YOUT_H (uint8_t)0x45
#define GYRO_YOUT_L (uint8_t)0x46
#define GYRO_ZOUT_H (uint8_t