正点stm32f407探索者开发板使用HAL库通过I2C协议配置并读取MPU6050(基础向)

参考资料:[1][2]正点原子资料下载中心->stm32f407探索者开发板:资料A盘:Explorer STM32F4_V2.2_SCH.pdf,探索者IO引脚分配表.xlsx,5,MPU6050资料.rar

文章内容仅供参考;


通过STM32f07ZG芯片通过i2c协议向MPU6050的寄存器写数据来配置传感器,并通过该协议读取传感器读数;

MPU6050简述

在这篇文章中,主要用到了MPU6050集成的3轴MEMS陀螺仪和3轴MEMS加速度计;
其中陀螺仪的测量值是正比于角速度,不难理解,也可以方便地直接转换为国际单位制(如何转换下文详述);
对于加速度传感器的测量值,我们可以引入如下模型
在这里插入图片描述
在这里插入图片描述
若我使传感器在地表以1g的加速度竖直向上加速,那么传感器的示数应为Z=-2g
其测量值即为墙壁对小球造成的加速度,具体表现为小球所受重力加速度与小球与地面加速度的矢量和。同样,测量值与SI(国际单位制)也需要正比换算;

MPU6050的封装

在这里插入图片描述
我们可以观察到AD0针脚接地,根据AD0电平与传感器Slave地址的关系
在这里插入图片描述
我们可以得知传感器的从机地址为0x68;
我们结合在这里插入图片描述
可知I2C的两条线连接到了芯片的PB8和PB9引脚,我们可以将这两条引脚设置为I2C1;
在这里插入图片描述

I2C的函数操作

在这里插入图片描述
在这里我们用到的是这两个函数,内容是以阻塞模式将一定量的数据写入特定的内存地址/以阻塞模式从特定的内存地址读取一定量的数据;
函数参数如下(以读从机函数为例):
在这里插入图片描述
第一个值是指向包含指定 I2C 的配置信息的 I2C_HandleTypeDef 结构的指针,这部分是配置完.ioc文件后CubeMAX自动生成的,具体取决于使用的I2C编号,此处即为&hi2c1
在这里插入图片描述
第二个值为七位目标设备地址,注意使用时还需要左移一位,也就是上面提到的0x68;
第三个值为内存地址,即从机上的寄存器地址,地址的值需要查询寄存器分配表;
第四个值为内存地址长度,每8位二进制数为1,在这篇文章中均为1;
第五个值为接收数据的地址,指向要发送的数据;
第六个值为要接收的数据量,每8位二进制数为1;
第七个值为超时时间,如果超时未收到应答信号,则会在返回值中体现出来,单位毫秒(1000ms=1s);
返回值定义如下(自动生成):
在这里插入图片描述
写从机函数的第五、六个值变成了指向要发送数据的指针和要发送的数据量,和读从机函数细节相同;

配置过程寄存器操作内容

代码会在最后附上
在这里插入图片描述

上图的一些名称不是标准命名,仅供参考

重置MPU6050

在这里插入图片描述
MPU_PWR_MGMT1_REG(0x6B)寄存器Bit7写为1,并延时适当时间等待复位;

valu=0x80;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT1_REG,1,&valu,1,100);// Reset MPU6050
HAL_Delay(100);

唤醒MPU6050并配置时钟源

MPU_PWR_MGMT1_REG(0x6B)寄存器Bit6位写为0,Bit210设置为001,即将时钟源定位X轴角速度计;;

valu=0x01;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT1_REG,1,&valu,1,100);// Awaken MPU6050 &Set clock as PLL X

关闭所有中断

在这里插入图片描述
在这个简单实验中不需要配置这部分;
MPU_INT_EN_REG(0x38)寄存器Bit0347均置为1;

valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_INT_EN_REG,1,&valu,1,100);// Close all interrupts

失能FIFO并关闭传感器i2c主机模式

在这里插入图片描述
MPU_USER_CTRL_REG(0x6A)寄存器Bit654写0;

valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_USER_CTRL_REG,1,&valu,1,100);// Turn off IIC host mode and FIFO

无数据需要写入FIFO

在这里插入图片描述
在这里插入图片描述

使MPU_FIFO_EN_REG(0x23)寄存器均为0即可;

valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_FIFO_EN_REG,1,&valu,1,100);// No sensors were added to the FIFO

关闭传感器待机模式

在这里插入图片描述

MPU_PWR_MGMT2_REG(0x6C)寄存器Bit543210位均置0;

valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT2_REG,1,&valu,1,100);// Awaken sensor

配置陀螺仪和加速度计

在这里插入图片描述
在这里插入图片描述
本次简单实验不需要自检,选择量程即可;
MPU_ACCEL_CFG(0x1C)寄存器和MPU_GYRO_CFG(0X1B)寄存器的Bit43均设置为1(选择最大量程);

valu=0x18;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_ACCEL_CFG,1,&valu,1,100);// Accelerometer configuration
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_GYRO_CFG,1,&valu,1,100);// Gyroscope configuration

配置数字低通滤波器


这里选择相对均衡的配置,即将MPU_CONFIGURATION(0x1A)的Bit210配置为011;

valu=0x03;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_CONFIGURATION,1,&valu,1,100);// Select sampling rate

配置输出率

在这里插入图片描述

根据上式,MPLRT写0即可,将MPU_RATE_DIVIDER(0x19)寄存器所有位写0;

valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_RATE_DIVIDER,1,&valu,1,100);// Select output rate

配置部分代码一览

#define MPU_PWR_MGMT1_REG		0X6B
#define MPU_PWR_MGMT2_REG		0X6C
#define MPU_INT_EN_REG			0X38
#define MPU_USER_CTRL_REG		0X6A
#define MPU_FIFO_EN_REG			0X23
#define MPU_DEVICE_ID_REG		0X75
#define MPU_ACCEL_XOUTH_REG	    0X3B
#define MPU_GYRO_XOUTH_REG  	0X43
#define MPU_ACCEL_CFG       	0X1C
#define MPU_GYRO_CFG        	0X1B
#define MPU_RATE_DIVIDER    	0X19
#define MPU_CONFIGURATION   	0X1A
HAL_StatusTypeDef stat;
uint8_t valu=0x80;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT1_REG,1,&valu,1,100);// Reset MPU6050
HAL_Delay(100);
valu=0x01;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT1_REG,1,&valu,1,100);// Awaken MPU6050 &Set clock as PLL X
valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_INT_EN_REG,1,&valu,1,100);// Close all interrupts
valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_USER_CTRL_REG,1,&valu,1,100);// Turn off IIC host mode and FIFO
valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_FIFO_EN_REG,1,&valu,1,100);// No sensors were added to the FIFO
valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_PWR_MGMT2_REG,1,&valu,1,100);// Awaken sensor
valu=0x18;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_ACCEL_CFG,1,&valu,1,100);// Accelerometer configuration
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_GYRO_CFG,1,&valu,1,100);// Gyroscope configuration
valu=0x03;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_CONFIGURATION,1,&valu,1,100);// Select sampling rate
valu=0x00;
stat=HAL_I2C_Mem_Write(&hi2c1,0x68<<1,MPU_RATE_DIVIDER,1,&valu,1,100);// Select output rate

读取部分寄存器操作内容

在这里插入图片描述
在这里插入图片描述
按地址读取测量值即可;
接收之后需要把数据处理成16位有符号整数。

#define MPU_ACCEL_XOUTH_REG	0X3B
#define MPU_GYRO_XOUTH_REG  0X43
int16_t data16A[3],data16G[3];
uint8_t dataACCEL[6],dataGYRO[6];
stat=HAL_I2C_Mem_Read(&hi2c1, 0x68<<1,MPU_ACCEL_XOUTH_REG, 1, dataACCEL,6, 100);
stat=HAL_I2C_Mem_Read(&hi2c1, 0x68<<1,MPU_GYRO_XOUTH_REG, 1, dataGYRO,6, 100);
for(int8_t i=0;i<3;i++)
	data16G[i]=(((uint16_t)dataGYRO[2*i])<<8)|dataGYRO[2*i+1],
	data16A[i]=(((uint16_t)dataACCEL[2*i])<<8)|dataACCEL[2*i+1];

此时data16·[i]中存储的并不是SI下的数据:
对于陀螺仪,如果内存数字为X,则有 X = w ⋅ LSB A C C E L X=w\cdot \text{LSB}_{ACCEL} X=wLSBACCEL,w的单位即为°/s;
对于加速度计,如果内存的数字为X,则有 X = a ⋅ LSB G Y R O X=a\cdot \text{LSB}_{GYRO} X=aLSBGYRO,a的单位为g(约9.8m/s2),需要注意,加速度值并不是物体相对于地面的加速度值,而是该值与重力加速度的矢量和;
对于LSB的值可以依照所选量程对照上表可得;

一些数据验证

我在不同角度下静置开发板,并通过U5的调试模式下以10Hz左右读取了100组加速度计测量值(data16A[i])的平均值,定义函数
f ( [ a 1 , a 2 , a 3 ] ) = a 1 2 + a 2 2 + a 3 2 f([a_1,a_2,a_3])=\sqrt{a_1^2+a_2^2+a_3^2} f([a1,a2,a3])=a12+a22+a32
绘制下表:

组数a1a2a3f([a1,a2,a3])
1-1.8151.352039.582040.23
2385.6647.982004.432041.76
31385.47168.051488.202040.22
4-2068.7839.1410.002069.19
52.992084.68-59.762085.54

可以观察到,在误差允许范围内,均接近所选量程下最低分辨率的1g(2048LSB/g);

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值