AnsweredAssumed Answered

I2C communication issue using LL libraries

Question asked by Lyen.Rum on Nov 23, 2016
Latest reply on Sep 27, 2017 by Imen D
Hello All,

I'm struggling with I2C communication with L476 using LL libraries. In my custom board, a OV5642 camera is connected with I2C1 and a LSM6DS3 IMU with I2C3. Previously I've configured I2C RTC with L151 (by waiting for events) using Std Peripheral libraries. But, I'm missing some flags in L476. Also, L476 doesn't have support for SPL.

I successfully ran the example I2C Polling code (provided in L4cube library) between two L476 Nucleo boards. I followed the same code here, but, I'm not receiving any value or seeing any clock (oscilloscope) in I2C SCL lines. I'm wondering what I am doing wrong here. In board, I2C lines are connected directly to devices without any external pull-ups.

I request your kind suggestion. I'm not much sure about set timing things, I took the value from Cube Tool for PLCK clock and I2C fast mode.

My configurations as follows:

//LSM6DS3_ADDRESS = 0x6B

void LSM6DS3_I2C_Init(void){     // SCL on PC.0, SDA on PC.1  
  LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOC);

  /* Configure SCL Pin as : Alternate function, High Speed, Open drain, Pull up */
  LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_0, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_0, LL_GPIO_AF_4);
  LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_0, LL_GPIO_SPEED_FREQ_VERY_HIGH);
  LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_0, LL_GPIO_OUTPUT_OPENDRAIN);
  LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_0, LL_GPIO_PULL_UP);

  /* Configure SDA Pin as : Alternate function, High Speed, Open drain, Pull up */
  LL_GPIO_SetPinMode(GPIOC, LL_GPIO_PIN_1, LL_GPIO_MODE_ALTERNATE);
  LL_GPIO_SetAFPin_0_7(GPIOC, LL_GPIO_PIN_1, LL_GPIO_AF_4);
  LL_GPIO_SetPinSpeed(GPIOC, LL_GPIO_PIN_1, LL_GPIO_SPEED_FREQ_VERY_HIGH);
  LL_GPIO_SetPinOutputType(GPIOC, LL_GPIO_PIN_1, LL_GPIO_OUTPUT_OPENDRAIN);
  LL_GPIO_SetPinPull(GPIOC, LL_GPIO_PIN_1, LL_GPIO_PULL_UP);

  /* Enable the peripheral clock for I2C3 */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
    
  LL_RCC_SetI2CClockSource(LL_RCC_I2C3_CLKSOURCE_PCLK1);
    
  LL_I2C_Disable(I2C3);
 
  /* Configure the SDA setup, hold time and the SCL high, low period */

  LL_I2C_SetTiming(I2C3, 0x0040131E); // Time found from Cube Tool for Fast mode, 400 KHz, 100ns Rise time, 10ns Fall time
 
  LL_I2C_SetOwnAddress2(I2C3, 0x00, LL_I2C_OWNADDRESS2_NOMASK); // Default
    
  LL_I2C_Enable(I2C3);
}

// Same for I2C1 camera

void LSM6DS3_I2C_Write(uint8_t Addr, uint8_t Data)
{
uint8_t TxBuffer[] = {Addr,Data};
uint8_t TxIndex;
uint8_t ubNbDataToTransmit_I2c=2;
LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2c, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);

while(!LL_I2C_IsActiveFlag_STOP(I2C3))  // Loop until end of transfer received (STOP flag raised)
 {
    /* Check TXIS flag value in ISR register */
   if(LL_I2C_IsActiveFlag_TXIS(I2C3))
    {
      /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */
      LL_I2C_TransmitData8(I2C3, TxBuffer[TxIndex]);
      TxIndex++;
    }
 }
 
/* End of I2C_SlaveReceiver_MasterTransmitter Process */
LL_I2C_ClearFlag_STOP(I2C3);
}

void LSM6DS3_I2C_Read(uint8_t Addr)
{
uint8_t ubNbDataToTransmit_I2C=1;
LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);

while(!LL_I2C_IsActiveFlag_STOP(I2C3))  // Loop until end of transfer received (STOP flag raised)
 {
    /* Check TXIS flag value in ISR register */
   if(LL_I2C_IsActiveFlag_TXIS(I2C3))
    {
      /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */
      LL_I2C_TransmitData8(I2C3, Addr);
    }
 }

LL_I2C_HandleTransfer(I2C3, LSM6DS3_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);

while(!LL_I2C_IsActiveFlag_STOP(I2C3))  // Loop until end of transfer received (STOP flag raised)
{
 /* Check RXNE flag value in ISR register */
if(LL_I2C_IsActiveFlag_RXNE(I2C3))
{      
/* Read character in Receive Data register. RXNE flag is cleared by reading data in RXDR register */
  RxBuffer[BufferIndex++] = LL_I2C_ReceiveData8(I2C3);  
}
}
LL_I2C_ClearFlag_STOP(I2C3);
}


// For Camera I2C communication

void DCMI_SingleRandomWrite(uint16_t Addr, uint8_t Data)
{
uint8_t TxBuffer[] = {(uint8_t)(Addr>>8),(uint8_t)(Addr),Data};
uint8_t TxIndex;
uint8_t ubNbDataToTransmit_I2C=3;
LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_WRITE_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);

while(!LL_I2C_IsActiveFlag_STOP(I2C1))  // Loop until end of transfer received (STOP flag raised)
 {
    /* Check TXIS flag value in ISR register */
   while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
 {
      /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */
      LL_I2C_TransmitData8(I2C1, TxBuffer[TxIndex]);
      TxIndex++;
 }
}
  /* End of I2C_SlaveReceiver_MasterTransmitter Process */
  LL_I2C_ClearFlag_STOP(I2C1);
}


void DCMI_SingleRandomRead(uint16_t Addr)
{
uint8_t TxBuffer[] = {(uint8_t)(Addr>>8),(uint8_t)(Addr)};
uint8_t TxIndex;
uint8_t ubNbDataToTransmit_I2C=2;
LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_WRITE_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, ubNbDataToTransmit_I2C, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);


while(!LL_I2C_IsActiveFlag_STOP(I2C1))  // Loop until end of transfer received (STOP flag raised)
 {
    /* Check TXIS flag value in ISR register */
   while(!LL_I2C_IsActiveFlag_TXIS(I2C1));
 {
      /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */
      LL_I2C_TransmitData8(I2C1, TxBuffer[TxIndex]);
      TxIndex++;
 }
}
  /* End of I2C_SlaveReceiver_MasterTransmitter Process */
  LL_I2C_ClearFlag_STOP(I2C1);
}


LL_I2C_HandleTransfer(I2C1, OV9655_DEVICE_READ_ADDRESS, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);
while(!LL_I2C_IsActiveFlag_STOP(I2C1))  // Loop until end of transfer received (STOP flag raised)
  {
 /* Check RXNE flag value in ISR register */
  if(LL_I2C_IsActiveFlag_RXNE(I2C1))
    {
      /* Write data in Transmit Data register. TXIS flag is cleared by writing data in TXDR register */
      Camera_Reg_Value = LL_I2C_ReceiveData8(I2C1);
    }
  }
  LL_I2C_ClearFlag_STOP(I2C1);
}

Outcomes