cancel
Showing results for 
Search instead for 
Did you mean: 

I2C communication issue using LL libraries

rumlyen
Associate II
Posted on November 23, 2016 at 05:57

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);

}

5 REPLIES 5
rumlyen
Associate II
Posted on November 27, 2016 at 16:31

Kindly anyone can help with an idea/advice ?

I've checked left shifted slave address and read/write bit but not seeing any acknowledgement from slave after sending writing address.

What might be the impact of I2C timing value here? I've took the timing value from Cube Tool by putting fast mode with 100ns and 10ns rise and fall time (from examples provided in L4 library). Not much details I found in OV5642 datasheet about these timing values.

Thank you in advance for your reply.
Posted on December 10, 2016 at 19:30

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6qh&d=%2Fa%2F0X0000000bwg%2FuwF75rDmOseoYq4Ef1ez33qb.LeBMD3tRfeLmQueCaM&asPdf=false
joemccarr
Senior
Posted on December 12, 2016 at 14:48

As far as i know you need to use pullups for 12c to work. But you said you got the demo code to work ?

Madhu R
Associate II
Posted on September 26, 2017 at 18:54

hi

Lyen.Rum

Hi ,

. I am also trying to communicate with i2c slave with nucleo-l476 controller. i'm not familier with using LL libraries. I think you successfully worked on it . Can you please share me the working code base.

Thanks and regards,

Madhu R

Posted on September 27, 2017 at 09:57

Hello

madhu.r

,

Have a look to the I2C examplebased on LL driver with STM32CubeL4:

STM32Cube_FW_L4_V1.9.0\Projects\STM32L476RG-Nucleo\Examples_LL\I2C

Best Regards

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen