2016-03-08 03:55 AM
Hello,
I'm having problems with STM32L100RC I2C1 peripheral on PB6 and PB7. The lines are pulled to MCU Vcc with 1k resistors. The problem is that when I configure the PB6 and PB7 as I2C1 pins, the MCU pulls SDA line low, the I2C busy flag is set and the I2C1 peripheral is stuck. The initialisation code is following: #define I2C_SDA_PIN GPIO_Pin_7
#define I2C_SDA_GPIO_PORT GPIOB
#define I2C_SDA_GPIO_CLK RCC_AHBPeriph_GPIOB
#define I2C_SCL_PIN GPIO_Pin_6
#define I2C_SCL_GPIO_PORT GPIOB
#define I2C_SCL_GPIO_CLK RCC_AHBPeriph_GPIOB
void v_Initialise_I2c(void)
{
uint16_t u16_delay;
uint8_t u8_clock_cycles = 0;
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
NVIC_InitTypeDef t_i2c_vector;
/* GPIOB Periph clock enable */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
// Set SCL and SDA as inputs.
GPIO_InitStructure.GPIO_Pin = I2C_SDA_PIN | I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
GPIO_SetBits(I2C_SCL_GPIO_PORT, I2C_SCL_PIN | I2C_SDA_PIN);
if ((GPIO_ReadInputDataBit(I2C_SDA_GPIO_PORT, I2C_SDA_PIN) == 0) || (GPIO_ReadInputDataBit(I2C_SCL_GPIO_PORT, I2C_SCL_PIN) == 0))
{
if (GPIO_ReadInputDataBit(I2C_SDA_GPIO_PORT, I2C_SDA_PIN) == 0)
{
DEBUG_PRINT(3, ''SDA line down!'');
}
if (GPIO_ReadInputDataBit(I2C_SCL_GPIO_PORT, I2C_SCL_PIN) == 0)
{
DEBUG_PRINT(3, ''SCL line down!'');
}
DEBUG_PRINT(3, ''Generate clock to release line.'');
// Set SCL as output
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(I2C_SCL_GPIO_PORT, &GPIO_InitStructure);
while (GPIO_ReadInputDataBit(I2C_SDA_GPIO_PORT, I2C_SDA_PIN) == 0)
{
GPIO_ResetBits(I2C_SCL_GPIO_PORT, I2C_SCL_PIN);
u16_delay = 15;
while (u16_delay--)
{
__NOP();
}
GPIO_SetBits(I2C_SCL_GPIO_PORT, I2C_SCL_PIN);
u16_delay = 15;
while (u16_delay--)
{
__NOP();
}
WDRESET;
}
DEBUG_PRINT(3, ''Done!'');
}
GPIO_PinAFConfig(I2C_SDA_GPIO_PORT, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_PinAFConfig(I2C_SCL_GPIO_PORT, GPIO_PinSource6, GPIO_AF_I2C1);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
GPIO_Init(I2C_SDA_GPIO_PORT, &GPIO_InitStructure);
/* I2C1 and I2C2 Periph clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
I2C_Cmd(I2C1, DISABLE);
I2C_DeInit(I2C1);
I2C_Cmd(I2C1, ENABLE);
I2C_StructInit(&I2C_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = 0x00;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 100000;
I2C_Init(I2C1, &I2C_InitStructure);
/* Enable and set EV and ER interrupts as high priority interrupts. */
t_i2c_vector.NVIC_IRQChannel = I2C1_EV_IRQn;
t_i2c_vector.NVIC_IRQChannelPreemptionPriority = 0;
t_i2c_vector.NVIC_IRQChannelSubPriority = 2;
t_i2c_vector.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&t_i2c_vector);
t_i2c_vector.NVIC_IRQChannel = I2C1_ER_IRQn;
t_i2c_vector.NVIC_IRQChannelPreemptionPriority = 0;
t_i2c_vector.NVIC_IRQChannelSubPriority = 3;
NVIC_Init(&t_i2c_vector);
I2C_ClearITPendingBit(I2C1, ALL_I2C_INTERRUPTS);
I2C_ITConfig(I2C1, I2C_IT_BUF | I2C_IT_EVT | I2C_IT_ERR, ENABLE);
I2C_SoftwareResetCmd(I2C1, ENABLE);
Delay(10);
I2C_SoftwareResetCmd(I2C1, DISABLE);
return;
}
The lines are pulled low whenGPIO_PinAFConfig() is called. I've even added the clock pulse generation in case the slave pulls the SDA low. I've checked with an oscilloscope that the line is pulled low by the MCU. Why is this? Is there something wrong with my initialisations?
Thanks in advance!
-Juho L
#i2c
2016-03-28 05:50 AM
Hi lepisto.juho,
I have 2 suggestions: 1- use another combination of pins than PB6/PB7. You have PB8 (SCL) and PB9 (SDA). 2- move these lines of code to the beginning:GPIO_PinAFConfig(I2C_SDA_GPIO_PORT, GPIO_PinSource7, GPIO_AF_I2C1);
GPIO_PinAFConfig(I2C_SCL_GPIO_PORT, GPIO_PinSource6, GPIO_AF_I2C1);
I would like to keep me informed about the result.
-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.
2016-04-04 03:31 AM
Hello,
Unfortunately the code will be used on a target that has fixed HW, so changing pins is not possible.I moved the AF functions to the beginning of the initialisation function, but no change in behaviour.-Juho L2016-04-11 03:55 AM
An update: Since I could not get the I2C peripheral to work, I implemented a bit-bang I2C and it works, so the electronics are OK. Very strange indeed.
2018-01-11 05:49 AM
I'm having a similar issue that we've been struggling with for a long time. Did anyone ever resolve this other than doing your own bit banging?
2018-01-11 08:18 AM
The SPL on the F1 had an initialization order requirement for I2C, related to Init vs Enable as I recall.