2014-02-17 02:55 PM
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 :)2014-02-18 01:18 AM
Hi
''They are set at 2MHz, pushpull and nopull. '' For I2C the IO pins MUST be set to open drain.2014-02-18 01:59 AM
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);2014-02-18 03:36 AM
'' 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 IRQs2014-02-18 03:59 AM
'''' 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!2014-02-18 04:10 AM
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);2014-02-18 08:21 AM
''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.2014-02-19 01:33 AM
2014-02-19 01:42 AM
''''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!
2014-02-19 02:02 AM