AnsweredAssumed Answered

I2C read from device with STM32F767

Question asked by Pilous Droip on Mar 1, 2018
Latest reply on Mar 1, 2018 by Pilous Droip

Heelo friends.

 

I have STM32F767. And need to read from I2C device. 

I2C device has address 0x4C. Speed is set to 100kHz.

 

This is my INIT I2C peripheral:

uint8_t I2C1_Init(void)

{
   // declare and initialize pins to be used for I2C
   LL_AHB1_GRP1_EnableClock (LL_AHB1_GRP1_PERIPH_GPIOB);
   /* Configure SCL Pin as : Alternate function, High Speed, Open drain, Pull up */
   LL_GPIO_SetPinMode (GPIOB, LL_GPIO_PIN_8, LL_GPIO_MODE_ALTERNATE);
   LL_GPIO_SetAFPin_8_15 (GPIOB, LL_GPIO_PIN_8, LL_GPIO_AF_4);
   LL_GPIO_SetPinSpeed (GPIOB, LL_GPIO_PIN_8, LL_GPIO_SPEED_FREQ_HIGH);
   LL_GPIO_SetPinOutputType (GPIOB, LL_GPIO_PIN_8, LL_GPIO_OUTPUT_OPENDRAIN);
   LL_GPIO_SetPinPull (GPIOB, LL_GPIO_PIN_8, LL_GPIO_PULL_UP);
   /* Configure SDA Pin as : Alternate function, High Speed, Open drain, Pull up */
   LL_GPIO_SetPinMode (I2C1_PORT_SDA, LL_GPIO_PIN_9, LL_GPIO_MODE_ALTERNATE);
   LL_GPIO_SetAFPin_8_15 (I2C1_PORT_SDA, LL_GPIO_PIN_9, LL_GPIO_AF_4);
   LL_GPIO_SetPinSpeed (I2C1_PORT_SDA, LL_GPIO_PIN_9, LL_GPIO_SPEED_FREQ_HIGH);
   LL_GPIO_SetPinOutputType (I2C1_PORT_SDA, LL_GPIO_PIN_9, LL_GPIO_OUTPUT_OPENDRAIN);
   LL_GPIO_SetPinPull (I2C1_PORT_SDA, LL_GPIO_PIN_9, LL_GPIO_PULL_UP);

   // initialize I2C block
   LL_I2C_Disable(I2C1);
   LL_RCC_SetI2CClockSource(LL_RCC_I2C1_CLKSOURCE_PCLK1);
   LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1); // Enable clock for I2C2

   LL_I2C_Disable(I2C1);
   LL_I2C_SetTiming(I2C1,0x60201E2B);   //from CubeMX
   LL_I2C_SetOwnAddress2(I2C1, 0x00, LL_I2C_OWNADDRESS2_NOMASK); // Default

   LL_I2C_Enable(I2C1);

   return 0;
}

 

And my Read function:

uint8_t I2C_ReadChar(I2C_TypeDef *I2Cx, uint8_t Addr, uint8_t Reg, uint8_t *Value, uint8_t size)
{

   LL_I2C_HandleTransfer(I2Cx, (Addr<<1), LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_AUTOEND,    LL_I2C_GENERATE_START_WRITE);

   while(!LL_I2C_IsActiveFlag_STOP(I2Cx)) // Loop until end of transfer received
   {
      /* Indicate the status of Transmit data register empty flag */
      if(LL_I2C_IsActiveFlag_TXE(I2Cx))
      {
         /* Write data in Transmit Data register. */
         LL_I2C_TransmitData8(I2Cx, Reg);
      }
   }

   LL_I2C_HandleTransfer(I2Cx, (Addr<<1), LL_I2C_ADDRSLAVE_7BIT, size,    LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_READ);

   while(!LL_I2C_IsActiveFlag_STOP(I2Cx)) // Loop until end of transfer received 
   {
      /*Check RXNE flag value in ISR register*/
      if(LL_I2C_IsActiveFlag_RXNE(I2Cx))
      {
         /*Read character in Receive Data register.*/
         *Value = LL_I2C_ReceiveData8(I2Cx);
      }
   }

   LL_I2C_ClearFlag_STOP(I2Cx);

   /* all is good, return 0 */
   return 0;
}

 

And my first call this function is OK:

Here is my call function

if(strcmp((char *)uart_reads, "i2c") == 0)
{
   uint8_t data[2];
   I2C_ReadChar(I2C1, 0x4C, 0x00, data, 1);   //i2C addr: 0x4C, reg 0x00, ret. val data, size 1 byte
   itoa(data[0], buffer, 10);
   usart_puts(buffer);
   usart_puts("\r\nI2C finish");
}

 

And my first call this function is OK:

 

But second read from device is wrong.

 

Any idea, what is wrong? 

Outcomes