cancel
Showing results for 
Search instead for 
Did you mean: 

I2C2 Busy flag after clock enable

germain
Associate II
Posted on August 25, 2015 at 16:53

I know it's a recurring problem. I could'nt make I2C2 work on my STM32F401VET.

When I use RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

I2C2->SR2 =2

No matter what I do.

I try many work around proposed on this forum but nothing works.

Another weird thing happening is when I set my pin SDA on PB3 to AF, SDA go down.

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // use PB3 and PB10

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; // set output to open drain --> the line has to be only pulled low, not driven high

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // enable pull up resistors

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

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_Init(GPIOB, &GPIO_InitStructure);

// SDA =

HIGH

GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_I2C2); // SDA =LOW

GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // SCL

Someone has faced the same issues ?

#i2c2-sr2-busy-stm32f401
9 REPLIES 9
Posted on August 25, 2015 at 20:21

What's attached to the pins?

If you just configure the pins as GPIO Inputs with Pull-Up, what's the state of the pins then?

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
germain
Associate II
Posted on August 26, 2015 at 16:07

It is an audio codec WM8731, there are also external pull up resitor on SDA and SCL.

At fisrt I thought that it was the codec wich pull low the SDA. But when I put the SDA pin as Input, the line goes HIGH then I set it again to AF it goes LOW.

I also tried to reset the I2C2 after setting the clock, or doing a manual clocking on SCL. But nothing worked. 

kime
Associate
Posted on August 26, 2015 at 23:19

When initializing the GPIO,  init the CLK then the DTA [check your msp hal function ..._I2cHost::ConfigurePins(void)]    I found this on another post and it does fix the startup problem,  depending on the I2C channel the cube sometimes inits both pins at once and other times it does it separately   Seperately is the key.

If an external device is active on the bus:

Reconfigure as GPIO and clock out a byte which is not going to cause problems on your bus.  Eventually the bus busy flag will clear.

If stuck internally (check your transmit flag) like your problem reads:

Request the channel clock out a stop signal and then reset it:

      hI2Cx.Instance->CR1 |= I2C_CR1_STOP;

      perhaps delay

      hI2Cx.Instance->CR1 &= ~I2C_CR1_STOP;

      perhaps delay

      

      hI2Cx.Instance->CR1 |= I2C_CR1_SWRST;

      perhaps delay

      hI2Cx.Instance->CR1 &= ~I2C_CR1_SWRST;

Also its not entirely clear when you indicate the line state.  Is this measured externally with a scope or internally using a status flag of the uP?

germain
Associate II
Posted on August 27, 2015 at 00:17

I use standard periph.

I already try inverting the init of SDA and SCL ( I read the thread you mentioned)

I try your sample of code, it did'nt work :\

I check the state externaly not internaly with a Flag.

Amel NASRI
ST Employee
Posted on August 27, 2015 at 11:00

HiGermain,

Did you tried the workaround consisting on enabling the I2C2 clock (RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);) after GPIO configuration? If it doesn't work, try this order:

// GPIOB clock enable
GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_I2C2); // SDA =LOW
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // SCL
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // use PB3 and PB10
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; // set output to open drain --> the line has to be only pulled low, not driven high
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // enable pull up resistors
GPIO_Init(GPIOB, &GPIO_InitStructure); // init GPIOB
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure); // SDA =HIGH
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

Is there another pins combination that you may use for I2C2? If yes, try it. -Mayla-

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

germain
Associate II
Posted on August 27, 2015 at 18:54

This is how I have done it.

GPIO_DeInit(GPIOA);

GPIO_DeInit(GPIOB);

GPIO_DeInit(GPIOC);

GPIO_DeInit(GPIOD);

GPIO_DeInit(GPIOE);

// GPIO Periph clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // PORTA clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); // PORTB clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); // PORTC clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); // PORTD clock enable

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); // PORTE clock enable

GPIO_InitTypeDef GPIO_InitStructure;

// GPIOB Configuration SCL and SDA pins

// SCL on PB10 and SDA on PB3

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // use PB3 and PB10

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; // set output to open drain --> the line has to be only pulled low, not driven high

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // enable pull up resistors

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

GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C3); // SCL

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

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

GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_I2C3); // SDA

// Configure I2S2_LRCK as alternate function

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_SPI2); // Connect I2S2_LRCK pins to AF5

// Configure I2S2_SD as alternate function

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOC, &GPIO_InitStructure);

// Configure I2S2_MCK as alternate function

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOC, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_SPI2); // Connect I2S2_SD pins to AF5

GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_SPI2); // Connect I2S2_MCK pins to AF5

// Configure I2S2_SCK as alternate function

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOD, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_SPI2); // Connect I2S2_SCK pins to AF5

I2C_InitTypeDef I2C_InitStruct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

// Enable the I2C clock

I2C_DeInit(I2C2);

I2C_InitStruct.I2C_Mode = I2C_Mode_I2C; // I2C mode

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

I2C_InitStruct.I2C_OwnAddress1 = 0x33; // own address, not relevant in master mode

I2C_InitStruct.I2C_Ack = I2C_Ack_Enable; // disable acknowledge when reading (can be changed later on)

I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses

I2C_InitStruct.I2C_ClockSpeed = 100000; // 100kHz

// enable I2C2

I2C_Init(I2C2, &I2C_InitStruct); // init I2C2

I2C_Cmd(I2C2, ENABLE);

I2S_InitTypeDef I2S_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

/* CODEC_I2S peripheral configuration for master TX */

SPI_I2S_DeInit(SPI2);

I2S_InitStructure.I2S_AudioFreq = 48000;

I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;

I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;//extended;

I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;

I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;

I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;

/* Initialize the I2S main channel for TX */

I2S_Init(SPI2, &I2S_InitStructure);

v_I2C_Write16(I2C2, WM8731ADDRESS ,0x0f, 0);

uint8_t i;

/* Load default values */

for(i=0;i<W8731_NUM_REGS;i++)

{

v_I2C_Write16(I2C2, WM8731ADDRESS ,i, w8731_init_data[i]);

}

Mikk Leini
Senior
Posted on August 27, 2015 at 22:23

One thing which looks fishy is that you want to use I2C2 but you configure the pins to alternative function I2C3. Also the I2C2 can be AF9. I guess it should be like this:

PB3 (SDA) should be GPIO_AF9_I2C2

PB10 (SCL) should be GPIO_AF_I2C2

germain
Associate II
Posted on August 28, 2015 at 09:20

Sorry it an artefact I test I2C3 after everything fail on I2C2, I forgot to set it back to I2C2 before the copy and paste on this forum.

So it's not the problem. 

By the way I2C1 and I2C3 look to work fine. I will change my design but I would like to know if I2C2 is usable. 

Mikk Leini
Senior
Posted on August 28, 2015 at 14:12

Of course I2C2 should be usable.

Did you try setting the I2C2 SDA pin to Alternative Function 9 ?