No se pueden leer los datos escritos en 24AA1025

4

Tengo un PIC18F con MSSP con el que estoy interactuando con un 24AA1025. Estoy usando MPLAB 8 y las funciones de C18 para hacerme la vida más fácil. El único problema es que (supuestamente) he escrito un byte en el 24AA1025, pero cuando lo leo, obtengo 0xFF en lugar del byte que escribí.

Así es como tengo la EEPROM conectada:

A0 - GND
A1 - GND
A2 - Vcc
Vss - GND
SDA - pulled up to +5 via 2.2k resistor, and connected to SDA on PIC
SCL - pulled up to +5 via 2.2k resistor, and connected to SCL on PIC
WP - Vss
Vcc - 5V

Aquí está mi función de escritura (ahora editada con código de trabajo):

bool I2CWriteByte( long address, unsigned char data)
{
    unsigned char ret;
    unsigned char control_byte;
    unsigned char high_address_byte;
    unsigned char low_address_byte;

    control_byte = (address >= 65536) ? 0b10101000 : 0b10100000;
    high_address_byte = (char)((address & 0x0000FF00) >> 8);
    low_address_byte = (char)(address & 0x000000FF);

    IdleI2C();

    // perform ack polling around control byte sending every time
    ret = SendControlByte( control_byte);
    if( ret == -1)
        return false;

    ret = WriteI2C( high_address_byte);
    if( ret == -1)
        return false;
    ret = WriteI2C( low_address_byte);
    if( ret == -1)
        return false;
    ret = WriteI2C( data);
    if( ret == -1)
        return false;

    StopI2C();
    return true;
}

Aquí está mi función de lectura (ahora editada con código de trabajo):

bool I2CReadByte( long address, unsigned char* data)
{
    unsigned char ret;
    // to do a read, first do part of a write but don't send the data byte, then send a new control byte with bit 0 set to 1 for read.
    // see 24AA1025 datasheet page 12
    unsigned char control_byte;
    unsigned char high_address_byte;
    unsigned char low_address_byte;

    control_byte = (address >= 65536) ? 0b10101000 : 0b10100000;
    high_address_byte = (char)((address & 0x0000FF00) >> 8);
    low_address_byte = (char)(address & 0x000000FF);

    IdleI2C();
    ret = SendControlByte( control_byte);
    if( ret == -1)
        return false;

    ret = WriteI2C( high_address_byte);
    if( ret == -1)
        return false;
    ret = WriteI2C( low_address_byte);
    if( ret == -1)
        return false;

    control_byte = (address >= 65536) ? 0b10101001 : 0b10100001;
    ret = SendControlByte( control_byte);
    if( ret == -1)
        return false;

    // now return value
    *data = ReadI2C();
    StopI2C();
    return true;
}

EDITAR - La importante función SendControlByte (), que cumple los requisitos de sondeo de ack:

bool SendControlByte( unsigned char control_byte)
{
    bool nack;
    bool ret;

    nack = true;

    while( nack) {
        StartI2C();
        ret = WriteI2C( control_byte);
        if( ret == -1)
            return false;
        if( SSPCON2bits.ACKSTAT == 0)
            nack = false;
    }
}

WriteI2C nunca devuelve un error, por lo que asumo que realmente funcionó ...

Usé la herramienta de análisis de protocolo I2C de mi sniffer lógico, y parece que todos los datos se están enviando / recibiendo correctamente:

¿Alguienpuedesugeriralgoquehaceracontinuaciónparaladepuración?Elbytedecontrolparececorrecto,yaquees0b1010despuésdeSTART,seguidodelidentificadordebloque,A0,A1yR/!W.Heprobadodirecciones>64KByconfirméqueB1estáconfiguradocorrectamente.MiEEPROMtieneA0yA1atierra,porloquesevebientambién.R/!Wesbajoparaescriturasyaltojustoantesdelalectura.Loúnicoqueaúnnohehechoesunretrasoadicionaldespuésdelaescritura,peromañanalointentaré.

EDITAR-LaopcióndeanálisisI2Cmuestraloqueustedeshanestadodiciendo:

    
pregunta Dave

1 respuesta

4

Supongo que el problema es que necesitas demorar después de la escritura.

El dispositivo estará ocupado durante aproximadamente 3-5 milisegundos después de una escritura, durante el cual no responderá a ningún comando. Si emite una lectura durante este período de tiempo, el dispositivo la ignorará y la línea SDA permanecerá alta, lo que de hecho daría como resultado que se lean todas las pulsaciones del reloj.

En primer lugar, intente agregar un retraso después de la escritura, tal vez 10 milisegundos más o menos.
Si eso funciona, consulte el capítulo de la hoja de datos sobre el reconocimiento de sondeo para mejorar el rendimiento. En resumen, reconocer el sondeo significa enviar un comando de escritura una y otra vez hasta que el dispositivo lo reconozca, momento en el que sabe que el ciclo de escritura se ha completado.

    
respondido por el exscape

Lea otras preguntas en las etiquetas