📄 i2c.c
字号:
/*****************************************************************************
* i2c.c: I2C C file for NXP LPC210x Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2005.10.01 ver 1.00 Prelimnary version, first Release
*
*****************************************************************************/
#include "LPC210x.H" /* LPC21xx definitions */
#include "type.h"
#include "irq.h"
#include "i2c.h"
#include "gpio.h"
#define SpiComm_Write (0x12)
BYTE I2C0RxCounter;
BYTE I2C0RxFinished = 0;
BYTE I2C0RxBuffer[BUFSIZE];
BYTE I2C0TxCounter;
BYTE I2C0TxFinished = 0;
BYTE I2C0TxBuffer[BUFSIZE];
BYTE mi2cstatus; // I2C_OK or I2C_ERROR
static BYTE mbytenum; // Number of transmitted bytes
#ifdef LPC2102_I2C1_MASTER
unsigned long I2C1MasterState = I2C_IDLE;
unsigned long I2CCmd;
unsigned char I2C1MasterBuffer[BUFSIZE];
unsigned long I2C1ReadLength;
unsigned long I2C1WriteLength;
unsigned long RdIndex = 0;
unsigned long WrIndex = 0;
#endif
/*****************************************************************************
** Function name: I2C0_Init
** Description: Initialize I2C0 controller
** Parameter: I2c mode is either MASTER or SLAVE
** Returned value: true or false; return false if the I2C
** interrupt handler was not installed correctly
*****************************************************************************/
DWORD I2C0_Init( DWORD I2cMode )
{
BYTE i=0;
PINSEL0 |= 0x00000050; // Set P0.2 as SCL0 and P0.3 as SDA0
/*--- Clear flags ---*/
I2C0CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
/*--- Reset registers ---*/
I2C0SCLL = I2SCLL_SCLL;
I2C0SCLH = I2SCLH_SCLH;
if( I2cMode == I2CSLAVE ) /* I2C Slave */
{
I2C0ADR = I2CSL_ADDRS << 1;
}
/* Install interrupt handler */
if( install_irq( I2C0_INT, (void *)I2C0_SlaveHandler ) == FALSE )
{
return( FALSE );
}
/* Enable I2C controller for Master or Slave functions */
if( I2cMode == I2CMASTER )
{
I2C0CONSET = I2CONSET_I2EN;
}
else
{
I2C0CONSET = I2CONSET_I2EN | I2CONSET_AA;
}
/* Initialize I2C Tx and Rx and SPI Rx counters */
I2C0TxCounter = 0;
I2C0RxCounter = 0;
/* Initialize I2C Tx and Rx buffers */
for(i=1; i<BUFSIZE; i++)
{
I2C0TxBuffer[i] = 0x00;
I2C0RxBuffer[i] = 0x00;
}
return( TRUE );
} // I2C0_Init
/*****************************************************************************
** Function name: I2C0_SlaveHandler
** Description: I2C0 interrupt handler, deal with SLAVE mode only.
** Parameter: None
** Returned value: None
*****************************************************************************/
void I2C0_SlaveHandler (void) __irq
{
BYTE StatValue;
/* Reads the I2C status to branch to one of the I2C state routines */
StatValue = I2C0STAT;
IENABLE;
I2C0CONCLR = I2CONCLR_AAC | I2CONCLR_STAC; // Clear STA and AA flags
/* Handles I2C state routines */
switch(StatValue)
{
/****************************************************
* S L A V E R E C E I V E R M O D E *
*****************************************************/
case 0x60: /* Own SLA+W received; ACK returned; Data will be received and ACK returned (Slave Receiver) */
case 0x68:
case 0x70:
case 0x78:
I2C0CONSET = I2CONSET_AA;
I2C0CONCLR = I2CONCLR_SIC;
I2C0RxCounter = 0; // Clear I2C Rx counter
break;
case 0x80: /* Addressed with own SLV address; Data received; ACK returned; Additional data will be read */
case 0x90:
case 0x88: /* Addressed with own SLV address; Data received; Not ACK returned */
case 0x98:
I2C0RxBuffer[I2C0RxCounter] = I2DAT;
if( I2C0RxBuffer[0] == SpiComm_Write ) /* Checks Fn ID: Write I2C receive data to Spi device */
{
if( I2C0RxCounter == 0 ) /* SPI function ID handling */
{
I2C0CONCLR = I2CONCLR_SIC;
I2C0RxCounter++;
}
else /* Unbuffered SPI Write operation */
{
IODIR |= 0x80; // Set P0.7 as output
IOCLR |= 0x80; // Set P0.7 as Low to activate SSEL signal (active-low)
SPI_Send((BYTE*)&I2C0RxBuffer[1], 1);
I2C0CONCLR = I2CONCLR_SIC; // Release SCL clock after SPI communication is completed
}
}
else /* Functions that are not SPI Write */
{
I2C0CONCLR = I2CONCLR_SIC; // Clear SI flag to release SCL clock
if( (I2C0RxCounter+1) <= BUFSIZE )
I2C0RxCounter++;
}
I2C0CONSET = I2CONSET_AA;
break;
case 0xA0: /* STOP or REP.START received while addressed as slave */
if( I2C0RxBuffer[0] == SpiComm_Write )
IOSET |= 0x80; // P0.7 is set as High to de-activate SSEL signal (active-low)
mi2cstatus = I2C_OK;
I2C0CONSET = I2CONSET_AA;
I2C0CONCLR = I2CONCLR_SIC;
i2c_receive_finished();
break;
/************************************************************
* S L A V E T R A N S M I T T E R M O D E *
************************************************************/
case 0xA8: /* Own SLA+R received, Ack returned (slave transmitter) */
case 0xB0:
mbytenum = 0;
case 0xB8: /* Data transmitted, ACK received */
I2C0DAT = I2C0TxBuffer[mbytenum];
I2C0CONSET = I2CONSET_AA;
I2C0CONCLR = I2CONCLR_SIC;
if( i2c_slave_islasttxbyte(mbytenum) )
I2C0TxFinished = 1; // no more data bytes to transmit
mbytenum++;
break;
case 0xC0: /* Data byte transmitted, NACK received last data byte transmitted, NACK received */
case 0xC8:
mi2cstatus = I2C_OK;
I2C0CONSET = I2CONSET_AA;
I2C0CONCLR = I2CONCLR_SIC;
I2C0TxFinished = 1;
i2c_transfer_finished();
break;
default: /* Unknown state */
mi2cstatus = I2C_ERROR;
I2C0CONSET = I2CONSET_AA;
I2C0CONCLR = I2CONCLR_SIC;
break;
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
} // I2C0_SlaveHandler
/***********************************************************************
** Function name: i2c_receive_finished
** Description: Called when an I2C transfer has finished.
** mi2cstatus may be read to determine if the transfer
** was successful (I2C_OK) or failed (I2C_ERROR)
** Parameter: None
** Returned value: None
************************************************************************/
void i2c_receive_finished(void)
{
I2C0RxFinished = 1;
ApplnHandler_Flag = 1;
} // i2c_receive_finished
/***********************************************************************
** Function name: i2c_transfer_finished
** Description: Called when an I2C transfer has finished.
** Resets the transmit buffer and transmit counter.
** Parameter: None
** Returned value: None
************************************************************************/
void i2c_transfer_finished(void)
{
BYTE i;
if(I2C0TxFinished)
{
I2C0TxCounter = 0; /* Clears I2C Tx counter */
for (i=0; i<BUFSIZE; i++)
{
I2C0TxBuffer[i] = 0; /* Clears I2C Tx buffer */
}
}
/* Release interrupt to I2C host */
IODIR |= P0_0_MASKBITPATTERN; /* Ensure P0.0 is configured as output */
IOSET |= P0_0_MASKBITPATTERN; /* Set P0.0 (Active-Low) as High */
if(gInterrupt_Status)
gInterrupt_Status = 0;
i2c_send_flag = 1;
} // i2c_transfer_finished
/***********************************************************************
** Function name: i2c_slave_islasttxbyte
** Description: Determines if a byte will be the last one to be
** transmitted when operating as a slave.
** Parameter: None
** Returned value: return 1 if the byte will be the last one to transmit
** return 0 if the byte will not be the last one to transmit
************************************************************************/
BYTE i2c_slave_islasttxbyte(BYTE bytenum )
{
if( bytenum == (I2C0TxCounter-1) )
return 1;
else
return 0;
} // i2c_slave_islasttxbyte
#ifdef LPC2102_I2C1_MASTER
/*****************************************************************************
** Function name: I2C1_Master_Demo
** Description: This function demonstrates how I2C1 can be used as an I2C
** Master Mode.
** Parameter: None
** Returned value: None
*****************************************************************************/
void I2C1_Master_Demo(void)
{
BYTE i;
/* Initialize I2C1 controller */
I2C1_Init(I2CMASTER);
/* Demonstration of using I2C1 in I2C Master mode - WRITE */
I2C1WriteLength = 4;
I2C1ReadLength = 0;
I2C1MasterBuffer[0] = SLV_ADDRESS | WR_BIT;
I2C1MasterBuffer[1] = 0xa5;
I2C1MasterBuffer[2] = 0x5a;
I2C1MasterBuffer[3] = 0xaa;
I2C1MasterBuffer[4] = 0x55;
I2CCmd = I2C_WRITE;
I2CEngine();
/* Clear buffer */
for(i=0; i<BUFSIZE; i++)
{
I2C1MasterBuffer[i] = 0;
}
/* Demonstration of using I2C1 in I2C Master mode - READ */
I2C1ReadLength = 4;
I2C1WriteLength = 0;
I2C1MasterBuffer[0] = SLV_ADDRESS | RD_BIT;
I2CCmd = I2C_READ;
I2CEngine();
/* Clear buffer */
for(i=0; i<BUFSIZE; i++)
{
I2C1MasterBuffer[i] = 0;
}
/* Demonstration of using I2C1 in I2C Master mode - WRITE + READ */
I2C1WriteLength = 4;
I2C1ReadLength = 4;
I2C1MasterBuffer[0] = SLV_ADDRESS | WR_BIT;
I2C1MasterBuffer[1] = 0x11;
I2C1MasterBuffer[2] = 0x22;
I2C1MasterBuffer[3] = 0x33;
I2C1MasterBuffer[4] = 0x44;
I2C1MasterBuffer[5] = SLV_ADDRESS | RD_BIT;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -