STM32F103硬件IIC与MPU6050通信,附代码详解

硬件IIC代码配置详解

硬件IIC通信层

IIC库函数详解

void I2C_DeInit(I2C_TypeDef* I2Cx);
//恢复缺省值
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
//初始化
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
//结构体初始化
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//IIC使能DMA
void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//功能:指定下一个DMA传输是否为最后一个
//注释:该位在主接收模式使用, 使得在最后一次接收数据时可以产生一个NACK
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
//生成I2Cx通信起始信号
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
//生成I2Cx通信停止信号
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能或者失能指定的I2C应答功能
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
//配置指定的I2C自身地址2,如果STM32作为从设备使用时,必须进行配置
void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能双地址模式
void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能或者失能广播呼叫
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);
//使能或者失能指定的I2C中断
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
//通过I2Cx外设发送数据字节
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
//通过I2Cx外设接收数据字节
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
//发送7位地址以选中从设备
uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);
//读取指定的I2C寄存器并返回其值
void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
//使能或者失能指定的I2C软件重置
/******下面不常用******/
void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition);
void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert);
void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition);
void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);
void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle);
/**
 * 三种I2C状态监控函数
 *  1) Basic state monitoring//基本状态监测
 *******************************************************************************
 */
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
//检查最后一个I2Cx事件是否等于作为参数传递的事件
/**
 * 
 *  2) Advanced state monitoring//高级状态监控
 *******************************************************************************
 */
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx);
//返回最后一个I2Cx事件
/**
 * 
 *  3) Flag-based state monitoring//基于标志位的状态监控
 *******************************************************************************
 */
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
//获取指定的I2C标志位
/**
 *
 *******************************************************************************
 */

void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
//清除标志位
ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
//获取中断标志位
void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
//清除中断标志位

MPU6050硬件IIC通信

.c

#include "stm32f10x.h"               
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS		0xD0
/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_WaitEvent
  ** @brief         : 防止死循环程序卡死:超时退出机制
  ** @param         : None
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
	uint32_t Timeout;
	Timeout = 10000;
	while (I2C_CheckEvent(I2Cx, I2C_EVENT) != SUCCESS)
	{
		Timeout --;
		if (Timeout == 0)
		{
			break;//可加入错误处理功能:如打印等
		}
	}
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_WriteReg
  ** @brief         : 指定地址,写入寄存器函数
  ** @param         : None
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : 复合格式指定地址部分
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)//写寄存器
{	

	I2C_GenerateSTART(I2C2, ENABLE);  						//起始条件;(写完就结束,退出函数【非阻塞式的函数】)
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);	//等待EV5事件;【确保上面函数执行到位】
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); //发送从机地址
					/***(发送和接收数据自带了应答)***/
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);   //等待EV6事件
	
	I2C_SendData(I2C2, RegAddress);								//写入DR;发送数据(自动转到移位寄存器)
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);//等待EV8事件
	
	I2C_SendData(I2C2, Data);									//发送最后一个字节Data
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待EV8_2事件(移位完成了,不再接收数据了):字节已经发送完毕
	
	I2C_GenerateSTOP(I2C2, ENABLE);		//终止时序
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_ReadReg
  ** @brief         : 指定地址,读出寄存器函数
  ** @param         : None
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : 复合格式指定地址部分
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
uint8_t MPU6050_ReadReg(uint8_t RegAddress)//读寄存器
{
	uint8_t Data;

	I2C_GenerateSTART(I2C2, ENABLE);  //起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//等待EV5事件
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); //发送从机地址
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);	//等待EV6事件
	
	I2C_SendData(I2C2, RegAddress);//发送数据
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待EV8事件
/******************************************************************************************
	
******************************************************************************************/
	I2C_GenerateSTART(I2C2, ENABLE);//重复起始条件
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT);//等待EV5事件
	
	I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver); //发送从机地址
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //等待EV6事件
/******************************************************************************************
	接收最后一个字节之前,提前配置ACK和STOP
******************************************************************************************/
	I2C_AcknowledgeConfig(I2C2, DISABLE);//提前给ACK置0;(不给应答)
	I2C_GenerateSTOP(I2C2, ENABLE);//提前申请产生终止条件:STOP=1
	
	MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);//等待EV7事件;(产生后,一个数据已经存到DR中)
	Data = I2C_ReceiveData(I2C2);//读取DR的数据:存到Data中
	
	I2C_AcknowledgeConfig(I2C2, ENABLE);//ACK回复默认的1;(为了方便指定地址收多个字节)
	
	return Data;
}



/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_Init
  ** @brief         : 初始化
  ** @param         : None
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
void MPU6050_Init(void)
{
	/******************************开启时钟*****************************/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);	
	//GPIO_PinRemapConfig(GPIO_Remap_I2C1,ENABLE);
	/*****************************定义结构体变量******************************/
	GPIO_InitTypeDef GPIO_InitStructure;
	I2C_InitTypeDef I2C_InitStructure;
	/****************************配置引脚模式*******************************/
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;		//复用开漏输出:硬件I2C协议的设计要求;硬件控制
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	/****************************配置IIC2外设*******************************/
	I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;			//模式
	I2C_InitStructure.I2C_ClockSpeed = 50000;			//50KHZ
	I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;	//时钟占空比
	I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;			//默认给应答
	I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;	//STM32作为从机模式时;可以相应7位地址
	I2C_InitStructure.I2C_OwnAddress1 = 0x00;	//STM32作为从机模式时;用于指定STM32自身地址,方便别的主机呼叫(不要和其他设备重复)
	I2C_Init(I2C2, &I2C_InitStructure);
	
	I2C_Cmd(I2C2, ENABLE);	//使能

	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);
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_GetID
  ** @brief         : 读取MPU6050的ID
  ** @param         : None
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
uint8_t MPU6050_GetID(void)
{
	return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}

/**
  ************************************************************************** 
  ** -------------------------------------------------------------------- **
  ** @name          : MPU6050_GetData
  ** @brief         : 读取MPU6050的角速度和陀螺仪
  ** @param         : int16_t *AccX, int16_t *AccY, int16_t *AccZ,
					  int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ
  ** @retval        : None
  ** @author        : XRaccoon
  ** -------------------------------------------------------------------- **
  ** @attention     : None
  ** -------------------------------------------------------------------- **
  ************************************************************************** 
**/
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;
	
	DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);
	DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);
	*AccX = (DataH << 8) | DataL;
	
	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;
}

.h

#ifndef __MPU6050_H
#define __MPU6050_H
#include "stdint.h"
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);

void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ, 
						int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);

#endif

reg.h寄存器宏定义

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H

#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
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

#endif

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STM32F103是一款基于ARM Cortex-M3内核的微控制器,具备硬件IIC(Inter-Integrated Circuit)功能,可以实现主从设备之间的通信硬件IIC通信是一种串行通信协议,通常用于短距离的设备之间的通信。它需要两根信号线:SDA(数据线)和SCL(时钟线)。在IIC通信中,一个设备充当主设备,控制整个通信的进行,而其他设备则充当从设备,等待主设备的命令。 在STM32F103中,可以通过配置相关寄存器和使用相应的库函数来实现IIC通信。作为主设备,我们需要首先初始化IIC总线,并设置相应的通信速率。然后,我们可以通过发送起始信号、选择从设备地址和读写操作来与从设备进行通信通信过程中,主设备可以通过发送或接收数据来完成数据的传输。 作为从设备,我们首先需要等待主设备选择我们的地址。当地址匹配时,我们可以通过拉低SDA线来发送应答信号,表示已经准备好进行通信。在收到数据后,我们可以发送应答信号,告知主设备数据已经接收完毕。 硬件IIC通信是一种简单、高效的通信方式,适用于需要短距离、低速率的设备之间的通信。在使用STM32F103进行硬件IIC主从通信时,我们需要合理配置主设备和从设备的相关参数,并遵循IIC通信的协议来进行通信。 总之,STM32F103通过硬件IIC功能,可以实现主从设备之间的通信。通过合适的配置和使用相应的库函数,我们可以轻松地实现IIC通信,并实现数据的传输。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

领悟电子界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值