Electrical – STM32f030C8 I2C EEPROM -no data received when read after a write

eepromi2cstm32stm32f0

I am developing library for I2C eeprom at24c04 with stm32f030c8.
My read and write functions work but when i try to read immediately after a write to eeprom, the eeprom doest return any data. however i could immediately do a write consecutively. The problem occurs only when i read after a write statement. i tried enabling and disabling the I2C enable bit but problem still exist. Can anyone tell me whats the issue.

void main()
{
   Configure_GPIO_I2C2();
   Configure_I2C2_Master(0xA0,1);

    I2C_WriteByte(5,'k');
    charr= I2C_ReadByte(5);//the program get stuck here because no byte is 
                            //received from eeprom
    UART_Send_String(1,&charr);

}

void I2C_WriteByte(uint8_t addr,uint8_t bytetowrite)
            {
                I2C2->ISR=0x01;
                I2C2_StartWrite(2);//start

                I2C2->TXDR = addr;//write addr
                while(!(I2C2->ISR & I2C_ISR_TXE));

                //I2C2_StartWrite(1);

                I2C2->TXDR = bytetowrite;
                while(!(I2C2->ISR & I2C_ISR_TXE));

                I2C2->CR2 |= I2C_CR2_STOP;//stop
                while(I2C2->CR2 & I2C_CR2_STOP);

            }

            uint8_t I2C_ReadByte(uint8_t byteToRead)
            {
                I2C2->ISR=0x01;
                I2C2_StartWrite(1);

                I2C2->TXDR = byteToRead;
                while(!(I2C2->ISR & I2C_ISR_TXE));

                I2C2_StartRead(1);  
                while(!(I2C2->ISR & I2C_ISR_RXNE));
                UART_Send_String(1,"r strt");
                uint8_t recv_data=I2C2->RXDR;   


                I2C2->CR2 |= I2C_CR2_STOP;
                while(I2C2->CR2 & I2C_CR2_STOP);

                return recv_data;

            }


            /////////////////////////////////////////////////////////
            /////////////////////////////////////////////////////////
            void Configure_GPIO_I2C2(void)
            {

                RCC->AHBENR |= RCC_AHBENR_GPIOFEN;  
                GPIOF->MODER |= (2<<12) | (2<<14);  
                GPIOF->OTYPER |= GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7; 

                GPIOF->OSPEEDR &=  ~(1<<12);
                GPIOF->OSPEEDR &=  ~(1<<14);

                GPIOF->PUPDR &= ~(1<<12);
                GPIOF->PUPDR &= ~(1<<12);
            }

        void Configure_I2C2_Master(uint8_t slave_addr,uint8_t no_of_bytes)
            {

                RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;

                /* (1) Timing register value is computed with the AN4235 xls file,
                 fast Mode @400kHz with I2CCLK = 48MHz, rise time = 140ns, fall time = 40ns */  
                I2C2->CR1 &= ~I2C_CR1_PE;
                I2C2->TIMINGR |= (uint32_t)0x00B01A4B; /* (1) */
                I2C2->CR2 |= (uint8_t)slave_addr;
                I2C2->CR2 |= no_of_bytes<<16;   
                I2C2->CR1 |= I2C_CR1_PE;
                //NVIC_SetPriority(I2C2_IRQn, 0); /* (7) */
                //NVIC_EnableIRQ(I2C2_IRQn); /* (8) */
            }

    void I2C2_StartWrite(int bytesToWrite)
            {

                I2C2->CR2 &= ~I2C_CR2_RD_WRN;

                I2C2->CR2 |= bytesToWrite<<16;

                I2C2->CR2 |= I2C_CR2_START;
                while(I2C2->CR2 & I2C_CR2_START);
            }



            void I2C2_StartRead(int bytesToRead)
            {
            I2C2->CR2 |= I2C_CR2_RD_WRN;

                I2C2->CR2 |= bytesToRead<<16;

                I2C2->CR2 |= I2C_CR2_START;
                while(I2C2->CR2 & I2C_CR2_START);
            }

Best Answer

My read and write functions work but when i try to read immediately after a write to eeprom, the eeprom doest return any data. however i could immediately do a write consecutively.

This smells like you are not waiting for the EEPROM to finish the write. I didn't look at your EEPROM, but with all the ones I've ever used, a write or erase sequence only starts the action. The EEPROM is then busy for some time afterward.

Most EEPROMs have something like a status register where you can poll a bit to see if it is busy. This read action can be performed whether busy or not.

The most general software architecture always polls the busy bit before trying to do anything. If the EEPROM is busy, it keeps polling until it is not, then proceeds with whatever action was requested. More sophisticated implementations set a flag on write and erase, indicating that the EEPROM might be busy. Busy checking is only done when this flag is set. Naive implementations always just wait after a erase or write.

Look at your code carefully, especially what exactly is sent to the EEPROM when a write is immediately followed by a read. My guess is that the busy checking is somehow skipped in that case.