STM32 硬件I2C读写MPU6050

接线图

函数介绍

生成起始条件

cs 复制代码
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);

生成终止条件

cs 复制代码
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);

配置在收到一个字节后,是否给从机应答(配置ACK位)

cs 复制代码
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);

发送数据,就是把Data这个数据直接写入到DR寄存器

cs 复制代码
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);

读取DR的数据

cs 复制代码
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);

发送7位地址的专用函数

cs 复制代码
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);

代码配置

配置硬件I2C读写初始化函数

1.定义结构体变量

bash 复制代码
//定义结构体变量
GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量
I2C_InitTypeDef  I2C_InitStructure;//定义I2C结构体变量

2.开启时钟

bash 复制代码
//开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);//开启I2C2的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO B族的时钟

3.配置GPIO

bash 复制代码
//配置GPIO
	
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//配置为复用开漏
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
GPIO_Init(GPIOB, &GPIO_InitStructure);

4.初始化I2C2外设

bash 复制代码
//配置I2C2
	
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;							//I2C模式
I2C_InitStructure.I2C_ClockSpeed = 50000; 							//配置SCL的时钟频率
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;			//时钟占空比
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;							//应答位配置
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//从机响应几位地址的配置
I2C_InitStructure.I2C_OwnAddress1 = 0x00;								//自身地址1
I2C_Init(I2C2, &I2C_InitStructure);

使能I2C

bash 复制代码
//使能I2C2
I2C_Cmd(I2C2, ENABLE);

整体代码

cs 复制代码
//------------------------------硬件I2C读写--------------------------------------

void I2C_Init2(void)
{

	//定义结构体变量
	GPIO_InitTypeDef GPIO_InitStructure;//定义GPIO结构体变量
	I2C_InitTypeDef  I2C_InitStructure;//定义I2C结构体变量
	
	
	//开启时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);//开启I2C2的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//开启GPIO B族的时钟
	
	//配置GPIO
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//配置为复用开漏
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//配置I2C2
	
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;							//I2C模式
	I2C_InitStructure.I2C_ClockSpeed = 50000; 							//配置SCL的时钟频率
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;			//时钟占空比
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;							//应答位配置
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//从机响应几位地址的配置
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;								//自身地址1
	I2C_Init(I2C2, &I2C_InitStructure);
	
	//使能I2C2
	I2C_Cmd(I2C2, ENABLE);
	
}

//------------------------------硬件I2C读写--------------------------------------

MPU6050配置

cs 复制代码
//从机地址
#define MPU6050_ADDRESS    0xD0
cs 复制代码
void MPU6050_Init(void)
{
	I2C_Init2();
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);
}

指定地址写时序

cs 复制代码
//指定地址写时序
void MPU6050_WriteReg(uint8_t RegAddRess, uint8_t Data)
{
	
	//生成起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待EV5事件到来,检查EV5事件
	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	//发送从机地址 方向为发送
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	//等待事件 EV6
	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
	//写入DR,发送数据
	I2C_SendData(I2C2, RegAddRess);
	//等待事件 EV8
	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
	//发送数据
	I2C_SendData(I2C2, Data);
	//等待事件 EV8_2
	while (I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
	//终止条件
	I2C_GenerateSTOP(I2C2, ENABLE);
}

指定地址读时序

cs 复制代码
//指定地址读时序
uint8_t MPU6050_ReadReg(uint8_t RegAddRess)
{

uint8_t Data;
	//起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待事件 EV5
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	//发送从机地址 方向为发送
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	//等待事件 EV6
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);
	//发送寄存器地址
	I2C_SendData(I2C2, RegAddRess);
	//等待事件 EV8_2
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED) != SUCCESS);
	
	//重复起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待事件 EV5
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	//发送从机地址 方向为接收
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);
	//等待事件 EV6
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);
	//配置ACK位
	I2C_AcknowledgeConfig(I2C2, DISABLE);
	//终止条件
	I2C_GenerateSTOP(I2C2, ENABLE);
	//等待事件 EV7
	while(I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
	//读取DR
	Data = I2C_ReceiveData(I2C2);
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);
	
	return Data;
	
}

主函数

cs 复制代码
#include "MyI2C.h"
#include "MPU6050.h"
int main(void)
{
	int16_t AX, AY, AZ, GX, GY, GZ;
	uint8_t ID;
	OLED_Init();
	MPU6050_Init();

	OLED_ShowString(1, 1, "ID:");
	ID = MPU6050_GetID();
	OLED_ShowHexNum(1, 4, ID, 2);
	while(1)
	{
		MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);
		OLED_ShowSignedNum(2, 1, AX, 5);
		OLED_ShowSignedNum(3, 1, AY, 5);
		OLED_ShowSignedNum(4, 1, AZ, 5);
		OLED_ShowSignedNum(2, 8, GX, 5);
		OLED_ShowSignedNum(3, 8, GY, 5);
		OLED_ShowSignedNum(4, 8, GZ, 5);
		
		
	}
	
	
}

优化死循环

超时退出机制,防止卡死

cs 复制代码
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;
		}
	}
}

将读写时序函数里的while全部替换

cs 复制代码
//指定地址写时序
void MPU6050_WriteReg(uint8_t RegAddRess, uint8_t Data)
{

	//生成起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待EV5事件到来,检查EV5事件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	//发送从机地址 方向为发送
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	//等待事件 EV6
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	//写入DR,发送数据
	I2C_SendData(I2C2, RegAddRess);
	//等待事件 EV8
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);
	//发送数据
	I2C_SendData(I2C2, Data);
	//等待事件 EV8_2
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
	//终止条件
	I2C_GenerateSTOP(I2C2, ENABLE);
}

//指定地址读时序
uint8_t MPU6050_ReadReg(uint8_t RegAddRess)
{

	uint8_t Data;
	//起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待事件 EV5
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	//发送从机地址 方向为发送
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter);
	//等待事件 EV6
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
	//发送寄存器地址
	I2C_SendData(I2C2, RegAddRess);
	//等待事件 EV8_2
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);
	
	//重复起始条件
	I2C_GenerateSTART(I2C2, ENABLE);
	//等待事件 EV5
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);
	//发送从机地址 方向为接收
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver);
	//等待事件 EV6
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);
	//配置ACK位
	I2C_AcknowledgeConfig(I2C2, DISABLE);
	//终止条件
	I2C_GenerateSTOP(I2C2, ENABLE);
	//等待事件 EV7
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);
	//读取DR
	Data = I2C_ReceiveData(I2C2);
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);
	
	return Data;
	
}
相关推荐
总结所学9 分钟前
labview官网离线下载
嵌入式硬件
zcmodeltech10 分钟前
智能矿井沙盘模型多系统协同控制系统设计:基于STM32与Modbus RTU的感知-传输-控制一体化方案
服务器·数据库·分布式·stm32·单片机·嵌入式硬件
szxinmai主板定制专家2 小时前
驱控一体新范式:RK3576+FPGA+CODESYS工业实时AI控制架构全解
人工智能·嵌入式硬件·计算机视觉·fpga开发·架构·工业ai·驱控一体
国科安芯3 小时前
ASC0101S自动双向电平转换原理深剖
单片机·嵌入式硬件·fpga开发·云计算·信息与通信
李永奉3 小时前
中科蓝讯SDK开发-开启串口Debug打印调试教程
单片机·嵌入式硬件·mcu·物联网·电脑
LCG元3 小时前
STM32硬件SPI驱动OLED SSD1306显示屏全流程实战:从CubeMX配置到中英文显示
stm32·单片机·嵌入式硬件
sukalot3 小时前
windows网络适配器驱动开发-双 STA 连接(下)
windows·驱动开发·stm32
飞凌嵌入式3 小时前
性能翻倍·功耗减半!RK3572八核核心板,重构嵌入式计算新标杆
人工智能·嵌入式硬件·飞凌嵌入式
zcmodeltech4 小时前
智慧农业沙盘模型物联网控制系统设计:基于STM32与Modbus RTU的传感器-执行器闭环方案
服务器·分布式·stm32·嵌入式硬件·物联网·能源
WD1372980155714 小时前
WD5030L,超高集成度、大电流输出、高效率低发热,限流24V转12V,6A
stm32·单片机·嵌入式硬件·51单片机