STM32F4XX软件I2C驱动MPU6050

本文详细介绍了MPU6050传感器的工作原理,包括其加速度计和陀螺仪功能,以及如何通过STM32F4系列单片机的软件I2C接口进行数据通信和寄存器操作。提供了一段驱动代码示例,展示了读写寄存器和获取传感器数据的过程。
摘要由CSDN通过智能技术生成

MPU6050

一、简介

MPU6050是一款6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角,常应用于平衡车、飞行器等需要检测自身姿态的场景。

  • 3轴加速度计(Accelerometer)
    测量X、Y、Z轴的加速度
  • 3轴陀螺仪传感器(Gyroscope)
    测量X、Y、Z轴的角速度

详细信息可参考产品说明书

二、软件I2C

这里给出STM32F4XXX软件I2C代码

#include "stm32f4xx.h"                  // Device header
#include "Delay.h"

//软件I2C,SDA和SCL引脚根据需要配置
//GPIO全在AHB1总线,这里选择PD2作SCL和PD3作SDA

/*封装I2C引脚电平函数*/
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOD, GPIO_Pin_2, (BitAction)BitValue);
	Delay_us(10);
}
void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOD, GPIO_Pin_3, (BitAction)BitValue);
	Delay_us(10);
}
uint8_t MyI2C_R_SDA()
{
	uint8_t BitValue = GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_3);//主机读取SDA引脚电平
	Delay_us(10);
	return BitValue;
}

/*I2C初始化函数,SDA和SCL同时为高电平*/
void MyI2C_Init()
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_Init(GPIOD, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOD, GPIO_Pin_2 | GPIO_Pin_3);//I2C处于空闲状态
}
/*I2C起始条件*/
void MyI2C_Start()
{
	//在SCL高电平期间,SDA从高电平切换到低电平,先拉低SDA再拉低SCL
	MyI2C_W_SDA(1);//先释放SDA
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}
/*I2C终止条件*/
void MyI2C_End()
{
	//在SCL高电平期间,SDA从低电平切换到高电平,先拉高SCL再拉高SDA
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}
/*发送一个字节*/
void MyI2C_SendByte(uint8_t Byte)
{
	//在SCL低电平期间,主机将数据依次放到SDA线上(高位先行)然后释放SCL
	for(uint8_t i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));//通过按位与将数据以高位先行的顺序写传输
		MyI2C_W_SCL(1);//从机在SCL高电平期间读取数据位
		MyI2C_W_SCL(0);//保证SCL以低电平结束确保下次数据传输
	}
}
/*接收一个字节*/
uint8_t MyI2C_ReceiveByte()
{
	//SCL低电平期间,从机将数据依次放到SDA线上(高位先行)然后释放SCL
	
	uint8_t Byte = 0x00;
	MyI2C_W_SDA(1);//为了防止主机干扰从机写入数据,需要主机释放SDA即转换为接收模式
	for(uint8_t i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);//主机在SCL高电平期间读取数据位
		if(MyI2C_R_SDA() == 1) Byte |= (0x80 >> i);
		MyI2C_W_SCL(0);
	}
	return Byte;
}
/*发送应答*/
//主机在接收完一个字节之后,在下一个时钟发送一位数据,0表示应答,1表示非应答
void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);
	MyI2C_W_SCL(1);//从机在SCL高电平期间读取应答位
	MyI2C_W_SCL(0);
}


/*接收应答*/
//主机在发送完一个字节之后,在下一个时钟接收一位数据以判断从机是否应答,0表示应答,1表示非应答
uint8_t MyI2C_ReceiveAck()
{ 
	uint8_t AckBit;
	MyI2C_W_SDA(1);//主机在接受之前要释放SDA,切换到接收状态
	MyI2C_W_SCL(1);//主机在SCL高电平期间读取应答位
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

三、MPU6050主要寄存器

  1. SMPLRT_DIV采样频率分频器
    MPU6050采样频率分频器
    用于配置采样频率的分频系数,分频越小内部AD转换越快,参照公式: 采样频率 = 陀螺仪输出时钟频率 1 + 分频值 采样频率 = \frac{陀螺仪输出时钟频率}{1+分频值} 采样频率=1+分频值陀螺仪输出时钟频率不使用低通滤波器时,陀螺仪时钟为8KHz。

  2. CONFIG配置寄存器
    MPU6050配置寄存器
    分两部分,外部同步设置和低通滤波器配置,一般只涉及到低通滤波器使数据更加平滑。

  3. GYRO_CONFIG陀螺仪配置寄存器
    MPU6050陀螺仪配置寄存器
    高三位是XYZ轴的自测使能位,中间两位是满量程选择位,低三位没用到。

  4. ACCEL_CONFIG加速度计配置寄存器
    MPU6050加速度寄存器
    加速度计配置寄存器和上面一样,只不过第三位是配置高通滤波器进行运动检测。

  5. 数据寄存器
    I2C从此处读取所需要的数据,是一个16位的有符号数,以二进制补码方式存储。读出高八位和第八位,高位左移八次或上低位数据即为原数据

  6. 电源管理寄存器
    寄存器1可用于设备复位、睡眠模式、循环模式(省电,唤醒的频率由寄存器2决定)、温度传感器失能和选择系统时钟来源(陀螺仪的晶振更加准确)。
    寄存器2可用于设置唤醒频率、分别控制6个轴进入待机模式

  7. 器件ID
    MPU6050ID
    这个寄存器只读,中间六位固定为1101 00,即I2C地址。

所有的寄存器上电默认值为0x00,除了107寄存器(0x40)和117寄存器(0x68)

四、MPU6050驱动

这里给出读一个字节的函数代码

uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
	uint8_t Data;
	MyI2C_Start();
	MyI2C_SendByte(MPU6050_Address);
	MyI2C_ReceiveAck();
	MyI2C_SendByte(RegAddress);
	MyI2C_ReceiveAck();
	
	MyI2C_Start();//重新指定读写位
	MyI2C_SendByte(MPU6050_Address | 0x01);//切换为读,控制权交给从机
	MyI2C_ReceiveAck();
	Data = MyI2C_ReceiveByte();//只读取一个字节
	MyI2C_SendAck(1);
	MyI2C_End();
	
	return Data;
}

对于在寄存器中写数据,需要根据寄存器地址进行操作,为方便对寄存器地址的调用这里用头文件包含所要用到的寄存器

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H
//MPU6050主要寄存器地址
#define	MPU6050_SMPLRT_DIV		0x19		//器件采样频率分频器寄存器
#define	MPU6050_CONFIG			0x1A		//器件配置寄存器
#define	MPU6050_GYRO_CONFIG		0x1B		//器件陀螺仪配置寄存器
#define	MPU6050_ACCEL_CONFIG	0x1C		//器件加速度配置寄存器

#define	MPU6050_ACCEL_XOUT_H	0x3B		//器件加速度数据寄存器
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41		//器件温度数据寄存器
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43		//器件陀螺仪数据寄存器
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

#define	MPU6050_PWR_MGMT_1		0x6B		//电源管理寄存器1
#define	MPU6050_PWR_MGMT_2		0x6C		//电源管理寄存器2
#define	MPU6050_WHO_AM_I		0x75		//器件ID

#endif

要在MPU6050寄存器中写数据,首先要解除睡眠模式,这里给出MPU6050初始化代码

void MPU6050_Init()
{
	MyI2C_Init();
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//解除睡眠模式,同时配置x轴陀螺仪时钟
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x01);//不需要循环模式同时不需要待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//设置10分频
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);//不需要外部同步,低通滤波设置为110
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//不需要自测,选择最大量程
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//不需要自测,选择最大量程,不需要高通滤波
}

初始化之后,陀螺仪就不断的产生数据存在寄存器中,不断读取数据寄存器数值即可

//读取寄存器数据值
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{
	uint8_t DataH, DataL;
	//寄存器中的值是16位有符号数,以二进制补码形式存储
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);//高8位
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低8位
	*AccX = (DataH << 8) | DataL;//拼接为16位原数据
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);
	*AccY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);
	*AccZ = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);
	*GyroX = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);
	*GyroY = (DataH << 8) | DataL;
	
	DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);
	*GyroZ = (DataH << 8) | DataL;
}
  • 41
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
单片机,又称单片微控制器,并非仅完成某一逻辑功能的芯片,而是将整个计算机系统集成到一个芯片上。其相当于一个微型计算机,与标准计算机相比,单片机仅缺少I/O设备。简而言之,一块芯片即构成了一台计算机。单片机具有体积小、质量轻、价格便宜的特点,为学习、应用和开发提供了便利条件。学习使用单片机是了解计算机原理与结构的最佳选择。 单片机的使用领域十分广泛,如智能仪表、实时工控、通讯设备、导航系统、家用电器等。一旦产品用上了单片机,就能实现产品的升级换代,使产品具有更高的智能化水平,常在产品名称前冠以“智能型”形容词,如智能型洗衣机等。此外,单片机在国防、电子玩具、厨房和家居设备等领域也有广泛的应用。 单片机技术还在不断发展,其在智能家居和智能城市、物联网设备和系统、边缘计算和边缘人工智能等领域的应用日益广泛。例如,通过单片机与传感器、执行器等设备的连接,可以实现智能家居设备的远程控制、自动化调节和智能化管理;作为物联网设备的核心控制单元,单片机能够实现物联网设备之间的互联互通,为物联网系统的运行提供基础支持;在边缘计算和边缘人工智能方面,单片机可以与人工智能技术结合,实现设备端数据的实时处理和智能分析。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值