cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L151RB I2C Busy flag always set

alby87
Associate II
Posted on February 17, 2014 at 23:55

Hi!

I've a custom made board with STM32L15RB microcontroller. My I2C1 is not working well: I see the Busy flag going SET when I activate the APB1 Clock (RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);)

With a logic probe, I notice that both CLOCK and DATA are high (pullup resistors installed).

When I set them in alternate function (first I set them using PinAFConfig, and them in mode AF) they goes immediatly low. They are set at 2MHz, pushpull and nopull.

I tested to manualy force a clock signal (going up and down in out mode for CLOCK signal): the logic probe sees the square wave, but the DATA (set in AF I2C mode) wouldn't get up.

If I ignore the Busy flag (STM32 is the only master, there are three slaves), and generate a START, it wouldn't pass this piece of code''while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));'' and no interrupt are generated.

FYI, this is the clock configuration:

HSE=16MHz, PLLMUL 6, PLLDIV 3, SYSCLK 32000 , AHB PRESCALER 2, HCLK 16000, APB1 and APB2 prescaler 1 (PCLK1=PCLK2=16000).

I've configured it by using the system_stm32l1xx.c created by Clock Configuration.xls. I've also set in my preprocessor symbols this ''HSE_VALUE=16000000'' (I'm using KEIL uVision 4). I need to do something else to configure the HSE clock source? I'm using an external 16MHz oscillator.

I know about the errata... I'll configure the DMA... when I2C will start to work 🙂

Many thanks!

Alberto 🙂
15 REPLIES 15
chen
Associate II
Posted on February 18, 2014 at 10:18

Hi

''They are set at 2MHz, pushpull and nopull. ''

For I2C the IO pins MUST be set to open drain.

alby87
Associate II
Posted on February 18, 2014 at 10:59

Many, many thanks. They are now both in open drain, but the busy is always set and the lines goes down at GPIO_Init(). This is a snippet from my code:

RCC_ClocksTypeDef RCC_Clocks;

GPIO_InitTypeDef GPIO_InitStructure;

NVIC_InitTypeDef NVIC_InitStructure;

I2C_InitTypeDef I2C_InitStructure;

 

 memset(gsmDmaBuffer, 0, sizeof(*gsmDmaBuffer));

 

 RCC_HSEConfig(RCC_HSE_ON);

 

 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY)== RESET); //RCC_WaitForHSEStartUp(); sosdtituire con

 

 I2C_DeInit(I2C1);

 RCC_GetClocksFreq(&RCC_Clocks);

  SysTick_Config(RCC_Clocks.HCLK_Frequency / 10);

 

 //Start the Reset and clock control (RCC) peripheral

 RCC_AHBPeriphClockCmd(

  (

   RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD

  ),

  ENABLE

 ); //Turn on I2C

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); <---BUSY FLAG IS SET

 

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE); <---BUSY FLAG IS CLEARED

 RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE); <---BUSY FLAG IS SET

 

GPIO_StructInit(&GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB,GPIO_Pin_7,GPIO_AF_I2C1);

 

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;

 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOB, &GPIO_InitStructure); <--------------------------------------SDA GOES FROM HIGH TO LOW

GPIO_PinAFConfig(GPIOB,GPIO_Pin_8,GPIO_AF_I2C1);

 

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

  GPIO_Init(GPIOB, &GPIO_InitStructure); <------------------ SCL GOES FROM HIGH TO LOW

I2C_StructInit(&I2C_InitStructure);

 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

 I2C_InitStructure.I2C_ClockSpeed = 100000;

 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

 I2C_InitStructure.I2C_OwnAddress1 = 0x10;

 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

 

 I2C_Init(I2C1,&I2C_InitStructure);

 

 I2C_Cmd(I2C1,ENABLE);

 

 NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

chen
Associate II
Posted on February 18, 2014 at 12:36

'' but the busy is always set and the lines goes down at GPIO_Init()''

Do they go high after I2C_Init() has finished?

I do not see anything wrong with the code.

What does ''I2C_StructInit(&I2C_InitStructure);'' do?

The code in the working I2C here does not have this line.

''GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;''

I do not think this is wrong but the code here sets it to 100MHz

''NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;''

This is setting up IRQ/ISR for I2C but then you are not enabling the I2C peripheral IRQ

Looks like this :

''    /* Enable Interrupts */

    I2C_ITConfig(I2Cx, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF ), ENABLE);''

It is OK not to do this if you are not using IRQs. Comment out the NVIC lines if you do not intend to use IRQs

alby87
Associate II
Posted on February 18, 2014 at 12:59

'''' but the busy is always set and the lines goes down at GPIO_Init()''

Do they go high after I2C_Init() has finished?''

They remain low after I2C_Init() has finished.

''What does ''I2C_StructInit(&I2C_InitStructure);'' do?

The code in the working I2C here does not have this line.''

It initialite the I2C_InitStructure members with default parameters. Is good to have this before modifying the parameters

''''GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;''

I do not think this is wrong but the code here sets it to 100MHz''

Max with my controller is 40MHz, and it didn't worked either

''''NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;''

This is setting up IRQ/ISR for I2C but then you are not enabling the I2C peripheral IRQ

Looks like this :

''    /* Enable Interrupts */

    I2C_ITConfig(I2Cx, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF ), ENABLE);''

It is OK not to do this if you are not using IRQs. Comment out the NVIC lines if you do not intend to use IRQs''

It's in another piece of code, just after I fill the buffer I need to send. It should work in this manner:

Activate the I2C, fill the buffer, activate the IRQ, send START. That should call the I2C1_EV_IRQHandler() function, and send the data. But the interrupt function is never called, and in a test code, after the START function I can't get past the control while I posted in the first post.

Thanks!
chen
Associate II
Posted on February 18, 2014 at 13:10

Comparing your init code to the one I have here - you are missing :

    /*!< I2C Periph clock enable */

    RCC_APB1PeriphClockCmd(I2Cx_CLK, ENABLE);

    /*!< SCL & SDA GPIO clock enable */

    RCC_AHB1PeriphClockCmd(I2Cx_SCL_GPIO_CLK | I2Cx_SDA_GPIO_CLK, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /* Reset I2Cx_CLK IP */

    RCC_APB1PeriphResetCmd(I2Cx_CLK, ENABLE);

    /* Release reset signal of I2Cx_CLK IP */

    RCC_APB1PeriphResetCmd(I2Cx_CLK, DISABLE);

alby87
Associate II
Posted on February 18, 2014 at 17:21

''Comparing your init code to the one I have here - you are missing :

    /*!< I2C Periph clock enable */

    RCC_APB1PeriphClockCmd(I2Cx_CLK, ENABLE);''

I call it using: RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);

 '' /*!< SCL & SDA GPIO clock enable */

    RCC_AHB1PeriphClockCmd(I2Cx_SCL_GPIO_CLK | I2Cx_SDA_GPIO_CLK, ENABLE);''

I call it using: RCC_AHBPeriphClockCmd(

  (

   RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB | RCC_AHBPeriph_GPIOC | RCC_AHBPeriph_GPIOD

  ),

  ENABLE

 );//Turn on I2C

''RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

    /* Reset I2Cx_CLK IP */

    RCC_APB1PeriphResetCmd(I2Cx_CLK, ENABLE);

    /* Release reset signal of I2Cx_CLK IP */

    RCC_APB1PeriphResetCmd(I2Cx_CLK, DISABLE);''

Calling it with

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE); 

RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);

I've tried using a mine implementation of the protocol, and everything is working OK. Then I use I2C_Init and clock and data goes low. Busy is ALWAYS set, even when I used the ports as classic IN/OUT and not alternate function. 
chen
Associate II
Posted on February 19, 2014 at 10:33

''I've tried using a mine implementation of the protocol, and everything is working OK. ''

Does that mean you have something working?

''Then I use I2C_Init and clock and data goes low. Busy is ALWAYS set, even when I used the ports as classic IN/OUT and not alternate function. ''

Are you trying to get the I2C working using the standard peripheral library?

I have not tried it yet myself. Try looking at some of the examples.

alby87
Associate II
Posted on February 19, 2014 at 10:42

''''I've tried using a mine implementation of the protocol, and everything is working OK. ''

Does that mean you have something working?''

Yes... I can communicate and I get the expected response

''''Then I use I2C_Init and clock and data goes low. Busy is ALWAYS set, even when I used the ports as classic IN/OUT and not alternate function. ''

Are you trying to get the I2C working using the standard peripheral library?

I have not tried it yet myself. Try looking at some of the examples.''

It seems a faulty slave. This afternoon I'll go to the lab to have the ''faulty'' slave removed and check again. I'll update you!

mohsenkazemi87
Associate
Posted on February 19, 2014 at 11:02

hi,

i have the same problem with my I2C(busy flag always is set) in stm32f103.

do you have any idea about how to fix it?

bests