硬件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