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
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
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