Electrical – Two PIC 18f4620 , one as master & the second is slave I2C communication problem

i2cmicrocontrollerpicproteus

Link for PIC microcontroller 18F4620 datasheet if you may need it

I use "Mikroc for PIC pro 6.0" as a compiler and I write a program to communicate between two 18f4620 one is master and the other is slave .Both slave and master are working in HS oscillator mode with 4MHZ crystal oscillator

The complete code for master pic 18f4620

        //MAster pic 18f4620

   const unsigned short int crystalOscillator =4000000;



    void I2C_Master_Init(const unsigned long c)
    {
     SSPCON1 = 0b00101000;
     SSPCON2 = 0;
     SSPADD = (crystalOscillator/(4*c))-1;
     SSPSTAT = 0;
     TRISC.B3 = 1; //Setting as input as given in datasheet
     TRISC.B4 = 1; //Setting as input as given in datasheet
    }



    void I2C_Master_Wait()
    {
     while ((SSPSTAT & 0x04) || (SSPCON2 & 0x1F));
    }



    void I2C_Master_Start()
    {
     I2C_Master_Wait();
     SSPCON2.SEN = 1;
    }



    void I2C_Master_RepeatedStart()
    {
     I2C_Master_Wait();
     SSPCON2.RSEN = 1;
    }



    void I2C_Master_Stop()
    {
     I2C_Master_Wait();
     SSPCON2.PEN = 1;
    }



    void I2C_Master_Write(unsigned short int d)
    {
     I2C_Master_Wait();
     SSPBUF = d;
    }



    unsigned short int I2C_Master_Read(unsigned short int a)
    {
     unsigned short temp;
     I2C_Master_Wait();
     SSPCON2.RCEN = 1;
     I2C_Master_Wait();
     temp = SSPBUF;
     I2C_Master_Wait();
     if(a==1){SSPCON2.ACKDT=1;}
     else{SSPCON2.ACKDT=0;}
     SSPCON2.ACKEN = 1;
     return temp;
    }



    void main()
    {
     I2C_Master_Init(100000); //Initialize I2C Master with 100KHz clock
     Delay_ms(500);
     while(1)
     {
     I2C_Master_Start(); //Start condition
     I2C_Master_Write(0x30); //7 bit address + Write
    // I2C_Master_Write(0x00); //Write data
     //I2C_Master_Write(0x00);
     I2C_Master_Stop(); //Stop condition
     Delay_ms(2000);
     }
    }

The complete code for slave pic 18f4620

         //Slave pic 18f4620

//##############################################################################
unsigned short int zed=0;
volatile unsigned short int new =0 ,dataRead=0 , dataWrite=0;
unsigned char dataReadCh[7] , dataWriteCh[7];
//##############################################################################
void interrupt()
{
 if(PIR1.SSPIF == 1)
 {
  SSPCON1.CKP = 0;
  new=1;
 if ((SSPCON1.SSPOV) || (SSPCON1.WCOL))
 {
  zed = SSPBUF; // Read the previous value to clear the buffer
  SSPCON1.SSPOV = 0; // Clear the overflow flag
  SSPCON1.WCOL = 0; // Clear the collision bit
  SSPCON1.CKP = 1;
 }
 if((!SSPSTAT.D_A||SSPSTAT.D_A) && !SSPSTAT.R_W)
 {
  while(!SSPSTAT.BF){};
  while(SSPSTAT.BF){dataRead = SSPBUF;}
  SSPCON1.CKP = 1;
 }
 else if((!SSPSTAT.D_A||SSPSTAT.D_A) && SSPSTAT.R_W)
 {
  while(SSPSTAT.BF){zed = SSPBUF;}
  SSPBUF = dataWrite ;
  SSPCON1.CKP = 1;
  while(SSPSTAT.BF){};
 }
 PIR1.SSPIF = 0;
 }
}
//##############################################################################
void I2C_Slave_Init(unsigned short int address)
{
 SSPSTAT = 0b10000000;
 SSPADD = address;
 SSPCON1 = 0b00110110;
 SSPCON2 = 0b00000001;
 TRISC.B3 = 1; //Setting as input as given in datasheet
 TRISC.B4 = 1; //Setting as input as given in datasheet
 TRISC.B0=1;
 TRISC.B1=1;TRISC.B2=1;TRISC.B5=1;TRISC.B6=1;TRISC.B7=1;
 INTCON = 0b00000000;
 INTCON.PEIE = 1;
 INTCON.GIE = 1;
 PIE1.SSPIE = 1;
 PIR1.SSPIF = 0;
 while(SSPSTAT.BF){zed = SSPBUF;SSPCON1.SSPOV = 0;SSPCON1.WCOL = 0;}
}
//##############################################################################

void main() 
{
 ADCON1=0b00001111;
 TRISA.B0 = 0; //PORTD as output
 PORTA.B0=0;
 I2C_Slave_Init(0x18); //Initialize as a I2C Slave with address 0x30
 while(1)
 {
  if(new==1)
  {
   PORTA.B0=1;
   new=0;
  }
 }
}

I use those code in both "protues 8.0 simulator" and in real 18f6420 Boards

enter image description here

I never get a reaction from the slave as if it is not existed i alway get "notACK" signal which is not known is it from the Master or a responce from the slave but i am sure that "PIR1.SSPIF" never becomes equal 1, as once this happen after an MSSP interrupt happens the valu of the variable named "new" will be equal 1 and the LED on PORTA.B0 will light up

This Image contains the wave from of the oscilloscope showing the "NOT ACK" signal  at the 9th BIT

So any help please or any edit on my code u may suggest to make it work please

Note:when i change SSPMx to be 1110 instead of 0110 the slave MSSP interrupt happens and PIR1.SSPIF becomes 1 . LED on PORTA.B0 lights up so the slave is successfully interrupts on start stop bit but not with address byte sending nor with General Call as i tried to enable general call and send 0x00h but i still get "NOT ACK" signal in the end

SSPM3:SSPM0: Master Synchronous Serial Port Mode Select bits(2)

1111 = I2C Slave mode, 10-bit address with Start and Stop bit
interrupts enabled

1110 = I2C Slave mode, 7-bit address with Start and Stop bit
interrupts enabled

1011 = I2C Firmware Controlled Master mode (Slave Idle)

1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1))

0111 = I2C Slave mode, 10-bit address

0110 = I2C Slave mode, 7-bit address

Best Answer

Change R1 and R2 Pull up resistance 1000 ohms to 4.7komh's That's the first problem in your circuit another things is please insure your wiring is accurate and connected

Add small delay between start address data and stop for debugging and use i2c debugger in Proteus to check where your micro controller stuck

1000 = I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) Use this mode