Kein ACK von I2C EEPROM PIC18F

Ich versuche, einige Daten im 24AA01 EEPROM mit dem PIC18F13K22 zu speichern. Da ich auf die Komponenten warte, dachte ich, ich werde weitermachen und es in Proteus simulieren.

Schema

Dies ist mein Code (XC8-Compiler-basiert).

#include <xc.h>
#include "config.h"
#include "uart.h"

void i2c_writebyte(char x);
char i2c_readbyte();

void main(void) {
    OSCCON = 0x43;  //2Mhz
    TRISBbits.RB4 = 1;
    TRISBbits.RB6 = 1;
    TRISCbits.RC5 = 0;
    LATCbits.LATC5 = 0;   //Low to Enable Writing

    SSPADD = 4; //100kHz
    SSPSTAT = 0x80;
    SSPCON1 = 0x28;

    char a = 'y', c;

    uart_init();

    i2c_writebyte(a);

    c = i2c_readbyte();

    print(c, 1);

    LATCbits.LATC5 = 1;   //High to disable Writing
    while(1);
    return;
}
void i2c_writebyte(char x){
    try:

    SSPCON2bits.SEN = 1;    //Start bit
    while(SSPCON2bits.SEN != 0);

    SSPBUF = 0xA0;
    while(SSPSTATbits.BF != 0);
    while((SSPCON2 & 0x1F) || (SSPSTAT & 0x04));
    if (SSPCON2bits.ACKSTAT !=0){
    print("1", 1);
    return;
}

SSPBUF = 0x0;   //Address
while(SSPSTATbits.BF != 0);
if (SSPCON2bits.ACKSTAT !=0){
    print("2", 1);
    return;
}

SSPBUF = x;   //Byte
while(SSPSTATbits.BF != 0);
if (SSPCON2bits.ACKSTAT !=0){
    print("3", 1);
    return;
}

SSPCON2bits.PEN = 1;    //Stop bit
while(SSPCON2bits.PEN != 0);
}

char i2c_readbyte(){
    char x;
    try:
    SSPCON2bits.SEN = 1;    //Start bit
    while(SSPCON2bits.SEN != 0);

    SSPBUF = 0xA0;
    while(SSPSTATbits.BF != 0);
    if (SSPCON2bits.ACKSTAT !=0){
    print("4", 1);
    return;
    }

    SSPBUF = 0x0;   //Address
    while(SSPSTATbits.BF != 0);
    if (SSPCON2bits.ACKSTAT !=0){
    print("5", 1);
    return;
    }

    SSPCON2bits.SEN = 1;    //Start bit
    while(SSPCON2bits.SEN != 0);

    SSPBUF = 0xA1;
    while(SSPSTATbits.BF != 0);
    if (SSPCON2bits.ACKSTAT !=0){
    print("6", 1);
    return;
    }
    SSPCON2bits.ACKDT = 1; 
    SSPCON2bits.RCEN = 1;
    while(SSPSTATbits.BF == 0);
    x = SSPBUF;
    SSPCON2bits.ACKEN = 1;

    SSPCON2bits.PEN = 1;    //Stop bit
    while(SSPCON2bits.PEN != 0);

    return x;
}

Ich benutze den UART, um mir mitzuteilen, an welcher Stelle die ACK nicht empfangen wurde. Das Oszilloskop bestätigt das auch, wenn ich die Wellenform überprüfe.

Wellenform

Warum liefert das EEPROM kein ACK? Ist das ein Simulationsfehler oder mache ich etwas falsch?

Das Ändern der Klimmzüge auf 10k und 4,7k hatte ebenfalls keine Wirkung. Ich habe einen I2C-Debugger verwendet, um zu sehen, ob die richtigen Daten gesendet werden, aber ich habe so etwas gesehen. Kann mir jemand helfen, das zu interpretieren?

I2c-Debugger

Ich habe keine Zeit, Ihren Code zu überprüfen, aber ich stelle fest, dass Ihre I2C-Pullup-Widerstände mit einem Wert von 1k einen sehr niedrigen Wert (dh "stark") haben. Bitte ändern Sie diese beiden Widerstände in der Simulation auf 4k7 oder 10k, testen Sie erneut und aktualisieren Sie die Frage unten mit dem Ergebnis dieses Tests, damit alle Leser dieses Ergebnis leicht sehen können.
Es hat keine Veränderung bewirkt.
@Sam a 100k hat aus irgendeinem Grund funktioniert
"100k hat aus irgendeinem Grund funktioniert" - Wie Scott auch in einem Kommentar zu Ihrer Antwort erwähnte, ist dies im wirklichen Leben kein vernünftiger Wert für I2C-Klimmzüge. Dies deutet darauf hin, dass irgendwo in der von Ihnen verwendeten Simulation ein Problem vorliegt .
FYI - Obwohl ich Proteus schon lange nicht mehr verwendet habe, fand ich diese vorherige EE.SE-Frage " I2C-Pullup-Widerstände funktionieren nicht in der Simulation ", die darauf hindeutet, dass I2C-Pullup-Widerstände nicht unbedingt als normale Widerstände in Proteus simuliert werden können.

Antworten (1)

Gelöst ... für alle, die dieses Problem haben - ändern Sie die Klimmzüge auf 100k und es funktioniert wie ein Zauber.

Ich bitte den OP, diese Frage zu archivieren, damit der Code von anderen verwendet werden kann, die ihn möglicherweise benötigen.

100k ist einfach eine verrückte Zahl für einen I2C-Pullup.
Ich weiß, deshalb habe ich es am Anfang nicht versucht