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_InitStruct = {0};
    LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

    if(deviceAddr == BQ27441_G1_ADDR)
    {
        // 使能I2C外设时钟
        LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

        // 配置I2C外设参数
        I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
        I2C_InitStruct.Timing = 0x00707CBB;
        I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_DISABLE;
        I2C_InitStruct.DigitalFilter = 0;
        I2C_InitStruct.OwnAddress1 = 0;
        I2C_InitStruct.TypeAcknowledge = LL_I2C_ACK;
        I2C_InitStruct.OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
        LL_I2C_Init(I2C1, &I2C_InitStruct);

        // 配置I2C外设GPIO
        GPIO_InitStruct.Pin = LL_GPIO_PIN_6 | LL_GPIO_PIN_7;
        GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
        GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
        GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
        GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
        GPIO_InitStruct.Alternate = LL_GPIO_AF_4;
        LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    }

    // 开始I2C传输
    LL_I2C_Enable(I2C1);
    
    // 发送起始条件
    LL_I2C_GenerateStartCondition(I2C1);
    
    // 等待起始条件设置完成
    while(!LL_I2C_IsActiveFlag_SB(I2C1));

    // 发送器件地址
    LL_I2C_TransmitData8(I2C1, deviceAddr << 1);
    
    // 等待地址发送完成
    while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
    LL_I2C_ClearFlag_ADDR(I2C1);
    
    // 发送命令
    for(uint16_t i = 0; i < cmdLen; i++)
    {
        LL_I2C_TransmitData8(I2C1, cmdArray[i]);
        while(!LL_I2C_IsActiveFlag_TXE(I2C1));
    }
    
    // 等待数据发送完成
    while(!LL_I2C_IsActiveFlag_TXE(I2C1));

    // 发送停止条件
    LL_I2C_GenerateStopCondition(I2C1);
    
    // 等待停止条件设置完成
    while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    LL_I2C_ClearFlag_STOP(I2C1);

    // 读取或写入数据
    if(flag == I2C_FLAG_WRITE_READ)
    {
        // 发送起始条件
        LL_I2C_GenerateStartCondition(I2C1);
        
        // 等待起始条件设置完成
        while(!LL_I2C_IsActiveFlag_SB(I2C1));

        // 发送器件地址
        LL_I2C_TransmitData8(I2C1, deviceAddr << 1 | 1);
        
        // 等待地址发送完成
        while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
        LL_I2C_ClearFlag_ADDR(I2C1);
        
        // 读取数据
        for(uint16_t i = 0; i < dataLen; i++)
        {
            if(i == dataLen - 1)
            {
                LL_I2C_AcknowledgeNextValue(I2C1, LL_I2C_NACK);
            }
            
            while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
            dataArray[i] = LL_I2C_ReceiveData8(I2C1);
        }
        
        // 发送停止条件
        LL_I2C_GenerateStopCondition(I2C1);
        
        // 等待停止条件设置完成
        while(!LL_I2C_IsActiveFlag_STOP(I2C1));
        LL_I2C_ClearFlag_STOP(I2C1);
    }
    else if(flag == I2C_FLAG_WRITE_WRITE)
    {
        // 发送起始条件
        LL_I2C_GenerateStartCondition(I2C1);
        
        // 等待起始条件设置完成
        while(!LL_I2C_IsActiveFlag_SB(I2C1));

        // 发送器件地址
        LL_I2C_TransmitData8(I2C1, deviceAddr << 1);
        
        // 等待地址发送完成
        while(!LL_I2C_IsActiveFlag_ADDR(I2C1));
        LL_I2C_ClearFlag_ADDR(I2C1);
        
        // 写入数据
        for(uint16_t i = 0; i < dataLen; i++)
        {
            LL_I2C_TransmitData8(I2C1, dataArray[i]);
            while(!LL_I2C_IsActiveFlag_TXE(I2C1));
        }
        
        // 发送停止条件
        LL_I2C_GenerateStopCondition(I2C1);
        
        // 等待停止条件设置完成
        while(!LL_I2C_IsActiveFlag_STOP(I2C1));
        LL_I2C_ClearFlag_STOP(I2C1);
    }

    // 禁用I2C传输
    LL_I2C_Disable(I2C1);
}

使用说明:

  • deviceAddr: 器件地址,左移一位用于设置7位地址模式
  • cmdArray: 命令数组
  • dataArray: 数据数组
  • cmdLen: 命令数组长度
  • dataLen: 数据数组长度
  • flag: 传输类型,I2C_FLAG_WRITE_READ 为写命令后读数据,I2C_FLAG_WRITE_WRITE 为写命令后写数据

代码说明:

  • 函数首先初始化 I2C 外设和 GPIO,并使能 I2C 时钟。
  • 然后发送起始条件和器件地址。
  • 根据传输类型,发送命令数组和数据数组。
  • 最后发送停止条件,并等待传输完成。

注意事项:

  • 确保 I2C 时钟频率和 I2C 传输速度匹配器件的要求。
  • 注意 I2C 传输过程中可能会出现错误,需要添加错误处理机制。
  • 该代码示例仅供参考,实际应用中可能需要进行修改和调整。
I2C 传输函数 - STM32 LL 库实现

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

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