2014-06-18 02:17 AM
Hi, I am new to this forum and to using the STM32 processors, so please forgive me if this topic has already been discussed.
I am using a Discovery board with a STM32L152RC micro-processor on. I am trying to implement the I2C2 as a slave for a GUI I am using. The I2C interface itself is working, but it seems to stop the main loop from running. By debugging I can see that the SB bit is set over and over, thus calling the I2C2_EV_IRQHandler again and again even though my I2C port should be a slave and not a master. The SB bit should only be set when I create a Start condition, so why is it set again and again when the I2C is in slave mode? The interrupt should only be called if the I2C interface detects an address match. void MX_I2C_Init(void){ GPIO_InitTypeDef GPIO_InitStruct; I2C_InitTypeDef I2C_InitStructure; /** I2C1 GPIO Configuration (Master) PB8 ------> I2C1_SCL PB9 ------> I2C1_SDA ** I2C2 GPIO Configuration (Slave) PB10 ------> I2C2_SCL PB11 ------> I2C2_SDA */ /*Enable or disable the AHB peripheral clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // Enable GPIO peripheral clock /*Configure GPIO pin : PB */ GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // set pins to alternative function GPIO_InitStruct.GPIO_OType = GPIO_OType_OD; // Setup as open-drain if used as output GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; // No internal pull-up/down resistor GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; // For fast mode, use 10MHz GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pin alternate function */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1); // Alternative function I2C1 /*Configure GPIO pin alternate function */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); // Alternative function I2C1 /*Configure GPIO pin alternate function */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2); // Alternative function I2C2 /*Configure GPIO pin alternate function */ GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2); // Alternative function I2C2 // I2C1 clock enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // Enable peripheral clock I2C1 RCC_AHBPeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); // Enable peripheral clock I2C1 // I2C2 clock enable RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // Enable peripheral clock I2C2 RCC_AHBPeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE); // Enable peripheral clock I2C2 I2C_DeInit(I2C1); // Important to reset I2C after clock enabled I2C_DeInit(I2C2); // Important to reset I2C after clock enabled I2C_InitStructure.I2C_ClockSpeed = 200000; // I2C clockspeed 200 kHz I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; // Alternative function I2C mode I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // Duty Cycle 50% I2C_InitStructure.I2C_OwnAddress1 = 0x00; // Own address, not relevant in Master mode I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // Acknoledge enabled I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7 bit address I2C_Init(I2C1, &I2C_InitStructure); // Init I2C1 I2C_InitStructure.I2C_OwnAddress1 = TIA_Address; // Address 0x60, (remember to shift address left by one bit = 0xC0) I2C_Init(I2C2, &I2C_InitStructure); // Init I2C2 I2C_StretchClockCmd(I2C1,ENABLE); // Enable clock streching I2C_StretchClockCmd(I2C2,ENABLE); // Enable clock streching I2C_OwnAddress2Config(I2C2,Driver_Address); // Set I2C2 address2 to 0x68, (remember to shift address left by one bit = 0xD0) I2C_Cmd(I2C1, ENABLE); // Enable I2C1 peripheral I2C_Cmd(I2C2, ENABLE); // Enable I2C2 peripheral }int main(void){ MX_GPIO_Init(); MX_I2C_Init(); MX_Timer_Init(); SystemCoreClockUpdate(); // Get Core Clock Frequency if (SysTick_Configuration(SystemCoreClock / 1000)) { // SysTick 1 msec interrupts while (1); // Capture error } I2C_ITConfig(I2C2, (I2C_IT_ERR | I2C_IT_EVT | I2C_IT_BUF ), ENABLE); NVIC_EnableIRQ(I2C2_EV_IRQn); NVIC_EnableIRQ(I2C2_ER_IRQn); while (1) { GPIO_SetBits(GPIOB,GPIO_Pin_6); Delay(100); GPIO_ResetBits(GPIOB,GPIO_Pin_6); Delay(100); } }The code runs until I enable the NVIC_EnableIRQ(I2C2_EV_IRQn), then it seems to jump instantly to the interrupt and just go around and around in the I2C2_EV_IRQHandler, never to continue to the while(1) loop in the main().Any suggestions would be greatly appreciated.2014-06-18 03:33 AM
Never mind, I solved it myself. Turned out it had nothing to do with the SB bit, it was the AF bit that was set when the master did not ACK on a read. Clearing the AF bit made it work.