Sin ACK de I2C EEPROM PIC18F

Estoy tratando de almacenar algunos datos en la EEPROM 24AA01 usando el PIC18F13K22. Como estoy esperando los componentes, pensé en seguir adelante y simularlo en Proteus.

Esquemático

Este es mi código (basado en el compilador XC8).

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

Uso la UART para que me diga en qué momento no se recibió el ACK. El osciloscopio también lo confirma cuando compruebo la forma de onda.

forma de onda

¿Por qué la EEPROM no proporciona un ACK? ¿Es un error de simulación o estoy haciendo algo mal?

Cambiar los pull-ups a 10k y 4.7k tampoco tuvo efecto. Usé un depurador I2C para ver si iban los datos correctos, pero vi algo como esto. ¿Alguien puede ayudarme a interpretar esto?

Depurador I2c

No tengo tiempo para revisar su código, pero noto que sus resistencias pull-up I2C tienen un valor muy bajo (es decir, "fuertes") con un valor de 1k. Cambie ambas resistencias en la simulación a 4k7 o 10k, vuelva a probar y actualice la pregunta en la parte inferior con el resultado de esa prueba, para que todos los lectores puedan ver ese resultado fácilmente.
No creó ningún cambio.
@Sam a 100k funcionó por alguna razón
"100k funcionó por alguna razón": como Scott también mencionó en un comentario sobre su respuesta, en la vida real, ese no es un valor sensato para los pull-ups I2C. Esto sugiere que hay un problema en algún lugar de la simulación que estaba usando.
FYI: aunque no he usado Proteus durante mucho tiempo, encontré esta pregunta anterior de EE.SE " Las resistencias pull-up I2C no funcionan en la simulación ", lo que sugiere que las resistencias pull-up I2C no necesariamente se pueden simular como resistencias normales en Proteus.

Respuestas (1)

Resuelto ... para cualquiera que tenga este problema: cambie los pull ups a 100k y funciona de maravilla.

Solicito al operador que archive esta pregunta para que el código pueda ser utilizado por otras personas que puedan necesitarlo.

100k es simplemente un número extravagante para un pullup I2C.
Lo sé, es por eso que no lo intenté al principio.