AnsweredAssumed Answered

STM32F407 I2C Issue

Question asked by TheMeerd on Oct 15, 2014
Hello Everyone,

We have a specific module connected to stm32f4 discovery through I2C bus. Whatever I2C interface I have tried, it did not work. Better to say, the MCU send address to the module and also the first byte of the data. However, when it comes to send second byte it does not pass     while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); check. I also had a look at the connections with a logic analyzer and see that after sending write address and the first byte, the MCU gets ACK from the module. After sending the second byte it gets a NACK unexpectedly. We are able to send same data through Arduino however STM32F4 fails. Please see the configuration and test code below. Any ideas would be appreciated.

I2C Addressing: 7 Bit
I2C Clock: 400 KHz
MCU Clock: 168 MHz
APB1 Clock: 42 MHz



#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_i2c.h"
#include "misc.h"
 
void KM_I2C_Init(I2C_TypeDef *I2Cx)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  I2C_InitTypeDef I2C_InitStruct;
   
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
   
  if (I2Cx == I2C1) {
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;  
    GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); 
  } else {
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;  
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;  
    GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); 
  }
   
  I2C_DeInit(I2Cx);
  I2C_StructInit(&I2C_InitStruct);
  I2C_InitStruct.I2C_ClockSpeed = 400000;
  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
  I2C_Init(I2Cx, &I2C_InitStruct);
}
        
 
void KM_Read(I2C_TypeDef *I2Cx, uint8_t addr, uint8_t *buf)
{
  int idx = 0;
  size_t len = 0xFFFF;
   
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
   
  I2C_GenerateSTART(I2Cx, ENABLE);
 
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
   
  I2C_Send7bitAddress(I2Cx, addr << 1, I2C_Direction_Receiver);
  I2C_AcknowledgeConfig(I2Cx, ENABLE);
   
  for (idx = 0; idx < (int) len; idx++) {
    if (idx == ((int) len - 1)) {
        I2C_AcknowledgeConfig(I2Cx, DISABLE);
        printf("0x%02x \n", buf[idx]);
        I2C_GenerateSTOP(I2Cx, ENABLE);
    }
 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));
     
    buf[idx] = I2C_ReceiveData(I2Cx);
     
    if (idx == 0) {
      /* First byte states length of the remaining data. */
      len = *(uint8_t *)buf + 1;
      printf("\nReceived: ");
    }
     
    printf("0x%02x ", ((uint8_t *)buf)[idx]);
  }
}
 
 
void KM_Write(I2C_TypeDef *I2Cx, uint8_t addr, const uint8_t *buf)
{
  volatile uint32_t delay = 0;
  size_t len = buf[0] + 1;
  uint32_t idx;
   
  addr <<= 1; /* / 7 Bit Addressing */
  while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));
 
  I2C_GenerateSTART(I2Cx, ENABLE);
 
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));
 
  I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Transmitter);
   
  while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
   
  printf("Sent: ");
   
  /* !!! Hangs in the second cycle !!! */
  for (idx = 0; idx < len; idx++, delay = 0) {
    I2C_SendData(I2Cx, buf[idx]);
    printf("0x%02x ", buf[idx]);
 
    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  }
 
  I2C_GenerateSTOP(I2Cx, ENABLE);
}
    
static void FTest_Task(void *arg)
{
  char buf_send[] = { 0x05, 0x51, 0x00, 0x0B, 0x10, 0x01 };
  const char slaveAddr = 0x8;
  char buf_recv[16];
   
  KM_I2C_Init(I2C1);
                   
  for (;;) {
    KM_Write(I2C1, slaveAddr, buf_send);
    KM_Read(I2C1, slaveAddr, buf_recv);
  }
}

Outcomes