13、STM32F103C8T6 硬件IIC读取MPU6050

本文详细介绍了如何在STM32平台上对MPU6050传感器进行初始化,包括开启时钟、配置GPIO、启用I2C通信以及实现超时退出机制,以确保高效和安全的数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、MPU6050初始化

1、开启对应时钟

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

2、配置GPIO

	GPIO_InitTypeDef GPIO_InitStructure1;
	GPIO_InitStructure1.GPIO_Mode = GPIO_Mode_AF_OD;
	GPIO_InitStructure1.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure1.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure1);

3、初始化使能IIC

	I2C_InitTypeDef I2C_InitStructure;
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
	
	//stm32作为从机时才使用
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 
	I2C_InitStructure.I2C_ClockSpeed = 50000;
	
	//时钟占空比:只有在时钟频率大于100KHz,进入到快速状态时才有用,在小于等于100KHz的标准速度下,占空比是固定的1:1
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;	
	
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;
	I2C_Init(I2C2, &I2C_InitStructure);
	
	I2C_Cmd(I2C2, ENABLE);

4、初始化MPU6050

	//对MPU6050硬件电路进行初始化配置
	//芯片的写寄存器功能,需要解除芯片的睡眠模式,否则写入是无效的
	//睡眠模式 是电源管理寄存器1 的SLEEP控制的,写入0x00,解除睡眠模式,该寄存器地址为 0x6B;
	//解除睡眠,选择陀螺仪时钟
	MPU6050_Write_Reg(MPU6050_PWR_MGMT_1, 0x01); 
	//6 轴均不待机
	MPU6050_Write_Reg(MPU6050_PWR_MGMT_2, 0x00);
	//采样分频为 10	
	MPU6050_Write_Reg(MPU6050_SMPLRT_DIV, 0x09);	
	//滤波参数给最大
	MPU6050_Write_Reg(MPU6050_CONFIG, 0x06);
	//陀螺仪和下面加速度计都选择最大量程	
	MPU6050_Write_Reg(MPU6050_GYRO_CONFIG, 0x18);	
	MPU6050_Write_Reg(MPU6050_ACCEL_CONFIG, 0x18);

二、超时退出

注:硬件I2C,需要等待标志位判定成功后,再进行下一位,程序中出现了大量的while死循环等待,在程序中是比较危险的,一旦有一个事件一直没有产生,就会让整个程序卡死,对于死循环等待,可以加一个超时退出机制

//超时退出函数,里面封装了I2C_CheckEvent()
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t timeOut = 10000;
	while(I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)
	{
		timeOut--;
		if(timeOut == 0) //超时退出机制
		{
			break;
		}
	}
}

三、指定地址写

void MPU6050_Write_Reg(uint8_t regAddress, uint8_t data)
{
	I2C_GenerateSTART(I2C2, ENABLE);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	//注:发送数据 都自带了接收应答的过程,接收数据 都自带了发送应答的过程
	//如果应答错误,硬件会通过标志位和中断来提示
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	//这里不需要等待 EV8_1 事件

	I2C_SendData(I2C2, regAddress);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
	
	I2C_SendData(I2C2, data);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

	I2C_GenerateSTOP(I2C2, ENABLE);
}

四、指定地址读

uint8_t MPU6050_Read_Reg(uint8_t regAddress)
{
	uint8_t data;
	
	I2C_GenerateSTART(I2C2, ENABLE);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	
	//注:发送数据 都自带了接收应答的过程,接收数据 都自带了发送应答的过程
	//如果应答错误,硬件会通过标志位和中断来提示
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	//这里不需要等待 EV8_1 事件

	I2C_SendData(I2C2, regAddress);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

	I2C_GenerateSTART(I2C2, ENABLE);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
	
	//注, 再接收一个字节数据时(接收最后一个字节时,需要提前先设置ack 和 stop,再接收数据)
	I2C_AcknowledgeConfig(I2C2, DISABLE);
	I2C_GenerateSTOP(I2C2, ENABLE);
	
	//再等待EV7事件之后,再读取 DR 获取数据
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);
	data = I2C_ReceiveData(I2C2); 
	
	//接收完成后 ack 置 1(默认状态 ack 就是1 给从机应答,
	//在最后一个字节之前,临时将 ack 置 0,给非应答,所以在接收函数的最后需要恢复 默认的 ack = 1)
	//这样做是为了方便指定地址收多个字节
	I2C_AcknowledgeConfig(I2C2, ENABLE);
	
	return data;
}

其他操作参考上一节 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值