Tengo un PIC18F con MSSP 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 realiza el sondeo de reconocimiento necesario:
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, así que asumo que realmente funcionó...
Utilicé la herramienta de análisis de protocolo I2C de mi rastreador lógico y parece que todos los datos se envían/reciben correctamente:
¿Alguien puede sugerir algo que hacer a continuación para la depuración? El byte de control parece correcto, ya que es 0b1010 después de INICIO, seguido del identificador de bloque, A0, A1 y R/!W. He probado direcciones de >64 KB y he confirmado que B1 está configurado correctamente. Mi EEPROM tiene A0 y A1 conectados a tierra, por lo que también parece correcto. R/!W es bajo para escritura y alto justo antes de la lectura. Lo único que aún no he hecho es agregar un retraso después de la escritura, pero lo intentaré mañana.
EDITAR: la opción de análisis I2C muestra lo que han estado diciendo:
Supongo que el problema es que debe retrasarse después de la escritura.
El dispositivo estará ocupado durante aproximadamente 3 a 5 milisegundos después de una escritura, durante los cuales 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 conduciría a que todos se lean en los pulsos del reloj.
En primer lugar, intente agregar un retraso después de la escritura, quizás 10 milisegundos más o menos.
Si eso funciona, consulte el capítulo de la hoja de datos sobre sondeo de confirmación para mejorar el rendimiento. En resumen, confirmar el sondeo significa enviar un comando de escritura una y otra vez hasta que el dispositivo lo reconozca, momento en el que sabrá que el ciclo de escritura está completo.
escape
Novato91
dave