#include "LPC13Uxx.h" /* LPC13xx definitions */
#include "i2c.h"
volatile uint32_t timeout = 0;
volatile uint32_t I2CMode;
volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint8_t I2CMasterBuffer[BUFSIZE];
volatile uint8_t I2CSlaveBuffer[BUFSIZE];
volatile uint32_t I2CReadLength;
volatile uint32_t I2CWriteLength;
volatile uint32_t RdIndex = 0;
volatile uint32_t WrIndex = 0;
/*****************************************************************************
** Function name:I2C_IRQHandler
**
** Descriptions:I2C interrupt handler, deal with master mode only.
**
** parameters:None
** Returned value:None
**
*****************************************************************************/
void I2C_IRQHandler(void)
{
uint8_t StatValue;
timeout = 0;
/* this handler deals with master read and master write only */
StatValue = LPC_I2C->STAT;
switch ( StatValue )
{
case 0x08:/* A Start condition is issued. */
WrIndex = 0;
RdIndex = 0;
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10:/* A repeated started is issued */
RdIndex = 0;
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++]; /* Send SLA with R bit set, */
LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18:
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x28:/* Data byte has been transmitted, regardless ACK or NACK */
if ( WrIndex < I2CWriteLength )
{
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++]; /* this should be the last one */
}
else
{
if ( I2CReadLength != 0 )
{
LPC_I2C->CONSET = I2CONSET_STA;/* Set Repeated-start flag */
}
else
{
LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_OK;
}
}
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x30:
LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NACK_ON_DATA;
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x40:/* Master Receive, SLA_R has been sent */
if ( (RdIndex + 1) < I2CReadLength )
{
/* Will go to State 0x50 */
// I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
LPC_I2C->CONSET = I2CONSET_AA;/* assert ACK after data is received */
}
else
{
/* Will go to State 0x58 */
// I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
LPC_I2C->CONCLR = I2CONCLR_AAC;/* assert NACK after data is received */
}
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x50:/* Data byte has been received, regardless following ACK or NACK */
I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
if ( (RdIndex + 1) < I2CReadLength )
{
LPC_I2C->CONSET = I2CONSET_AA;/* assert ACK after data is received */
}
else
{
LPC_I2C->CONCLR = I2CONCLR_AAC;/* assert NACK on last byte */
}
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x58:
I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
I2CMasterState = I2C_OK;
LPC_I2C->CONSET = I2CONSET_STO;/* Set Stop flag */
LPC_I2C->CONCLR = I2CONCLR_SIC;/* Clear SI flag */
break;
case 0x20:/* regardless, it's a NACK */
case 0x48:
LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NACK_ON_ADDRESS;
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
case 0x38:/* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I2CMasterState = I2C_ARBITRATION_LOST;
LPC_I2C->CONCLR = I2CONCLR_SIC;
break;
}
return;
}
/*****************************************************************************
** Function name:I2CInit
**
** Descriptions:Initialize I2C controller
**
** parameters:I2c mode is either MASTER or SLAVE
** Returned value:true or false, return false if the I2C
**interrupt handler was not installed correctly
**
*****************************************************************************/
uint32_t I2CInit( uint32_t I2cMode )
{
LPC_SYSCON->PRESETCTRL |= (0x1<<1);
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5);
LPC_IOCON->PIO0_4 &= ~0x3F;/* I2C I/O config */
LPC_IOCON->PIO0_4 |= 0x01;/* I2C SCL */
LPC_IOCON->PIO0_5 &= ~0x3F;
LPC_IOCON->PIO0_5 |= 0x01;/* I2C SDA */
/*--- Clear flags ---*/
LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
LPC_I2C->SCLL = I2SCLL_SCLL;
LPC_I2C->SCLH = I2SCLH_SCLH;
/* Enable the I2C Interrupt */
NVIC_EnableIRQ(I2C_IRQn);
LPC_I2C->CONSET = I2CONSET_I2EN;
return( TRUE );
}
/*****************************************************************************
** Function name:I2CEngine
**
** Descriptions:The routine to complete a I2C transaction
**from start to stop. All the intermitten
**steps are handled in the interrupt handler.
**Before this routine is called, the read
**length, write length, I2C master buffer,
**and I2C command fields need to be filled.
**see i2cmst.c for more details.
**
** parameters:None
** Returned value:true or false, return false only if the
**start condition can never be generated and
**timed out.
**
*****************************************************************************/
uint32_t I2CEngine( void )
{
RdIndex = 0;
WrIndex = 0;
/*--- Issue a start condition ---*/
LPC_I2C->CONSET = I2CONSET_STA;/* Set Start flag */
I2CMasterState = I2C_BUSY;
while ( I2CMasterState == I2C_BUSY )
{
if ( timeout >= MAX_TIMEOUT )
{
I2CMasterState = I2C_TIME_OUT;
break;
}
timeout++;
}
LPC_I2C->CONCLR = I2CONCLR_STAC;
if( I2CMasterState != I2C_OK)
{
while(1);
}
return 0;
} |