cancel
Showing results for 
Search instead for 
Did you mean: 

I2C on STM32F4 gets stuck while checking EV6 flag

robertschilling9
Associate II
Posted on May 26, 2012 at 10:14

Hi guys,

I'm working on a STM32F4 Discovery board and trying send over I2C. Therefore I'm using the functions from the Standard Peripheral Library. Unfortunately the device stucks after sending the address while checking the

I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED

Here is my initialization:

#define IMU_I2C I2C1
#define IMU_I2C_CLK RCC_APB1Periph_I2C1
#define IMU_I2C_SCL_PIN GPIO_Pin_6 
#define IMU_I2C_SCL_GPIO_PORT GPIOB 
#define IMU_I2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define IMU_I2C_SCL_SOURCE GPIO_PinSource6
#define IMU_I2C_SCL_AF GPIO_AF_I2C1
#define IMU_I2C_SDA_PIN GPIO_Pin_9 
#define IMU_I2C_SDA_GPIO_PORT GPIOB 
#define IMU_I2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define IMU_I2C_SDA_SOURCE GPIO_PinSource9
#define IMU_I2C_SDA_AF GPIO_AF_I2C1
void
i2c_init(
void
)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
// Enable Clk
RCC_APB1PeriphClockCmd(IMU_I2C_CLK, ENABLE);
RCC_AHB1PeriphClockCmd(IMU_I2C_SCL_GPIO_CLK | IMU_I2C_SDA_GPIO_CLK, ENABLE);
// Performing a Reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC_APB1PeriphResetCmd(IMU_I2C_CLK, ENABLE);
RCC_APB1PeriphResetCmd(IMU_I2C_CLK, DISABLE);
// Remap Pins
GPIO_PinAFConfig(IMU_I2C_SCL_GPIO_PORT, IMU_I2C_SCL_SOURCE, IMU_I2C_SCL_AF);
GPIO_PinAFConfig(IMU_I2C_SDA_GPIO_PORT, IMU_I2C_SDA_SOURCE, IMU_I2C_SDA_AF); 
// Initialize SCL
GPIO_InitStructure.GPIO_Pin = IMU_I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IMU_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
// Initialize SDA
GPIO_InitStructure.GPIO_Pin = IMU_I2C_SDA_PIN;
GPIO_Init(IMU_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
// I2C configuration
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Cmd(IMU_I2C, ENABLE);
I2C_Init(IMU_I2C, &I2C_InitStructure);
}

My sending function is like the examples from ST but it stucks after sending the address while checking the EV6 flag.

void
i2c_write_buf(uint8_t address, uint8_t* buf, int32_t len)
{
while
(I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
/* Send I2C1 START condition */
I2C_GenerateSTART(I2C1, ENABLE);
/* Test on I2C1 EV5 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
/* Send slave Address for write */
I2C_Send7bitAddress(I2C1, address, I2C_Direction_Transmitter);
/* Test on I2C1 EV6 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); 
//I2C stucks here!!!
while
(len--)
{
/* Send I2C1 slave register address */
I2C_SendData(I2C1, *buf++);
/* Test on I2C1 EV8_2 and clear it */
while
(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
}
/* Send I2C1 STOP Condition */
I2C_GenerateSTOP(I2C1, ENABLE); 
}

For initialization and sending I followed the examples from ST. On the I2C pins the is a magnetometer with external pullups. Does anyone know where there is a mistake?? Thanks, Robert #stm32-i2c-master
4 REPLIES 4
robertschilling9
Associate II
Posted on May 26, 2012 at 14:58

My device has a 7-bit address of 0x68 and I do use the one byte left shifted 0xD0.

frankmeyer9
Associate II
Posted on May 27, 2012 at 14:12

At least for the M3 devices, especially the stm32f10x, there is a corresponding entry in the errata sheet. The peripheral my get stuck if not all EV_<x> events are handled.

This issue is supposedly fixed, as tThe stm32f4 errata sheet does not list it.

I must admit, after reading the first posts of frustrated users, I switched back to bit-banging. It's more resource hungry, but works

The 7-bit slave address is a common source of confusion. This address is completed with the access type (read/write), which defines the LSB. Effectively, this forms an 8-bit address, where each device consumes two addresses. You might need to consult the reference manual how the regarding peripheral register handles this.

If you check the bus with a scope, you will need to see a 0xD0 or oxD1 as address, i.e. the left-shifted variant.

robertschilling9
Associate II
Posted on May 27, 2012 at 16:37

Today I found out that the schematic for my breakout board was wrong. My chip does not use address 0x68 - it uses 0x69. For this reason I got no ACK and therefore the communication stucked.

raminmoshiri
Associate
Posted on September 01, 2013 at 02:12

I have same problem getting stuck on EV6 using I2C1 (PB08 & PB09) on a 

STM32F4 Discovery board with BB and Display.

I shift the 7-bit Slave address and verify proper bits on SDA followed by the

slave ACK on SDA. I can verify that using the wrong address, I do not get 

the ACK from the slave on SDA.

My problem with getting stuck at EV6 is that STM32F4 gives a 10-bit Address

ACK (I2C_EVENT_MASTER_MODE_ADDRESS10) instead of 7-bit address

ACK (I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED).

Below is my initialization, configuring 7-bit address mode.  please advise.

-Ramin

___________________________________________________________

/*******************************************************************************

* Function Name  : I2C_BusInit

* Description    : Configure I2C-Bus

* Input          : None

* Output         : None

* Return         : None

* Attention     : None

*******************************************************************************/

void I2C_BusInit(void)

{

  GPIO_InitTypeDef GPIO_InitStructure;

  I2C_InitTypeDef   I2C_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

  uint32_t timeout = (100 * I2C_TIMEOUT); // RAMIN

  int i; // Ramin

//  I2C_DeInit(Open_I2C);

  //=========================================================================================

  // Enable I2C CLOCK

  //-----------------------------------------------------------------------------------------

  RCC_APB1PeriphClockCmd(Open_I2C_CLK, ENABLE);

  //=========================================================================================

  //  Enable GPIO CLOCK: For the SCL/SDA Pins

  //-----------------------------------------------------------------------------------------

  RCC_AHB1PeriphClockCmd(Open_I2C_SCL_GPIO_CLK | Open_I2C_SDA_GPIO_CLK, ENABLE);

  //RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // ??????????????????

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

  // Performing a Reset

  RCC_APB1PeriphResetCmd(Open_I2C_CLK, ENABLE); // ?

  RCC_APB1PeriphResetCmd(Open_I2C_CLK, DISABLE); // ?

  //=========================================================================================

  // Pemap Pins: GPIO Alternate functions configuration (Connect GPIO pins to peripheral)

  //-----------------------------------------------------------------------------------------

  GPIO_PinAFConfig(Open_I2C_SCL_GPIO_PORT, Open_I2C_SCL_SOURCE, Open_I2C_SCL_AF);

  GPIO_PinAFConfig(Open_I2C_SDA_GPIO_PORT, Open_I2C_SDA_SOURCE, Open_I2C_SDA_AF);

  // ********************************************************************************

//  for (i=0; i<timeout; i++); //  *****************   DELAY   HARD CODED ******************

  // ********************************************************************************

  //=========================================================================================

  // GPIO INITIALIZATION: Configure I2C SCL & SDA GPIO pins

  //-----------------------------------------------------------------------------------------

/* You can connect I2C1 to two different

* pairs of pins:

* 1. SCL on PB6 and SDA on PB7

* 2. SCL on PB8 and SDA on PB9

GPIO_Pin_6, GPIO_Pin_7 for PB6 and PB7

GPIO_Pin_8, GPIO_Pin_9 for PB8 and PB9 */

  //-----------------------------------------------------------------------------------------

  GPIO_InitStructure.GPIO_Pin = Open_I2C_SCL_PIN;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // set pins to alternate function

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // set GPIO speed

  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // Open Drain GPIO_OType_OD --> Line has to be only pulled low, not driven high GPIO_OType_PP

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // enable pull up resistors ??????  GPIO_PuPd_UP;  (GPIO_PuPd_NOPULL)

//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; // enable pull up resistors ??????  GPIO_PuPd_UP;  (GPIO_PuPd_NOPULL)

  /* Configure I2C pins: SCL */

  GPIO_Init(Open_I2C_SCL_GPIO_PORT, &GPIO_InitStructure); // init GPIOB

  /* Configure I2C pins: SDA */

  GPIO_InitStructure.GPIO_Pin = Open_I2C_SDA_PIN;

  GPIO_Init(Open_I2C_SCL_GPIO_PORT, &GPIO_InitStructure); // init GPIOB

  //=========================================================================================

  // Configure I2C CONTROLLER

  //                              Apply I2C configuration after enabling it

  //-----------------------------------------------------------------------------------------

  I2C_InitStructure.I2C_ClockSpeed = I2C_SCL_SPEED; // 100 KHz   (400kHz = Fast Mode)

  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // I2C mode

  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard

  I2C_InitStructure.I2C_OwnAddress1 = 0; // I2C_OWN_ADDR; // own address, not relevant in master mode

  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // I2C_Ack_Enable/I2C_Ack_Disable; Disable ACK when reading (can be changed later on)

  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

  //=========================================================================================

  // Enable I2C PORT

  //-----------------------------------------------------------------------------------------

  I2C_Cmd(Open_I2C, ENABLE);

  I2C_Init(Open_I2C, &I2C_InitStructure);

  //=========================================================================================

  // Configure the SPI interrupt priority

  //-----------------------------------------------------------------------------------------

//NVIC_InitStructure.NVIC_IRQChannel = Open_I2C_IRQn;

//  NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;

//  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

//  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

//  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

//  NVIC_Init(&NVIC_InitStructure);

//  I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT, ENABLE);

//  I2C_ITConfig(I2C2, I2C_IT_BUF | I2C_IT_EVT, ENABLE);

//  I2C_GenerateSTART(I2C1, ENABLE);

}