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 为写数据

函数实现步骤:

  1. 初始化 I2C 控制器。
  2. 发送 START 信号。
  3. 发送设备地址和写指令。
  4. 发送写指令数组。
  5. 发送 RESTART 信号(如果需要读数据)。
  6. 发送设备地址和读指令(如果需要读数据)。
  7. 接收数据数组(如果需要读数据)。
  8. 发送 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);
I2C 通信函数实现 - 使用 LL 库读写时序

原文地址: https://www.cveoy.top/t/topic/nghv 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录