0
\$\begingroup\$

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);
            }
\$\endgroup\$
  • \$\begingroup\$ Are you doing any sort of check to ensure the write has finished before you read it so soon? \$\endgroup\$ – DiBosco Jun 21 '18 at 8:32
  • \$\begingroup\$ i did try an acknowledgement polling as mentioned in data sheet. and even a delay. but the result is same \$\endgroup\$ – Nikhil Ben George Jun 21 '18 at 8:40
  • 2
    \$\begingroup\$ What does I2C2_StartWrite do? Are you aware of the exact sequence of writing and reading with I2C? It should look like the waveforms on page 11 of the datsasheet. Then do you know how a read is done? Again, details are on the datasheet. What does your scope show is actually happening as opposed to what you think should be happening? \$\endgroup\$ – DiBosco Jun 21 '18 at 8:51
  • \$\begingroup\$ i added the I2C2_StartWrite and I2C2_StartRead functions. I developed the code from tutorial and from datasheet. i believe i m following the right method because i was able to write and read individually. Im following the i2c cycle shown in datasheet. @DiBosco \$\endgroup\$ – Nikhil Ben George Jun 21 '18 at 9:16
  • 1
    \$\begingroup\$ First of all, I'd like to repeat: What does your scope show? I hope I'm wrong, but I suspect because you dodged that question you've not used it yet. Second, I don't see enough accesses to TXDR. My suspcion is you don't quite understand how you need to write the hardware address, then the internal address, then the data. Reading data is even more complicated. I2C takes a lot of getting used to, it's quite a mind **** when you first try it. This tutorial IMHO is good: robot-electronics.co.uk/i2c-tutorial \$\endgroup\$ – DiBosco Jun 21 '18 at 9:31
2
\$\begingroup\$
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.

\$\endgroup\$
0
\$\begingroup\$

I modified the read function into two cycles, a write to load the read address and a current address read. Its working now. However im not sure why the the random address read cycle as mentioned in datasheet doesnt work.

\$\endgroup\$
  • \$\begingroup\$ I suspect you weren't retransmitting the start sequence previously. If I had to bet I'd say that you weren't actually following the random read procedure previously and now you are. I'd guess you were writing and reading without resending that start sequence. That tutorial link I sent is very good at clearly explaining that. The I2C analysers such as the Beagle is great at immediately pointing these thigns out too. Tools like that save a lot of time and are well worth spending the money on, especially when starting out IMHO. \$\endgroup\$ – DiBosco Jun 22 '18 at 10:20
  • \$\begingroup\$ @DiBosco i was sending the start instruction previously as you can see in the code. but now i added a stop condition in between the two start cycles. Thats the only change i made. I will invest in an analyzer \$\endgroup\$ – Nikhil Ben George Jun 23 '18 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.