I2C 通信函数实现 - 使用 LL 库读写时序
void I2CTransfer(uint16_t deviceAddr, uint8_t cmdArray[], uint8_t dataArray[], uint16_t cmdLen, uint16_t dataLen, uint16_t flag)
{
// 初始化I2C控制器
LL_I2C_InitTypeDef i2c_init;
LL_I2C_StructInit(&i2c_init);
i2c_init.PeripheralMode = LL_I2C_MODE_I2C;
i2c_init.Timing = I2C_TIMING;
LL_I2C_Init(I2C_PORT, &i2c_init);
// 发送START信号
LL_I2C_GenerateStartCondition(I2C_PORT);
// 等待START信号发送完毕
while(!LL_I2C_IsActiveFlag_SB(I2C_PORT));
// 发送设备地址和写指令
LL_I2C_TransmitData8(I2C_PORT, deviceAddr << 1);
// 等待设备地址发送完毕
while(!LL_I2C_IsActiveFlag_ADDR(I2C_PORT));
// 清除ADDR标志位
LL_I2C_ClearFlag_ADDR(I2C_PORT);
// 发送写指令
for(uint16_t i=0; i<cmdLen; i++)
{
LL_I2C_TransmitData8(I2C_PORT, cmdArray[i]);
// 等待数据发送完毕
while(!LL_I2C_IsActiveFlag_TXE(I2C_PORT));
}
// 发送RESTART信号
if(flag == I2C_FLAG_WRITE_READ)
{
LL_I2C_GenerateStartCondition(I2C_PORT);
// 等待START信号发送完毕
while(!LL_I2C_IsActiveFlag_SB(I2C_PORT));
// 发送设备地址和读指令
LL_I2C_TransmitData8(I2C_PORT, (deviceAddr << 1) | 0x01);
// 等待设备地址发送完毕
while(!LL_I2C_IsActiveFlag_ADDR(I2C_PORT));
// 清除ADDR标志位
LL_I2C_ClearFlag_ADDR(I2C_PORT);
// 接收数据
for(uint16_t i=0; i<dataLen-1; i++)
{
while(!LL_I2C_IsActiveFlag_RXNE(I2C_PORT));
dataArray[i] = LL_I2C_ReceiveData8(I2C_PORT);
}
// 发送NACK
LL_I2C_AcknowledgeNextData(I2C_PORT, LL_I2C_NACK);
// 接收最后一个数据
while(!LL_I2C_IsActiveFlag_RXNE(I2C_PORT));
dataArray[dataLen-1] = LL_I2C_ReceiveData8(I2C_PORT);
}
else if(flag == I2C_FLAG_WRITE_WRITE)
{
// 发送写数据
for(uint16_t i=0; i<dataLen; i++)
{
LL_I2C_TransmitData8(I2C_PORT, dataArray[i]);
// 等待数据发送完毕
while(!LL_I2C_IsActiveFlag_TXE(I2C_PORT));
}
}
// 发送STOP信号
LL_I2C_GenerateStopCondition(I2C_PORT);
}
该函数使用 STM32 LL 库实现 I2C 通信,支持写数据、读数据、以及写数据后读数据三种模式。
函数参数:
deviceAddr: 设备地址cmdArray: 写指令数组dataArray: 数据数组cmdLen: 写指令数组长度dataLen: 数据数组长度flag: 操作模式,I2C_FLAG_WRITE_READ为写数据后读数据,I2C_FLAG_WRITE_WRITE为写数据
函数实现步骤:
- 初始化 I2C 控制器。
- 发送 START 信号。
- 发送设备地址和写指令。
- 发送写指令数组。
- 发送 RESTART 信号(如果需要读数据)。
- 发送设备地址和读指令(如果需要读数据)。
- 接收数据数组(如果需要读数据)。
- 发送 STOP 信号。
注意事项:
I2C_PORT需要替换为实际的 I2C 端口号。I2C_TIMING需要根据实际情况进行配置。- 该函数没有处理错误情况,需要根据实际情况进行处理。
示例:
// 写数据
uint8_t writeData[] = {0x01, 0x02, 0x03};
I2CTransfer(0x40, NULL, writeData, 0, 3, I2C_FLAG_WRITE_WRITE);
// 写数据后读数据
uint8_t cmd[] = {0x00};
uint8_t readData[2];
I2CTransfer(0x40, cmd, readData, 1, 2, I2C_FLAG_WRITE_READ);
原文地址: https://www.cveoy.top/t/topic/nghv 著作权归作者所有。请勿转载和采集!