一、前言

        MPU6500为MPU6050的更新产品,其中MPU6050仅支持IIC通信,而MPU6500不仅支持IIC,还支持SPI通信,而SPI相较于IIC能提供更高的数据传输速率。该陀螺仪具有±250、±500、±1000和±2000度/秒的可编程满量程范围和0.01 dps/kHz时的极低速率噪声。加速度计范围为±2g、±4g、± 8 g和± 16 g。有可编程数字滤波器、-40 ° C至85°C范围内1%漂移的精密时钟、嵌入式温度传感器和可编程中断。该器件具有IC和SPI串行接口,VDD工作范围为1.71至3.6V,以及独立的数字IO电源,VDDIO范围为1.71 V至3.6V。与器件所有寄存器的通信使用400 kHz的I C或1 MHz的SPI进行。对于需要更快通信的应用,传感器和中断寄存器可以使用SPI以20 MHz通信。而本文将介绍如何使用这款芯片。

二、MPU6500的介绍

2.1 时序介绍

        从时序图可以看见,SCLK空闲时为高电平,其低电平时数据改变,高电平时读取数据(下降沿移出,上升沿移入),故SPI的模式为模式三:CPOL=1、CPHA=1。

2.2 原理图介绍

        其中(a)图为IIC时序,(b)图为SPI时序。

三、相关寄存器的介绍

这部分可以先略过,先看下边的代码编写再看此寄存器去理解代码。

3.1  PWR_MGMT_1(电源管理 1:0X6B)

主要是在初始化中用得到,比如初始化代码会先在最高位写入1来恢复默认设置,然后再写入0x00来唤醒MCU。

3.2 PWR_MGMT_2(电源管理 2:0X6C)

其中第[7:6]是设置唤醒频率用的(一般用不上),使用条件为:

(i) Set CYCLE bit to 1                                        将 CYCLE 位设置为 1
(ii) Set SLEEP bit to 0                                        将 SLEEP 位设置为 0
(iii) Set TEMP_DIS bit to 1                                将 TEMP_DIS 位设置为 1
(iv) Set DIS_XG, DIS_YG, DIS_ZG bits to 1     将 DIS_XG、DIS_YG DIS_ZG 位设置为 1

其中步骤 (i) 到(iii)中提到的位可以在PWR_MGMT_1寄存器中找到,在此模式下,设备将关闭除主 I C 接口之外的所有设备,仅以固定间隔唤醒加速度计以进行一次测量。唤醒频率可以通过 LP_WAKE_CTRL 进行配置,如下所示。

                                        

在初始化函数中我们一般将此寄存器都设置为0。

3.3 User Control(用户控制:0X6A)

用于设置一些相关参数,如设置为0X11:置于SPI模式以及重置路径。

3.4 Accelerometer Configuration 2 (加速度计配置 2:0X1D)

其原理可以不用管,主要是设置加速度计数据速率和带宽,想了解的可以自己去查阅数据手册。我们初始化中配置为0x03。

3.5 Interrupt Enable(中断使能:0X38)

此寄存器为中断使能引脚,我们一般只使能运动中断,也就是设置为0X40。

3.6 Accelerometer Interrupt Control(加速度计中断控制:0X69)

主要是启用Accel硬件智能,初始化为0xC0。

3.7  Low Power Accelerometer ODR Contro(低功耗加速度计 ODR 控制:0X1E)

主要是设置唤醒频率

3.8 Wake-on Motion Threshold(唤醒运动阈值:0X1F)

3.9 WHOAMI(我是谁:0X75)

我们使用的SPI通信,所以读这个寄存器正确的值应该为0x70。

3.10 FIFO Enable(FIFO使能寄存器:0X23)

3.11 INT Pin / Bypass Enable Configuration(INT 引脚/旁路使能配置:0X37)

3.12 Sample Rate Divider(采样率分频器:0X19)

数据应以或更高的采样率进行采样;SMPLRT_DIV仅用于 1kHz 内部采样。

3.13 Configuration (配置寄存器:0X1A)

    

用于配置FIFO以及设置陀螺仪滤波频率,初始化中配置为0X03。主要是依据你的滤波频率决定        

3.14 Gyroscope Configuration(陀螺仪配置寄存器:0X1B)

3.15 Accelerometer Configuration(加速度计配置:0X1C)

        

四、读取MPU6500加速度值以及陀螺值

4.1  CubeMx的配置

这里就不介绍下载口以及时钟的配置了,我设置的时钟为84MHz。

        至于为什么分频倍率选择128,这里的分频倍率可以选2、4、8、16、32、64、128、256,由于MPU6500的SPI最大速度为1MHz,如果选64分频肯定会超过这个速度,84MHz/64=1.3125MHz,故选用128分频。当然,如果你系统时钟是另一个频率可以按照这个去选最优分频倍率。当然不要忘了使能引脚NSS的初始化,配置为输出模式,然后配置串口,可以参考我的另一篇文章:串口配置,然后生成工程。        

4.2 代码的编写

在之前先定义两个全局变量用于SPI的数据交换

uint8_t mpu_tx,mpu_rx;//用于数据的发送交换

4.2.1 写函数

/***** 写入一个字节的数据 *****/
uint8_t mpu_write_byte(uint8_t const reg,uint8_t const data)
{
    MPU_CS(0);//开始通信
    mpu_tx = reg & 0x7F;//使第一位为0,写模式
    HAL_SPI_TransmitReceive(&hspi1,&mpu_tx,&mpu_rx,1,55);//写入命令地址
    mpu_tx = data;
    HAL_SPI_TransmitReceive(&hspi1,&mpu_tx,&mpu_rx,1,55);//写入数据
    MPU_CS(1);//结束通信
    return 0;
}

4.2.2 读函数

/***** 读取一个字节的数据 *****/
uint8_t mpu_read_byte(uint8_t const reg)
{
    MPU_CS(0);//开始通信
    mpu_tx = reg | 0x80;//使第一位为1,读模式
    HAL_SPI_TransmitReceive(&hspi1,&mpu_tx,&mpu_rx,1,55);//写入读取地址
    HAL_SPI_TransmitReceive(&hspi1,&mpu_tx,&mpu_rx,1,55);//为读取的数据提供存储空间
    MPU_CS(1);//结束通信
    return mpu_rx;
}

4.3 MPU6500的初始化

4.3.1 MPU6500初始化流程图

      

4.3.2 MPU6050的初始化

uint8_t MPU6500_Init(void)
{
    uint8_t res = 0;
    mpu_write_byte(MPU_PWR_MGMT1_REG,0x80);//重置内部寄存器并恢复默认设置
    mpu_delay(100);
    mpu_write_byte(MPU_PWR_MGMT1_REG,0x00);	//解除休眠状态
    mpu_delay(100);
    mpu_write_byte(MPU_USER_CTRL_REG,0x11);//设置为SPI通信
    mpu_delay(10);
    res = mpu_read_byte(MPU_DEVICE_ID_REG);//读取ID号
    if(res==MPU6500_ID)//ID号正确
    {
        mpu_write_byte(MPU_PWR_MGMT2_REG,0x00);//打开加速度计以及陀螺仪
        mpu_delay(10);
        
        mpu_write_byte(MPU_GYRO_CFG_REG,0x18);//设置陀螺仪自检及测量范围,0x018:不自检,2000deg/s
        mpu_delay(10);
        mpu_write_byte(MPU_ACCEL_CFG_REG,0x00);//设置陀螺仪加速计自检、测量范围及高通滤波频率,0x00:不自检,2G
        mpu_delay(10);
        
        mpu_write_byte(MPU_ACCEL_CFG2_REG,0x03);//设置速率与宽带
        mpu_delay(10);
        mpu_write_byte(MPU_INT_EN_REG,0x40);//仅使能运动中断
        mpu_delay(10);
        mpu_write_byte(MPU_MDETECT_CTRL_REG,0xC0);//启用硬件智能
        mpu_delay(10);
//        mpu_write_byte(MPU_MOTION_DET_REG,0xC0);//设置运动阈值
//        mpu_delay(10);
//        mpu_write_byte(MPU_ACCEL_ODR_REG,0xC0);//设置唤醒频率
//        mpu_delay(10);
        mpu_write_byte(MPU_PWR_MGMT1_REG,0x01);//选择最佳时钟源
        mpu_delay(10);
        
        mpu_write_byte(MPU_CFG_REG,0x03);
        mpu_delay(10);
        mpu_write_byte(MPU_FIFO_EN_REG,0x00);//FIFO使能
        mpu_delay(10);
        mpu_write_byte(MPU_INTBP_CFG_REG,0x82); //配置中断引脚为低电平有效
        mpu_delay(10);
        mpu_write_byte(MPU_SAMPLE_RATE_REG,0x31);//设置陀螺仪采样率,0x31:20Hz
        mpu_delay(10);
        mpu_write_byte(MPU_CFG_REG,0x06);//设置陀螺仪滤波频率,0x04:42Hz(相当于20Hz)
        mpu_delay(10);
    }
    else
        return 1;

    return 0;
}

4.4 加速度与陀螺仪数据的读取

4.4.1 加速度的读取

Addr (Hex) Register Name Serial I/F Bit
0X3B ACCEL_XOUT_H R ACCEL_XOUT_H[15:8]
0X3C ACCEL_XOUT_L R ACCEL_XOUT_L[7:0]
0X3D ACCEL_YOUT_H R ACCEL_YOUT_H[15:8]
0X3E ACCEL_YOUT_L R ACCEL_YOUT_L[7:0]
0X3F ACCEL_ZOUT_H R ACCEL_ZOUT_H[15:8]
0X40 ACCEL_ZOUT_L R ACCEL_ZOUT_L[7:0]
//得到加速度值(原始值)
//gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
void Get_MPU6500_Accelerometer(short *ax,short *ay,short *az)
{
    u8 BUF[6];  
    BUF[0]=mpu_read_byte(MPU_ACCEL_XOUTL_REG); 
    BUF[1]=mpu_read_byte(MPU_ACCEL_XOUTH_REG);
	*ax=((u16)BUF[1]<<8)|BUF[0];  
    
    BUF[2]=mpu_read_byte(MPU_ACCEL_YOUTL_REG);
    BUF[3]=mpu_read_byte(MPU_ACCEL_YOUTH_REG);
	*ay=((u16)BUF[3]<<8)|BUF[2];
    
    BUF[4]=mpu_read_byte(MPU_ACCEL_ZOUTL_REG);
    BUF[5]=mpu_read_byte(MPU_ACCEL_ZOUTH_REG);
	*az=((u16)BUF[5]<<8)|BUF[4];
}

 4.4.2 陀螺仪的读取

/**
 * @brief       得到陀螺仪值(原始值)
 * @param       gx,gy,gz:陀螺仪x,y,z轴的原始读数(带符号)
 * @retval      无
 */
void Get_MPU6500_GYRO(short *gx,short *gy,short *gz)
{
    u8 BUF[6];
    BUF[0]=mpu_read_byte(MPU_GYRO_XOUTL_REG); 
    BUF[1]=mpu_read_byte(MPU_GYRO_XOUTH_REG);
    *gx=((u16)BUF[1]<<8)|BUF[0]; 

    BUF[2]=mpu_read_byte(MPU_GYRO_YOUTL_REG);
    BUF[3]=mpu_read_byte(MPU_GYRO_YOUTH_REG);
    *gy=((u16)BUF[3]<<8)|BUF[2];

    BUF[4]=mpu_read_byte(MPU_GYRO_ZOUTL_REG);
    BUF[5]=mpu_read_byte(MPU_GYRO_ZOUTH_REG);
    *gz=((u16)BUF[5]<<8)|BUF[4];
}

4.4.3 温度的读取

要将温度传感器的输出转换为摄氏度,请使用以下公式:

                   

//得到温度值
//返回值:温度值(扩大了100倍)
short MPU_Get_Temperature(void)
{
    u8 BUF[2]; //用于存放温度
    short raw;
    float temp;
    BUF[0]=mpu_read_byte(TEMP_OUT_L); 
    BUF[1]=mpu_read_byte(TEMP_OUT_H); 
    raw=((u16)BUF[1]<<8)|BUF[0];//将8位数据整合为16位
    temp = 21+ ((double)(raw - 21))/333.87;// 读取计算出温度

    return temp*100;//为了好处理数据,这里扩大100倍
}

4.5 读取MPU6500数据

        我们将MPU6500平放与桌面上,此时在Z轴上会收到1g的重力加速度。例子中设置量程范围为\pm2g,也就是65536/4=16384,此时在z轴的加速度读数应该在16384附近,由于我没完全平放模块,所以会大了一点点,如下图:

                   

那么我设置量程为\pm16g呢?读数65536/32=2048左右,试试:

                       

那么关于读取MPU的原始数据就先到这里就结束了,往后给大家带来MPU6500的姿态解算。文章源代码:链接:https://pan.baidu.com/s/1v99GScyPQGAJEG8S3IaeTw?pwd=x8hc 提取码: x8hc

bsp_mpu6500_reg.h

#ifndef __BSP_MPU6500_REG_H
#define __BSP_MPU6500_REG_H

//#define MPU_ACCEL_OFFS_REG		0X06	//accel_offs寄存器,可读取版本号,寄存器手册未提到
//#define MPU_PROD_ID_REG			0X0C	//prod id寄存器,在寄存器手册未提到
#define MPU_SELF_TESTX_REG		0X0D	//自检寄存器X
#define MPU_SELF_TESTY_REG		0X0E	//自检寄存器Y
#define MPU_SELF_TESTZ_REG		0X0F	//自检寄存器Z
#define MPU_SELF_TESTA_REG		0X10	//自检寄存器A
#define MPU_SAMPLE_RATE_REG		0X19	//采样频率分频器
#define MPU_CFG_REG				0X1A	//配置寄存器
#define MPU_GYRO_CFG_REG		0X1B	//陀螺仪配置寄存器
#define MPU_ACCEL_CFG_REG		0X1C	//加速度计配置寄存器
#define MPU_ACCEL_CFG2_REG      0X1D
#define MPU_ACCEL_ODR_REG       0X1E    //设置唤醒频率
#define MPU_MOTION_DET_REG		0X1F	//唤醒运动阈值
#define MPU_FIFO_EN_REG			0X23	//FIFO使能寄存器
#define MPU_I2CMST_CTRL_REG		0X24	//IIC主机控制寄存器
#define MPU_I2CSLV0_ADDR_REG	0X25	//IIC从机0器件地址寄存器
#define MPU_I2CSLV0_REG			0X26	//IIC从机0数据地址寄存器
#define MPU_I2CSLV0_CTRL_REG	0X27	//IIC从机0控制寄存器
#define MPU_I2CSLV1_ADDR_REG	0X28	//IIC从机1器件地址寄存器
#define MPU_I2CSLV1_REG			0X29	//IIC从机1数据地址寄存器
#define MPU_I2CSLV1_CTRL_REG	0X2A	//IIC从机1控制寄存器
#define MPU_I2CSLV2_ADDR_REG	0X2B	//IIC从机2器件地址寄存器
#define MPU_I2CSLV2_REG			0X2C	//IIC从机2数据地址寄存器
#define MPU_I2CSLV2_CTRL_REG	0X2D	//IIC从机2控制寄存器
#define MPU_I2CSLV3_ADDR_REG	0X2E	//IIC从机3器件地址寄存器
#define MPU_I2CSLV3_REG			0X2F	//IIC从机3数据地址寄存器
#define MPU_I2CSLV3_CTRL_REG	0X30	//IIC从机3控制寄存器
#define MPU_I2CSLV4_ADDR_REG	0X31	//IIC从机4器件地址寄存器
#define MPU_I2CSLV4_REG			0X32	//IIC从机4数据地址寄存器
#define MPU_I2CSLV4_DO_REG		0X33	//IIC从机4写数据寄存器
#define MPU_I2CSLV4_CTRL_REG	0X34	//IIC从机4控制寄存器
#define MPU_I2CSLV4_DI_REG		0X35	//IIC从机4读数据寄存器

#define MPU_I2CMST_STA_REG		0X36	//IIC主机状态寄存器
#define MPU_INTBP_CFG_REG		0X37	//中断/旁路设置寄存器
#define MPU_INT_EN_REG			0X38	//中断使能寄存器
#define MPU_INT_STA_REG			0X3A	//中断状态寄存器

#define MPU_ACCEL_XOUTH_REG		0X3B	//加速度值,X轴高8位寄存器
#define MPU_ACCEL_XOUTL_REG		0X3C	//加速度值,X轴低8位寄存器
#define MPU_ACCEL_YOUTH_REG		0X3D	//加速度值,Y轴高8位寄存器
#define MPU_ACCEL_YOUTL_REG		0X3E	//加速度值,Y轴低8位寄存器
#define MPU_ACCEL_ZOUTH_REG		0X3F	//加速度值,Z轴高8位寄存器
#define MPU_ACCEL_ZOUTL_REG		0X40	//加速度值,Z轴低8位寄存器

#define MPU_TEMP_OUTH_REG		0X41	//温度值高八位寄存器
#define MPU_TEMP_OUTL_REG		0X42	//温度值低8位寄存器

#define MPU_GYRO_XOUTH_REG		0X43	//陀螺仪值,X轴高8位寄存器
#define MPU_GYRO_XOUTL_REG		0X44	//陀螺仪值,X轴低8位寄存器
#define MPU_GYRO_YOUTH_REG		0X45	//陀螺仪值,Y轴高8位寄存器
#define MPU_GYRO_YOUTL_REG		0X46	//陀螺仪值,Y轴低8位寄存器
#define MPU_GYRO_ZOUTH_REG		0X47	//陀螺仪值,Z轴高8位寄存器
#define MPU_GYRO_ZOUTL_REG		0X48	//陀螺仪值,Z轴低8位寄存器

#define MPU_I2CSLV0_DO_REG		0X63	//IIC从机0数据寄存器
#define MPU_I2CSLV1_DO_REG		0X64	//IIC从机1数据寄存器
#define MPU_I2CSLV2_DO_REG		0X65	//IIC从机2数据寄存器
#define MPU_I2CSLV3_DO_REG		0X66	//IIC从机3数据寄存器

#define MPU_I2CMST_DELAY_REG	0X67	//IIC主机延时管理寄存器
#define MPU_SIGPATH_RST_REG		0X68	//信号通道复位寄存器
#define MPU_MDETECT_CTRL_REG	0X69	//运动检测控制寄存器
#define MPU_USER_CTRL_REG		0X6A	//用户控制寄存器
#define MPU_PWR_MGMT1_REG		0X6B	//电源管理寄存器1
#define MPU_PWR_MGMT2_REG		0X6C	//电源管理寄存器2 
#define MPU_FIFO_CNTH_REG		0X72	//FIFO计数寄存器高八位
#define MPU_FIFO_CNTL_REG		0X73	//FIFO计数寄存器低八位
#define MPU_FIFO_RW_REG			0X74	//FIFO读写寄存器
#define MPU_DEVICE_ID_REG		0X75	//器件ID寄存器
 
#define MPU6500_ID          0x70

#endif
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐