I am currently attempting to write from a LPC1549JBD64 on a custom board to a number of I2C devices.
The code I have written is based on the LPCOpen "periph_i2cm_interrupt"
Initially I ran into an issue where after the master would transmit 2bytes (1 addr, 1 data) then the second ACK from the slave was not received. This resulted in SCL remaining low indefinitely and MSTSTATE in the STAT register to stay at TRANSMIT_READY, not returning to IDLE.
This was solved by placing a short delay after the __WFI() function in the 'waitForI2CXferComplete()', allowing time for the slave's ACK to be read. And the clock and registers to return to an idle state.
I have subsequently ran into an issue where the values in INTENSET cannot be cleared, resulting in the I2C interrupt handler forcing the code into an infinite loop. I have tried setting all the bits in INTENSET to 0, also writing directly to the appropriate bits in INTENCLR, though this does not clear the corresponding interrupt enables.
I am not sure what to do to overcome this, I am relatively new to NXP's systems and I2C so any help at all would be greatly appreciated.
Relevant code is enclosed, if there is any more information need please ask.
void setupI2CMaster(void)
{
initI2CPinMux();
Chip_I2C_Init(LPC_I2C0);
Chip_I2C_SetClockDiv(LPC_I2C0, I2C_CLK_DIVIDER);
Chip_I2CM_SetBusSpeed(LPC_I2C0, I2C_BITRATE);
Chip_I2CM_Enable(LPC_I2C0);
}
void waitForI2CXferComplete(I2CM_XFER_T *xferRecPtr)
{
while(xferRecPtr->status == I2CM_STATUS_BUSY)
{
__WFI();
Delay_us(1); // Delay prevents final ACK being ignored
}
}
void setupXferRecAndExecute(uint8_t SlvAddr,
uint8_t *txBuffPtr,
uint8_t txSize,
uint8_t *rxBuffPtr,
uint8_t rxSize)
{
i2cmXferRec.slaveAddr = SlvAddr;
i2cmXferRec.status = 0;
i2cmXferRec.txSz = txSize;
i2cmXferRec.rxSz = rxSize;
i2cmXferRec.txBuff = txBuffPtr;
i2cmXferRec.rxBuff = rxBuffPtr;
Chip_I2CM_Xfer(LPC_I2C0, &i2cmXferRec);
Chip_I2C_EnableInt(LPC_I2C0, I2C_INTENSET_MSTPENDING | I2C_INTENSET_MSTRARBLOSS | I2C_INTENSET_MSTSTSTPERR);
waitForI2CXferComplete(&i2cmXferRec);
Chip_I2C_ClearInt(LPC_I2C0, I2C_INTENSET_MSTPENDING | I2C_INTENSET_MSTRARBLOSS | I2C_INTENSET_MSTSTSTPERR);
/*
LPC_I2C0->INTENCLR = I2C_INTENSET_MSTPENDING;
LPC_I2C0->INTENCLR = I2C_INTENSET_MSTRARBLOSS;
LPC_I2C0->INTENCLR = I2C_INTENSET_MSTSTSTPERR;
LPC_I2C0->INTENSET = 0;
*/
Delay_us(100); // Delay must be present for continued operation. Without it collisions(?) can occur.
}
void sendI2CConfig(void)
{
setupXferRecAndExecute( POT_ADDR_7BIT,
configPotArray, 1,
configPotReceive, 0);
setupXferRecAndExecute( DAC_ADDR_7BIT,
configDACArray, 2,
configDACReceive, 0);
setupXferRecAndExecute( DAC_ADDR_7BIT,
modeDACArray, 2,
modeDACReceive, 0);
setupXferRecAndExecute( ADC_ADDR_7BIT,
configADCArray, 2,
configADCReceive, 0);
}