This is my IIC slave driver (sorry, I can't see any option to format the text as source code). I don't proces IIC events in ISR. When an IIC interrupt occurs, I disable it at NVIC and later proces the interrupt in my main program (IicSlaveExecute()). Calls IicSlaveAddressed, IicSlaveStopped, IicSlaveByteGet, IicSlaveByteProcess are callbacks to my application level.
Macros Flag(), ArbitrationLost(), ... are abbreviations for IIC->S & I2C_S_IICIF_MASK, IIC->S & I2C_S_ARBL_MASK, ...
void IicSlaveInit( void)
// Initialize bus
{
SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK
PinFunction(IIC_SLAVE_SDA_PIN, IIC_SLAVE_SDA_PIN_FUNCTION);
PinFunction(IIC_SLAVE_SCL_PIN, IIC_SLAVE_SCL_PIN_FUNCTION);
IIC->C1 = 0;
CpuIrqAttach(I2C0_IRQn, 0, I2C0_IRQHandler);
CpuIrqEnable( I2C0_IRQn);
IIC->A1 = IIC_SLAVE_ADDRESS;
IIC->C1 = I2C_C1_IICEN_MASK | I2C_C1_IICIE_MASK; | I2C_C1_WUEN_MASK;
IIC->FLT |= I2C_FLT_STOPIE_MASK;
} // IicSlaveInit
void IicSlaveExecute( void)
// Execute
{
byte Data;
if(!Flag()) {
return;
}
if(IIC->FLT & 16) { // if I don't
IIC->FLT |= 16;
ClearFlag();
} else if(ArbitrationLost()) {
ArbitrationLostClear();
ClearFlag();
} else if(StopFlag()) {
ClearStopFlag();
ClearFlag();
Acknowledge();
SetReceiveMode();
Read();
IicSlaveStopped();
} else if(Addressed()) {
ClearFlag();
IicSlaveAddressed( !ReadWrite());
Acknowledge();
if(ReadWrite()) {
SetTransmitMode();
if(!IicSlaveByteGet( &Data)) {
Data = 0xFF;
}
Send( Data);
} else {
SetReceiveMode();
Read();
}
} else {
ClearFlag();
if(ReadWrite()) {
if(Acknowledged()) { // ACK, Tx byte
if(!IicSlaveByteGet( &Data)) {
Data = 0xFF;
}
Send( Data);
} else { // NACK, turn off Tx
SetReceiveMode();
Read();
}
} else {
Acknowledge();
Data = Read();
IicSlaveByteProcess(Data);
}
}
CpuIrqEnable( I2C0_IRQn);
} // IicSlaveExecute
void __irq I2C0_IRQHandler( void)
// ISR
{
CpuIrqDisable( I2C0_IRQn);
} // I2C0_IRQHandler