#include "lpc17xx.h"
#include "type.h"
#include "i2c.h"
#include "lcd.h"
volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint32_t I2CSlaveState = I2C_IDLE;
volatile uint32_t I2CCmd;
volatile uint32_t I2CMode;
volatile uint8_t I2CMasterBuffer[BUFSIZE];
volatile uint8_t I2CSlaveBuffer[BUFSIZE];
volatile uint32_t I2CCount = 0;
volatile uint32_t I2CReadLength;
volatile uint32_t I2CWriteLength;
volatile uint32_t RdIndex = 0;
volatile uint32_t WrIndex = 0;
void I2C0_IRQHandler(void)
{
uint8_t StatValue;
/* this handler deals with master read and master write only */
StatValue = LPC_I2C0->I2STAT;
switch ( StatValue )
{
case 0x08:/* A Start condition is issued. */
WrIndex = 0;
LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10:/* A repeated started is issued */
RdIndex = 0;
/* Send SLA with R bit set, */
LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18:/* Regardless, it's a ACK */
if ( I2CWriteLength == 1 )
{
LPC_I2C0->I2CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NO_DATA;
}
else
{
LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
}
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x28:/* Data byte has been transmitted, regardless ACK or NACK */
if ( WrIndex < I2CWriteLength )
{
LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++]; /* this should be the last one */
}
else
{
if ( I2CReadLength != 0 )
{
LPC_I2C0->I2CONSET = I2CONSET_STA;/* Set Repeated-start flag */
}
else
{
LPC_I2C0->I2CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_OK;
}
}
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x30:
LPC_I2C0->I2CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NACK_ON_DATA;
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x40:/* Master Receive, SLA_R has been sent */
if ( (RdIndex + 1) < I2CReadLength )
{
/* Will go to State 0x50 */
LPC_I2C0->I2CONSET = I2CONSET_AA;/* assert ACK after data is received */
}
else
{
/* Will go to State 0x58 */
LPC_I2C0->I2CONCLR = I2CONCLR_AAC;/* assert NACK after data is received */
}
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x50:/* Data byte has been received, regardless following ACK or NACK */
I2CSlaveBuffer[RdIndex++] = LPC_I2C0->I2DAT;
if ( (RdIndex + 1) < I2CReadLength )
{
LPC_I2C0->I2CONSET = I2CONSET_AA;/* assert ACK after data is received */
}
else
{
LPC_I2C0->I2CONCLR = I2CONCLR_AAC;/* assert NACK on last byte */
}
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x58:
I2CSlaveBuffer[RdIndex++] = LPC_I2C0->I2DAT;
I2CMasterState = I2C_OK;
LPC_I2C0->I2CONSET = I2CONSET_STO;/* Set Stop flag */
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;/* Clear SI flag */
break;
case 0x20:/* regardless, it's a NACK */
case 0x48:
LPC_I2C0->I2CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NACK_ON_ADDRESS;
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
case 0x38:/* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I2CMasterState = I2C_ARBITRATION_LOST;
LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
break;
}
}
uint32_t I2CStart( void )
{
uint32_t timeout = 0;
uint32_t retVal = FALSE;
/*--- Issue a start condition ---*/
LPC_I2C0->I2CONSET = I2CONSET_STA;/* Set Start flag */
/*--- Wait until START transmitted ---*/
while( 1 )
{
if ( I2CMasterState == I2C_STARTED )
{
retVal = TRUE;
break;
}
if ( timeout >= MAX_TIMEOUT )
{
lcd_gotoxy(1,0);
lcd_print("MAX_TIMEOUT");
retVal = FALSE;
break;
}
timeout++;
}
return( retVal );
}
uint32_t I2CStop( void )
{
LPC_I2C0->I2CONSET = I2CONSET_STO; /* Set Stop flag */
LPC_I2C0->I2CONCLR = I2CONCLR_SIC; /* Clear SI flag */
/*--- Wait for STOP detected ---*/
while( LPC_I2C0->I2CONSET & I2CONSET_STO );
return TRUE;
}
uint32_t I2CInit( uint32_t I2cMode )
{
LPC_SC->PCONP |= (1 << 7);
/* set PIO0.27 and PIO0.28 to I2C0 SDA and SCL */
/* function to 01 on both SDA and SCL. */
LPC_PINCON->PINSEL1 &= ~((0x03<<22)|(0x03<<24));
LPC_PINCON->PINSEL1 |= ((0x01<<22)|(0x01<<24));
/*--- Clear flags ---*/
LPC_I2C0->I2CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
LPC_PINCON->I2CPADCFG &= ~((0x1<<0)|(0x1<<2));
LPC_I2C0->I2SCLL = I2SCLL_SCLL;
LPC_I2C0->I2SCLH = I2SCLH_SCLH;
/* Install interrupt handler */
NVIC_EnableIRQ(I2C0_IRQn);
LPC_I2C0->I2CONSET = I2CONSET_I2EN;
return( TRUE );
}
uint32_t I2CEngine( void )
{
I2CMasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;
lcd_clear();
if ( I2CStart() != TRUE )
{
I2CStop();
return ( FALSE );
}
while ( 1 )
{
if ( I2CMasterState == DATA_NACK )
{
I2CStop();
break;
}
}
return ( TRUE );
}
|