前言
前面我们已经使用软件驱动iIC,接下来我们使用硬件来驱动。
其实硬件很简单,懂得软件驱动的原理
写是发个地址+寄存器+数值
读是发个地址+寄存器
HAL库的函数也就是把这些数值填入就可以正常使用
STM32CUBEMX配置
直接把disable换一下就好,其他不用动
IIC的硬件三种使用方式
模式 | 应用场景 |
---|---|
普通 I2C(轮询模式) | 适用于对实时性要求不高、数据传输量小的简单应用,如偶尔读取一个传感器的状态信息。 |
I2C 中断模式(IT I2C) | 适用于对实时性有一定要求、数据传输量中等的场景,如周期性地读取多个传感器的数据。 |
I2C DMA 模式(DMA I2C) | 适用于数据传输量大、对实时性要求高的场景,如大量数据的存储或高速传感器数据的连续采集。 |
普通IIC
普通IIC会用到的函数有
HAL_I2C_Master_Transmit(hi2c, SIMPLE_DEVICE_ADDR << 1, data, size, 1000);
HAL_I2C_Master_Receive(hi2c, (SIMPLE_DEVICE_ADDR << 1) | 1, data, size, 1000);
HAL_I2C_Mem_Write(hi2c, MPU6050_WRITE_ADDR, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
HAL_I2C_Mem_Read(hi2c, MPU6050_READ_ADDR, reg, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000);
主要是这四种
HAL_I2C_Master_Transmit
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
就是简单对某个设备发送什么信息, 不涉及寄存器
HAL_I2C_Master_Receive
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
也只是简单接收,不涉及寄存器的
HAL_I2C_Mem_Read
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);
涉及寄存器的,在我们这个模块就需要对寄存器进行操作,所以我打算是使用这个,会使用这个,再去使用中断和DMA都很简单
HAL_I2C_Mem_Write
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_I2C_Mem_Read
和 HAL_I2C_Mem_Write
多了 MemAddress
和 MemAddSize
这两个参数,用于指定从设备内部的寄存器地址及地址大小,以实现对特定寄存器的读写操作。在使用时,需根据具体的 I2C 通信需求准确设置这些参数。
中断DMA
中断IIC
HAL_I2C_Mem_Read_IT
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_I2C_Mem_Write_IT
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);
DMA IIC
HAL_I2C_Mem_Read_DMA
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_I2C_Mem_Write_DMA
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);
普通IIC驱动MPU6050
我们模仿软件那样填入参数就好了
然后我们要封装下函数
void HAL_MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data) {
HAL_I2C_Mem_Write(&hi2c4, MPU6050_ADDR_AD0_LOW<<1, RegAddress, I2C_MEMADD_SIZE_8BIT, &Data, 1, 1000); // 写入数据到指定寄存器
}
uint8_t HAL_MPU6050_ReadReg(uint8_t RegAddress) {
uint8_t Data;
(&hi2c4, MPU6050_ADDR_AD0_LOW<<1|1, RegAddress, I2C_MEMADD_SIZE_8BIT, &Data, 1, 1000); // 读取指定寄存器的数据
return Data; // 返回读取到的数据
}
一读一些就好了
给寄存器写入数据,一定是地址,要不然功能都失效完
就是data哪里,如果你不想封装,直接填一个0x75获取地址的指令
那么是无效的,必须拿变量存然后放地址才行
然后就正常使用就OK了
示例程序
初始化程序
void HAL_MPU6050_init(void) {
HAL_MPU6050_WriteReg(PWR_MGMT_1, 0x80); // 复位 MPU6050
HAL_Delay(300); // 等待传感器复位
HAL_MPU6050_WriteReg(PWR_MGMT_1, 0x00); // 唤醒 MPU6050
HAL_MPU6050_WriteReg(PWR_MGMT_1, 0x01); // 设置时钟源为 X 轴
HAL_MPU6050_WriteReg(PWR_MGMT_2, 0x00); // 设置所有传感器启用
HAL_MPU6050_WriteReg(SMPLRT_DIV, 0x09); // 设置采样率分频值
HAL_MPU6050_WriteReg(CONFIG, 0x06); // 设置低通滤波器频率
HAL_MPU6050_WriteReg(GYRO_CONFIG, 0x18); // 设置陀螺仪量程为 ±2000 °/s
HAL_MPU6050_WriteReg(ACCEL_CONFIG, 0x18); // 设置加速度计量程为 ±16 g
HAL_Delay(100); // 等待传感器稳定
}
获取ID的程序
uint8_t HAL_MPU6050_GetDeviceID(void) {
uint8_t data;
HAL_I2C_Mem_Read(&hi2c4, MPU6050_ADDR_AD0_LOW<<1|1, WHO_AM_I, I2C_MEMADD_SIZE_8BIT, &data, 1, 1000); // 读取设备 ID 寄存器
return data; // 返回设备 ID
}
以上就是对基本的读和写的使用了