STM32f030C8 I2C EEPROM - no se reciben datos cuando se leen después de una escritura

0

Estoy desarrollando una biblioteca para I2C eeprom at24c04 con stm32f030c8 . Mis funciones de lectura y escritura funcionan, pero cuando intento leer inmediatamente después de escribir en eeprom, el eeprom no devuelve ningún dato. Sin embargo, inmediatamente pude hacer una escritura consecutiva. El problema ocurre solo cuando leo después de una declaración de escritura. Intenté habilitar y deshabilitar el bit de habilitación I2C pero el problema aún existe. ¿Alguien puede decirme cuál es el problema?

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);
            }
    

2 respuestas

2
Mis funciones de lectura y escritura funcionan, pero cuando intento leer inmediatamente después de escribir en eeprom, el eeprom no devuelve ningún dato. sin embargo, inmediatamente podría hacer una escritura consecutiva.

Esto huele a que no estás esperando que la EEPROM termine la escritura. No miré tu EEPROM, pero con todos los que he usado, una secuencia de escritura o borrado solo comienza la acción. La EEPROM está ocupada durante algún tiempo después.

La mayoría de las EEPROM tienen algo así como un registro de estado donde puedes sondear un poco para ver si está ocupado. Esta acción de lectura puede realizarse ya sea ocupada o no.

La arquitectura de software más general siempre sondea el bit de ocupado antes de intentar hacer algo. Si la EEPROM está ocupada, continúa el sondeo hasta que no lo está, luego procede con la acción solicitada. Las implementaciones más sofisticadas establecen una marca en escritura y borrado, lo que indica que la EEPROM podría estar ocupada. La comprobación de ocupado solo se realiza cuando se establece este indicador. Las implementaciones ingenuas siempre solo esperan después de un borrado o escritura.

Mire cuidadosamente su código, especialmente qué se envía exactamente a la EEPROM cuando una escritura es seguida inmediatamente por una lectura. Supongo que la comprobación de ocupado se omite de alguna manera en ese caso.

    
respondido por el Olin Lathrop
0

Modifiqué la función de lectura en dos ciclos, una escritura para cargar la dirección de lectura y una dirección de lectura actual. Está funcionando ahora. Sin embargo, no estoy seguro de por qué no funciona el ciclo de lectura de direcciones aleatorias como se menciona en la hoja de datos.

    
respondido por el Nikhil Ben George

Lea otras preguntas en las etiquetas