Skip to main content
ibarnes
Associate
November 24, 2009
Question

Polled I2C breaks with other interrupts

  • November 24, 2009
  • 1 reply
  • 523 views
Posted on November 24, 2009 at 18:44

Polled I2C breaks with other interrupts

    This topic has been closed for replies.

    1 reply

    ibarnes
    ibarnesAuthor
    Associate
    May 17, 2011
    Posted on May 17, 2011 at 13:31

    Hello,

    Using the StdPeriph_Lib_V3.1.2 and STM32F105R8. Clocked at 4MHz throughout, no PLL. Cut down the example code to do continuous reads from a Microchip 24LC04B.

    When there are no interrupts, the code runs fine and reads indefinitely. The moment I enable an unrelated interrupt (for example SysTick that does nothing but return) it falls over at ''test on EV7''. Looking at the bus with a scope, there are no differences between any of the reads and writes - even when it hangs the bus returns to the idle state.

    I realise that the code is not optimal and should have timeouts/recovery but I would like to get this sorted before I add those. I have attached the code below, does anyone have any ideas?

    -----

    #include ''stm32f10x.h''

    void Eeprom_Config(I2C_TypeDef* I2Cx);

    void Eeprom_Byte_Read(I2C_TypeDef* I2Cx, uint8_t *Data, uint16_t ReadAddr);

    int main(void)

    {

    GPIO_InitTypeDef GPIO_InitStructure;

    uint8_t Index;

    uint8_t Data;

    /* System Clocks Configuration */

    SystemInit();

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    /* Configure the GPIO ports */

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;

    GPIO_Init(GPIOB, &GPIO_InitStructure);

    SysTick_Config(SystemFrequency_AHBClk / 1000);

    Eeprom_Config(I2C2);

    while (1)

    {

    Eeprom_Byte_Read(I2C2, &Data, 0x0);

    for (Index = 0; Index < 50; Index ++) {};

    }

    }

    void Eeprom_Config(I2C_TypeDef* I2Cx)

    {

    I2C_InitTypeDef I2C_InitStructure;

    /* I2C configuration */

    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;

    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;

    I2C_InitStructure.I2C_OwnAddress1 = 0xA0;

    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;

    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;

    I2C_InitStructure.I2C_ClockSpeed = 400000;

    /* I2C Peripheral Enable */

    I2C_Cmd(I2Cx, ENABLE);

    /* Apply I2C configuration after enabling it */

    I2C_Init(I2Cx, &I2C_InitStructure);

    }

    void Eeprom_Byte_Read(I2C_TypeDef* I2Cx, uint8_t *Data, uint16_t ReadAddr)

    {

    /* While the bus is busy */

    while(I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY));

    /* Send START condition */

    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for write */

    I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Transmitter);

    /* Test on EV6 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    /* Send the EEPROM's internal address to read from: Only one byte address */

    I2C_SendData(I2Cx, ReadAddr);

    /* Test on EV8 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTED));

    /* Send START condition a second time */

    I2C_GenerateSTART(I2Cx, ENABLE);

    /* Test on EV5 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_MODE_SELECT));

    /* Send EEPROM address for read */

    I2C_Send7bitAddress(I2Cx, 0xA0, I2C_Direction_Receiver);

    /* Test on EV6 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    /* Disable Acknowledgement */

    I2C_AcknowledgeConfig(I2Cx, DISABLE);

    /* Send STOP Condition */

    I2C_GenerateSTOP(I2Cx, ENABLE);

    /* Test on EV7 and clear it */

    while(!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_RECEIVED));

    /* Read a byte from the EEPROM */

    *Data = I2C_ReceiveData(I2Cx);

    /* Enable Acknowledgement to be ready for another reception */

    I2C_AcknowledgeConfig(I2Cx, ENABLE);

    }

    void SysTick_Handler(void)

    {

    }