I am writing an I2C slave routine for PIC18F25K80 and I am stuck on a weird problem.
This is my routine:
void interrupt interruption_handler() {
PIE1bits.SSPIE = 0; // Disable Master Synchronous Serial Port Interrupt
if (PIR1bits.SSPIF != 1) {
//This is not I2C interruption;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
return;
}
//Treat overflow
if ((SSPCON1bits.SSPOV) || (SSPCON1bits.WCOL)) {
dummy = SSPBUF; // Read the previous value to clear the buffer
SSPCON1bits.SSPOV = 0; // Clear the overflow flag
SSPCON1bits.WCOL = 0; // Clear the collision bit
SSPCON1bits.CKP = 1;
board_state = BOARD_STATE_ERROR;
} else {
if (!SSPSTATbits.D_NOT_A) {
//Slave address
debug(0, ON);
//Read address
address = SSPBUF; //Clear BF
while(BF); //Wait until completion
if (SSPSTATbits.R_NOT_W) {
SSPCON1bits.WCOL = 0;
unsigned char a = 0x01;
SSPBUF = a;//0x01 works //Deliver first byte
asm("nop");
}
} else {
if (SSPSTATbits.BF) {
dummy = SSPBUF; // Clear BF (just in case)
while(BF);
}
if (SSPSTATbits.R_NOT_W) {
//Multi-byte read
debug(1, ON);
SSPCON1bits.WCOL = 0;
SSPBUF = 0x02; //Deliver second byte
asm("nop");
} else {
//WRITE
debug(2, ON);
}
}
transmitted = TRUE;
SSPCON1bits.CKP = 1;
PIR1bits.SSPIF = 0;
PIE1bits.SSPIE = 1; // Enable Master Synchronous Serial Port Interrupt
}
}
It works like a charm if I set constant values on SSPBUF. For example, if you do:
SSPBUF = 0x01;
(...)
SSPBUF = 0x02;
I get the two bytes on the master. I can even see the wave forms of the bytes being transmitted on the oscilloscope. Quite fun!
But when I try to set SSPBUF using a variable like:
unsigned char a = 0x01;
SSPBUF = a;
I get zero on the master.
It is driving me crazy.
Some hypothesis I've discarded:
It makes no sense to me. How good it is if you cannot define an arbitrary value using a variable?
Please gurus out there, enlighten this poor programmer.
Thanks in advance.
It has something to do with how the compiler generates the code and some undocumented/unknown PIC restriction around SSPBUF (it is an special register anyway).
I found out that it works when the compiler uses movwf and does not work when the compiler uses movff.
I moved the question to another forum because I realized the audience there is more adequate.
You will find more details here: https://electronics.stackexchange.com/questions/251763/writing-sspbuf-from-variable-in-i2c-slave-protocol-in-pic18/251771#251771