Hi all,
I already checked for this issue and I didn't find any post.
I'm trying to make the LPC1125 work as slave on I2C using the interrupt mode, but I can't. When the program runs it doesn't hit the ISR when I try to connect to.
Based on the provided example periph_i2c I wrote my init (using the provided lpc_chip_112x) as:
void Init_I2C_Slave(void){
/* Set the I2C inputs as standard mode*/
Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIO0_4, IOCON_FUNC1);
Chip_IOCON_PinMuxSet(LPC_IOCON, IOCON_PIO0_5, IOCON_FUNC1);
/* Init I2C module */
Chip_I2C_Init(I2C0);
/* Set the clock rate for the I2C peripheral */
Chip_I2C_SetClockRate(I2C0, I2C_DEFAULT_SPEED);
/* Set the I2C mode to interrupt*/
Chip_I2C_SetMasterEventHandler(I2C0, Chip_I2C_EventHandler);
/* Configure the I2C parameters */
dev_xfer.slaveAddr = (I2C_SLAVE_ADDR << 1);
dev_xfer.rxBuff = &g_comm.rxBuff;
dev_xfer.rxSz = sizeof(g_comm.rxBuff);
dev_xfer.txBuff = &g_comm.txBuff;
dev_xfer.txSz = sizeof(g_comm.txBuff);
Chip_I2C_SlaveSetup(I2C0, I2C_SLAVE_0, &g_comm, I2C_Events, 0);
}
Where my events function has been defined as:
static void I2C_Events(I2C_ID_T id, I2C_EVENT_T event){
switch(event){
case I2C_EVENT_DONE:
printf("I2C done event\r\n");
printf("%i\r\n", g_comm.rxBuff);
// update size
printf("\r\n");
break;
case I2C_EVENT_SLAVE_RX:
printf("I2C receive event\r\n");
printf("%i\r\n", g_comm.rxBuff);
printf("\r\n");
break;
case I2C_EVENT_SLAVE_TX:
printf("I2C transmit event\r\n");
printf("%i\r\n", g_comm.txBuff);
printf("\r\n");
break;
}
}
And my exchange data structure globally defined (to share data across the program) as:
/* Global communication structure */
typedef struct {
uint8_t rxBuff;
uint8_t txBuff;
}g_comm_t;
g_comm_t g_comm;
Finally my IRQ handler defined as:
/**
* @brief I2C Interrupt Handler
* @return None
*/
void I2C_IRQHandler(void)
{
Chip_I2C_SlaveStateHandler(I2C0);
}
Of course in my main I call the init and I enable the NVIC as well:
/* Init the I2C module as slave */
Init_I2C_Slave();
/* Enable the I2C NVIC interrupt */
NVIC_EnableIRQ(I2C0_IRQn);
My questions are:
Are the functions of my Init_I2C_Slave routine executed in the right order?
In the device user manual (rev1.0) at Slave Receiver mode (page 101) it is written that to initialize the I2C module as slave receiver I have to write the Slave Address register and write the I2C Control Set register as follow:
But if you take a look to the Chip_I2C_Init it is implemented as follow:
{
enableClk(id);
/* Bring I2C out of reset */
Chip_SYSCON_PeriphReset(RESET_I2C0);
/* Set I2C operation to default */
LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
}
As you can see above the flags: SI, STA are set too.
Should then exist a different Init function for the I2C configured as Slave?
One more: the function Chip_I2C_SetMasterEventHandler needs to be used in the I2C Slave mode as well? Because the name it is a bit misleading and I couldn't find any good explanation other than:
/* Set the master event handler */
int Chip_I2C_SetMasterEventHandler(I2C_ID_T id, I2C_EVENTHANDLER_T event){
...
}
In its own definition.
I assume "yes" since this part exists in the provided example... But I don't understand what it does.
Could you please help me to fix this?
Solved! Go to Solution.
Hi all,
I've been able to fix the issue.
I made a mistake in my Init_I2C_Slave function, I wrongly passed my data structure (g_comm) instead of the correct one.
In fact the Chip_I2C_SlaveSetup function (declared as below) needs its I2C_XFER_T data structure.
void Chip_I2C_SlaveSetup(
I2C_ID_T id,
I2C_SLAVE_ID sid,
I2C_XFER_T *xfer,
I2C_EVENTHANDLER_T event,
uint8_t addrMask);
The correct code results then:
void Init_I2C_Slave(void){
...
...
/* Configure the I2C parameters */
dev_xfer.slaveAddr = (I2C_SLAVE_ADDR << 1);
dev_xfer.rxBuff = &g_comm.rxBuff;
dev_xfer.rxSz = sizeof(g_comm.rxBuff);
dev_xfer.txBuff = &g_comm.txBuff;
dev_xfer.txSz = sizeof(g_comm.txBuff);
Chip_I2C_SlaveSetup(I2C0, I2C_SLAVE_0, &dev_xfer, I2C_Events, 0);
}
I can then answer also to the other questions:
LPC_I2Cx(id)->CONSET = (I2C_CON_AA | I2C_CON_I2EN);
Hi @Alice_Yang ,
many thanks for your reply.
The function I invoked is part of "your" library (have a look to the i2c_112x.c) :
/* Initializes the LPC_I2C peripheral with specified parameter */
void Chip_I2C_Init(I2C_ID_T id)
{
enableClk(id);
/* Bring I2C out of reset */
Chip_SYSCON_PeriphReset(RESET_I2C0);
/* Set I2C operation to default */
LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
}
/* Set I2C operation to default */
LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
LPC_I2Cx(id)->CONSET = (I2C_CON_AA | I2C_CON_I2EN);
... But I still not receiving (ISR not triggered).
And yes I'm using an external I2C logger as well.
Many thanks!
Kind regards,
superaga
Hi all,
I've been able to fix the issue.
I made a mistake in my Init_I2C_Slave function, I wrongly passed my data structure (g_comm) instead of the correct one.
In fact the Chip_I2C_SlaveSetup function (declared as below) needs its I2C_XFER_T data structure.
void Chip_I2C_SlaveSetup(
I2C_ID_T id,
I2C_SLAVE_ID sid,
I2C_XFER_T *xfer,
I2C_EVENTHANDLER_T event,
uint8_t addrMask);
The correct code results then:
void Init_I2C_Slave(void){
...
...
/* Configure the I2C parameters */
dev_xfer.slaveAddr = (I2C_SLAVE_ADDR << 1);
dev_xfer.rxBuff = &g_comm.rxBuff;
dev_xfer.rxSz = sizeof(g_comm.rxBuff);
dev_xfer.txBuff = &g_comm.txBuff;
dev_xfer.txSz = sizeof(g_comm.txBuff);
Chip_I2C_SlaveSetup(I2C0, I2C_SLAVE_0, &dev_xfer, I2C_Events, 0);
}
I can then answer also to the other questions:
LPC_I2Cx(id)->CONSET = (I2C_CON_AA | I2C_CON_I2EN);
Hello @superaga
1)
/* Set I2C operation to default */
LPC_I2Cx(id)->CONCLR = (I2C_CON_AA | I2C_CON_SI | I2C_CON_STA | I2C_CON_I2EN);
Pay attention, this is CONCLR register, not CONSET.
This code function is clear SI and STA to 0 .
2) " the function Chip_I2C_SetMasterEventHandler needs to be used in the I2C Slave mode as well? "
->> Yes.
Recommend you use logic analyzer measure I2C signal.
BR
Alice