STM32 I2C 驱动程序:利用 LL 库实现 I2C 读写操作
void I2CTransfer(uint16_t deviceAddr, uint8_t cmdArray[], uint8_t dataArray[], uint16_t cmdLen, uint16_t dataLen, uint16_t flag)
{
// 根据flag确定读写方式
if(flag == I2C_FLAG_WRITE_READ)
{
// 发送写命令
LL_I2C_Enable(I2C1);
LL_I2C_HandleTransfer(I2C1, deviceAddr, LL_I2C_ADDRSLAVE_7BIT, cmdArray, cmdLen, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
// 接收数据
LL_I2C_HandleTransfer(I2C1, deviceAddr, LL_I2C_ADDRSLAVE_7BIT, dataArray, dataLen, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
}
else if (flag == I2C_FLAG_WRITE_WRITE)
{
// 发送写命令和数据
uint8_t writeBuffer[cmdLen + dataLen];
memcpy(writeBuffer, cmdArray, cmdLen);
memcpy(writeBuffer + cmdLen, dataArray, dataLen);
LL_I2C_Enable(I2C1);
LL_I2C_HandleTransfer(I2C1, deviceAddr, LL_I2C_ADDRSLAVE_7BIT, writeBuffer, cmdLen + dataLen, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
while (!LL_I2C_IsActiveFlag_TXE(I2C1));
while (!LL_I2C_IsActiveFlag_STOP(I2C1));
}
}
static uint16_t i2cReadRegister(uint16_t addr,uint8_t regOffset)
{
uint16_t result = 0x00;
uint8_t cmdArray[1];
uint8_t dataArray[2];
cmdArray[0] = regOffset;
I2CTransfer(addr << 1, cmdArray, dataArray, 1, 2, I2C_FLAG_WRITE_READ );
result = (dataArray[1] << 8) | (dataArray[0]);
return result;
return dataArray[0];
}
static void i2cWriteRegister(uint16_t addr,uint8_t regOffset, uint8_t writeData)
{
uint8_t cmdArray[1];
uint8_t dataArray[2];
cmdArray[0] = regOffset;
dataArray[0] = writeData;
I2CTransfer(addr << 1, cmdArray, dataArray, 1, 2, I2C_FLAG_WRITE_WRITE );
}
函数说明:
- I2CTransfer: 该函数根据传入的
flag参数,选择执行 I2C 写操作或者读写操作。 - i2cReadRegister: 该函数用于从指定 I2C 设备的指定寄存器读取数据。
- i2cWriteRegister: 该函数用于向指定 I2C 设备的指定寄存器写入数据。
代码示例:
// 初始化 I2C1
LL_I2C_InitTypeDef I2C_InitStruct = {0};
I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
I2C_InitStruct.ClockSpeed = 400000;
I2C_InitStruct.DutyCycle = LL_I2C_DUTYCYCLE_2;
I2C_InitStruct.OwnAddress1 = 0x00;
I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
I2C_InitStruct.OwnAddress2 = 0x00;
LL_I2C_Init(I2C1, &I2C_InitStruct);
LL_I2C_Enable(I2C1);
// 读取寄存器
uint16_t data = i2cReadRegister(0x48, 0x00);
// 写入寄存器
i2cWriteRegister(0x48, 0x01, 0x55);
注意事项:
- 确保正确配置 I2C 模块和引脚。
- 修改代码中的 I2C 设备地址和寄存器地址。
- 使用前请参考 STM32 的官方文档以确保正确使用 LL 库。
优化建议:
- 使用
LL_I2C_HandleTransfer函数代替LL_I2C_Transmit和LL_I2C_Receive函数,提高代码效率。 - 使用循环语句来检查 I2C 传输状态,避免死锁。
- 在代码中添加错误处理机制,例如检查 I2C 传输是否成功。
- 使用更具体的函数名称,例如
I2c_ReadRegister和I2c_WriteRegister,以提高代码可读性。
总结:
本代码提供了一个简单而实用的 STM32 I2C 驱动程序,可用于与 I2C 设备进行通信。通过代码优化,可以提高代码效率和可读性。
原文地址: https://www.cveoy.top/t/topic/nggU 著作权归作者所有。请勿转载和采集!