AnsweredAssumed Answered

After the I2C start, the interrupt handler is called in a loop with I2C_EVENT_MASTER_MODE_SELECT event

Question asked by desaissement.benoit on Jul 17, 2015
Latest reply on Jul 23, 2015 by desaissement.benoit
Hello everybody,

First I have to say that I never implemented I2C with interruptions. I searched on this forum and on the ST libraries a functional and simple send/receive I2C code working with interruptions and I don't find something interesting, maybe I'm wrong. If you have a good example, do not hesitate :)

I have already a working code for I2C communications (including I2C1_Start,I2C1_Repeated_Start, I2C1_Stop, I2C1_Wr, I2C1_Read_Ack, I2C1_Read) but without interruptions: my code is not real-time. For the moment I just coded an interruption handler to check if this IRQHandler is called each time an I2C message is received by the STM32:

void I2C_Config(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
        GPIO_InitTypeDef GPIO_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
 
        ///////////////////////
        /// INIT GPIO I2C ///
        ///////////////////////
        // SDA and SCL Pins declaration
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_6; // SDA, SCL
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
 
        // READY pin
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; // INT
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
 
        // Connect I2C1 pins to AF
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);// SCL
        GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);// SDA
 
        I2C_DeInit(I2C1);
        I2C_InitTypeDef I2C_InitStruct;
        I2C_InitStruct.I2C_ClockSpeed = 400000;         // 400kHz
        I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;         // I2C mode
        I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2; // 50% duty cycle --> standard
        I2C_InitStruct.I2C_OwnAddress1 = 0x00;          // own address, not relevant in master mode
        I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;        // enable acknowledge when reading (can be changed later on)
        I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // set address length to 7 bit addresses
        I2C_Init(I2C1, &I2C_InitStruct);                // init I2C1
        I2C_Cmd(I2C1, ENABLE);
 
        // I2C NVIC
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
        NVIC_InitStructure.NVIC_IRQChannel = I2C1_EV_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PREAMPTION_PRIORITY_LOW;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        NVIC_InitStructure.NVIC_IRQChannel = I2C1_ER_IRQn;
        NVIC_Init(&NVIC_InitStructure);
        I2C_ITConfig(I2C1,I2C_IT_EVT,ENABLE); // enable event IRQ
}

void I2C1_EV_IRQHandler(void)
{
    uint32_t LastI2Cevent = I2C_GetLastEvent(I2C1);
 
    switch (LastI2Cevent)
    {
        case I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED:
        break;
 
        case I2C_EVENT_SLAVE_BYTE_RECEIVED:
        break;
 
        case I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED:
        break;
 
        case I2C_EVENT_SLAVE_STOP_DETECTED:
        break;
 
        case I2C_EVENT_SLAVE_BYTE_TRANSMITTED:
        break;
 
        case I2C_EVENT_SLAVE_ACK_FAILURE:
        break;
 
        case I2C_EVENT_MASTER_MODE_SELECT:
        break;
 
        defaultbreak;
    }
}

After the first time I execute my I2C1_Start() function, the code stays at the command 
while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));

... and this interrupt handler is called in a loop, with LastI2Cevent = I2C_EVENT_MASTER_MODE_SELECTevent.

Do you have any idea why?

Thanks a lot!

Outcomes