STM32G031K LL庫的使用 - IIC

說明:驅動基於STm32G031K6,其他型號需自行做改動。

注:因爲之前項目暫未用到LL庫的IIC,所以此驅動未經過實機驗證。歡迎反饋使用中的問題。

IIC的初始化: CubeMX生成

void STM32LLI2C1_Init(void)
{
  LL_I2C_InitTypeDef I2C_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  /**I2C1 GPIO Configuration  
  PA9   ------> I2C1_SCL
  PA10   ------> I2C1_SDA 
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_9|LL_GPIO_PIN_10;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_6;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* Peripheral clock enable */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);

  /** I2C Initialization 
  */
  I2C_InitStruct.PeripheralMode = LL_I2C_MODE_I2C;
  I2C_InitStruct.Timing = 0x00303D5B;
  I2C_InitStruct.AnalogFilter = LL_I2C_ANALOGFILTER_ENABLE;
  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);
  LL_I2C_EnableAutoEndMode(I2C1);
  LL_I2C_SetOwnAddress2(I2C1, 0, LL_I2C_OWNADDRESS2_NOMASK);
  LL_I2C_DisableOwnAddress2(I2C1);
  LL_I2C_DisableGeneralCall(I2C1);
  LL_I2C_EnableClockStretching(I2C1);
  LL_I2C_Enable(I2C1);
}

由於LL庫未提供與HAL類似的I2C多數據讀取的函數接口,所以需要自行編寫函數,我這裏是參照HAL庫內的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read寫的LL庫可使用的相對應函數。

I2C讀多個數據:

void STM32I2C1_MasterRead(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
{
    //等待iic空閒
    while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    //確認iic是否使能
    if(!LL_I2C_IsEnabled(I2C1))
    {
        LL_I2C_Enable(I2C1);
    }
    //配置
    LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_SOFTEND_MODE,I2C_GENERATE_START_WRITE);
    while(!LL_I2C_IsActiveFlag_TXIS(I2C1));

    //寫入從設備寄存器地址
    ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    while(!LL_I2C_IsActiveFlag_TC(I2C1));

    //配置
    LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_GENERATE_START_READ);

    //讀取數據
    ucBSP_I2C1_ReadMultipleData(pdata,length);

    //等待停止完成
    while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    LL_I2C_ClearFlag_STOP(I2C1);
}

I2C寫多個數據:

void STM32I2C1_MasterWrite(uint8_t device_7BitAddr, uint16_t mem_address,uint16_t mem_size,uint8_t *pdata,uint8_t length)
{
    //等待iic空閒
    while(LL_I2C_IsActiveFlag_BUSY(I2C1));
    //確認iic是否使能
    if(!LL_I2C_IsEnabled(I2C1))
    {
        LL_I2C_Enable(I2C1);
    }
    //配置爲寫
    LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,mem_size,I2C_RELOAD_MODE,I2C_GENERATE_START_WRITE);
    while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
    
    //寫入從設備寄存器地址
    ucBSP_I2C1_WriteMemAddr(mem_address,mem_size);
    while(!LL_I2C_IsActiveFlag_TCR(I2C1));

    //重新配置爲自動停止模式
    LL_I2C_HandleTransfer(I2C1,device_7BitAddr,LL_I2C_ADDRSLAVE_7BIT,length,I2C_AUTOEND_MODE,I2C_NO_STARTSTOP);

    //寫數據
    ucBSP_I2C1_WriteMultipleData(pdata,length);

    //等待停止完成
    while(!LL_I2C_IsActiveFlag_STOP(I2C1));
    LL_I2C_ClearFlag_STOP(I2C1);
}

爲了減少代碼重複和增加可讀性,對讀寫的一些過程另作了函數;

寫寄存器地址:

void STM32I2C1_WriteMemAddr(uint16_t mem_address,uint16_t mem_size)
{
    uint8_t MemAddrLSB = I2C_MEM_ADD_LSB(mem_address);;
    uint8_t MemAddrMSB = I2C_MEM_ADD_MSB(mem_address);;

    //發送器件寄存器地址
    if(mem_size == I2C_MEMADD_SIZE_8BIT)
    {
        LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    }else{
        LL_I2C_TransmitData8(I2C1, MemAddrMSB);
        //等待發送完成
        while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
        LL_I2C_TransmitData8(I2C1, MemAddrLSB);
    }
}

連續寫入小於255個數據:

void STM32I2C1_WriteMultipleData(uint8_t *pdata,uint8_t length)
{
    uint8_t count;
    for(count=0;count<length; count++)
    {
        //等待發送完成
        while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
        LL_I2C_TransmitData8(I2C1, *(pdata+count));
    }
}

連續讀取小於255個數據:

void STM32I2C1_ReadMultipleData(uint8_t *pdata,uint8_t length)
{
    uint8_t count;
    for(count=0;count<length; count++)
    {
        //等待接收非空
        while(!LL_I2C_IsActiveFlag_RXNE(I2C1));
        *(pdata+count) = LL_I2C_ReceiveData8(I2C1);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章