Ich habe einen PIC18F mit MSSP, den ich mit einem 24AA1025 verbinde. Ich verwende MPLAB 8 und die Funktionen von C18, um mir das Leben zu erleichtern. Das einzige Problem ist, dass ich (angeblich) ein Byte in den 24AA1025 geschrieben habe, aber wenn ich es zurücklese, bekomme ich 0xFF anstelle des Bytes, das ich geschrieben habe.
So habe ich das EEPROM verdrahtet:
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
Hier ist meine Schreibfunktion (jetzt mit funktionierendem Code bearbeitet):
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;
}
Hier ist meine Lesefunktion (jetzt mit Arbeitscode bearbeitet):
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;
}
BEARBEITEN – Die überaus wichtige SendControlByte()-Funktion, die die erforderliche Bestätigungsabfrage durchführt:
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 gibt nie einen Fehler zurück, also gehe ich davon aus, dass es tatsächlich funktioniert hat ...
Ich habe das I2C-Protokollanalysetool meines Logik-Sniffers verwendet, und es sieht so aus, als würden alle Daten ordnungsgemäß gesendet / empfangen:
Kann jemand etwas vorschlagen, was als nächstes zum Debuggen zu tun ist? Das Steuerbyte sieht korrekt aus, da es nach START 0b1010 ist, gefolgt von der Blockkennung, A0, A1 und R/!W. Ich habe >64-KB-Adressen getestet und bestätigt, dass B1 richtig eingestellt ist. Mein EEPROM hat A0 und A1 geerdet, also sieht das auch richtig aus. R/!W ist niedrig für Schreibvorgänge und hoch kurz vor dem Lesen. Das einzige, was ich noch nicht gemacht habe, ist eine Verzögerung nach dem Schreiben, aber ich werde es morgen versuchen.
BEARBEITEN - Die I2C-Analyseoption zeigt, was Sie gesagt haben:
Ich vermute, dass das Problem tatsächlich darin besteht, dass Sie nach dem Schreiben verzögern müssen.
Das Gerät ist nach einem Schreibvorgang etwa 3-5 Millisekunden beschäftigt, währenddessen es auf keine Befehle antwortet. Wenn Sie während dieser Zeit einen Lesevorgang ausgeben, wird das Gerät ihn ignorieren und die SDA-Leitung bleibt hoch – was tatsächlich dazu führen würde, dass alle Einsen auf den Taktimpulsen gelesen werden.
Versuchen Sie zunächst, nach dem Schreiben eine Verzögerung hinzuzufügen, vielleicht 10 Millisekunden oder so.
Wenn dies funktioniert, überprüfen Sie das Datenblattkapitel zum Bestätigungsabruf, um die Leistung zu verbessern. Kurz gesagt, Bestätigungsabfrage bedeutet, dass ein Schreibbefehl immer wieder gesendet wird, bis das Gerät ihn bestätigt. An diesem Punkt wissen Sie, dass der Schreibzyklus abgeschlossen ist.
Flucht
Anfänger91
David