LPC1125 as I2C slave

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1125 as I2C slave

Jump to solution
1,250 Views
superaga
Contributor III

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:

pic_01.png

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?

Labels (1)
Tags (1)
0 Kudos
Reply
1 Solution
1,232 Views
superaga
Contributor III

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:

  • Should then exist a different Init function for the I2C configured as Slave?
    • No, the existing function works properly.
    • There is no need to further add the following line (inside the Chip_I2C_Init function):

 

 

LPC_I2Cx(id)->CONSET = (I2C_CON_AA | I2C_CON_I2EN);

 

 

  • Is there an order to execute the Init function (Init_I2C_Slave)?
    • The used order (in my Init_I2C_Slave routine) worked properly.

 

 

View solution in original post

0 Kudos
Reply
3 Replies
1,236 Views
superaga
Contributor III

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);
}

 

  • Should then exist a different Init function for the I2C configured as Slave?
    • I added also the CONSET line as:

 

/* 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.

  • Is there an order to execute the Init function (Init_I2C_Slave)?
  • Is there something else I forgot to check?
    • Any suggestions?

Many thanks!

Kind regards,

superaga

0 Kudos
Reply
1,233 Views
superaga
Contributor III

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:

  • Should then exist a different Init function for the I2C configured as Slave?
    • No, the existing function works properly.
    • There is no need to further add the following line (inside the Chip_I2C_Init function):

 

 

LPC_I2Cx(id)->CONSET = (I2C_CON_AA | I2C_CON_I2EN);

 

 

  • Is there an order to execute the Init function (Init_I2C_Slave)?
    • The used order (in my Init_I2C_Slave routine) worked properly.

 

 

0 Kudos
Reply
1,241 Views
Alice_Yang
NXP TechSupport
NXP TechSupport

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

 

0 Kudos
Reply