Electronic – No ACK from I2C EEPROM PIC18F

eepromi2cpic

Im trying to store some data in the 24AA01 EEPROM using the PIC18F13K22. Since I am awaiting the components, I thought I will go ahead and simulate it in Proteus.

Schematic

This is my code (XC8 compiler based).

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

I use the UART to tell me at what point the ACK was not received. The oscilloscope also confirms that when I check the waveform.

Waveform

Why isn't the EEPROM providing an ACK? Is it a simulation bug or am I doing something wrong?

Changing the pull-ups to 10k and 4.7k had no effect as well. I used an I2C debugger to see if the correct data was going but I saw something like this. Can anyone help me intepret this?

I2c Debugger

Best Answer

Solved ... to anybody who has this problem - change the pull ups to 100k and it works like a charm.

I request the Op to archive this question so that the code can be used by others who might need it.