江科大IIC读取MPU6050hal库实现
hal库相关函数
初始化结构体
typedef struct
{uint32_t ClockSpeed; /*通讯速度*/uint32_t DutyCycle; /*快速模式下的占空比*/uint32_t OwnAddress1; /*设备地址1*/uint32_t AddressingMode; /*设备地址模式*/uint32_t DualAddressMode; /*双地址模式 */uint32_t OwnAddress2; /*设备地址2*/uint32_t GeneralCallMode; /*呼叫模式*/uint32_t NoStretchMode; /*时钟延长模式*/} I2C_InitTypeDef;
句柄
#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)
typedef struct __I2C_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
{I2C_TypeDef *Instance; /外设基地址*/I2C_InitTypeDef Init; /*初始化结构体*/uint8_t *pBuffPtr; /*传输缓存区*/uint16_t XferSize; /*传输数据大小 */__IO uint16_t XferCount; /*剩余传输数量 */__IO uint32_t XferOptions; /*传输选项*/__IO uint32_t PreviousState; /*通讯机上一个状态*/DMA_HandleTypeDef *hdmatx; /*IIC发送DMA句柄*/DMA_HandleTypeDef *hdmarx; /*IIC接收DMA句柄 */HAL_LockTypeDef Lock; /*状态锁存*/__IO HAL_I2C_StateTypeDef State; /*当前通讯状态*/__IO HAL_I2C_ModeTypeDef Mode; /*当前通讯模式*/__IO uint32_t ErrorCode; /*错误类型 */__IO uint32_t Devaddress; /*存储 I2C 目标设备的地址*/__IO uint32_t Memaddress; /*存放 I2C 目标设备内部的内存地址或寄存器地址*/__IO uint32_t MemaddSize; /*目标设备地址大小 */__IO uint32_t EventCount; /*记录 I2C 通信过程中发生的特定事件的次数 */#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)void (* MasterTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Tx Transfer completed callback */void (* MasterRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Master Rx Transfer completed callback */void (* SlaveTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Tx Transfer completed callback */void (* SlaveRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Slave Rx Transfer completed callback */void (* ListenCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Listen Complete callback */void (* MemTxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Tx Transfer completed callback */void (* MemRxCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Memory Rx Transfer completed callback */void (* ErrorCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Error callback */void (* AbortCpltCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Abort callback */void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode); /*!< I2C Slave Address Match callback */void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp Init callback */void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c); /*!< I2C Msp DeInit callback */#endif /* USE_HAL_I2C_REGISTER_CALLBACKS */
} I2C_HandleTypeDef;
获取标志位
__HAL_I2C_GET_FLAG()
初始化函数
HAL_StatusTypeDef HAL_I2C_Init(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c);
void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c);
收发函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout);
主模式发送,接受,从模式发送接收,向存储器写入读取,校验设备状态
中断收发函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_EnableListen_IT(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_DisableListen_IT(I2C_HandleTypeDef *hi2c);
HAL_StatusTypeDef HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress);
HAL_I2C_Master_Seq_Transmit_IT
:支持序列传输,可以分阶段发送数据,中间可插入重启条件(Re-START)或停止条件(STOP)。通过XferOptions
参数控制传输阶段(如首次传输、中间传输、最后传输),适用于复杂的 I2C 通信协议(如多部分数据传输、寄存器寻址后的数据写入)。
HAL_I2C_Master_Transmit_IT
:只能进行单次完整传输,发送数据后自动发送停止条件。适用于简单的一次性数据传输场景。
DMA收发函数
HAL_StatusTypeDef HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size);HAL_StatusTypeDef HAL_I2C_Master_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Master_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
HAL_StatusTypeDef HAL_I2C_Slave_Seq_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t XferOptions);
hal库实现江科大
我们按照江科大的I2C来配置
江科大的I2C1用到了OLED显示屏上面,所以我们要使用的是I2C2来进行通讯。
速度模式为快速模式。时钟为50KHz,占空比为2,从地址为七位,地址为0x00(这部分没啥用),全部默认值就可以了。
IIC通讯的重点就是把标准库的函数转换成hal库的,软件模拟方式就是修改GPIO的输入输出,这个就不演示了,这里主要完成硬件IIC部分代码转换。
首先看江科大的代码,主要就是由读写IIC两个核心代码为主,其他的代码都是在这个基础上完成的,所以我们只需要对读写IIC进行修改。
/*** 函 数:MPU6050写寄存器* 参 数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述* 参 数:Data 要写入寄存器的数据,范围:0x00~0xFF* 返 回 值:无*/
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{ uint8_t temp[2];temp[0] = RegAddress;temp[1] = Data;HAL_I2C_Master_Transmit(&hi2c2,MPU6050_ADDRESS,temp,2,500);
// I2C_GenerateSTART(I2C2, ENABLE); //硬件I2C生成起始条件
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
//
// I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); //硬件I2C发送从机地址,方向为发送
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //等待EV6
//
// I2C_SendData(I2C2, RegAddress); //硬件I2C发送寄存器地址
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING); //等待EV8
//
// I2C_SendData(I2C2, Data); //硬件I2C发送数据
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); //等待EV8_2
//
// I2C_GenerateSTOP(I2C2, ENABLE); //硬件I2C生成终止条件
}/*** 函 数:MPU6050读寄存器* 参 数:RegAddress 寄存器地址,范围:参考MPU6050手册的寄存器描述* 返 回 值:读取寄存器的数据,范围:0x00~0xFF*/
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{uint8_t Data;uint8_t temp = RegAddress;HAL_I2C_Master_Transmit(&hi2c2,MPU6050_ADDRESS,&temp,1,500);//硬件I2C发送寄存器地址HAL_I2C_Master_Receive(&hi2c2,MPU6050_ADDRESS,&Data,1,500);
// I2C_GenerateSTART(I2C2, ENABLE); //硬件I2C生成起始条件
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
//
// I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Transmitter); //硬件I2C发送从机地址,方向为发送
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); //等待EV6
//
// I2C_SendData(I2C2, RegAddress); //硬件I2C发送寄存器地址
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED); //等待EV8_2
//
// I2C_GenerateSTART(I2C2, ENABLE); //硬件I2C生成重复起始条件
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT); //等待EV5
//
// I2C_Send7bitAddress(I2C2, MPU6050_ADDRESS, I2C_Direction_Receiver); //硬件I2C发送从机地址,方向为接收
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED); //等待EV6
//
// I2C_AcknowledgeConfig(I2C2, DISABLE); //在接收最后一个字节之前提前将应答失能
// I2C_GenerateSTOP(I2C2, ENABLE); //在接收最后一个字节之前提前申请停止条件
//
// MPU6050_WaitEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED); //等待EV7
// Data = I2C_ReceiveData(I2C2); //接收数据寄存器
//
// I2C_AcknowledgeConfig(I2C2, ENABLE); //将应答恢复为使能,为了不影响后续可能产生的读取多字节操作return Data;
}
我们用hal库的IIC通讯方式修改标准库的通讯方式就行了,这么一看hal库的更为简单,只需要调用函数即可,而标准库得我们对事件进行等待,检测,hal库的函数功能更加齐全。
void MPU6050_Init(void)
{/*MPU6050寄存器初始化,需要对照MPU6050手册的寄存器描述配置,此处仅配置了部分重要的寄存器*/MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01); //电源管理寄存器1,取消睡眠模式,选择时钟源为X轴陀螺仪MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00); //电源管理寄存器2,保持默认值0,所有轴均不待机MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09); //采样率分频寄存器,配置采样率MPU6050_WriteReg(MPU6050_CONFIG, 0x06); //配置寄存器,配置DLPFMPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18); //陀螺仪配置寄存器,选择满量程为±2000°/sMPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18); //加速度计配置寄存器,选择满量程为±16g
}
初始化函数里面的对MPU6050的校准这个也得加进去。