📄 i2c.c
字号:
/*****************************************************************************
* i2c.c: I2C C file for NXP LPC23xx/24xx Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2006.07.19 ver 1.00 Prelimnary version, first Release
*
*****************************************************************************/
#include "LPC23xx.h" /* LPC23xx/24xx definitions */
#include "type.h"
#include "irq.h"
#include "i2c.h"
#include "stdio.h"
#include "uart.h"
#define BUFFER_SIZE 0x40
extern char RUN_INFOR[BUFFER_SIZE];
volatile DWORD I2CMasterState = I2C_IDLE;
volatile DWORD I2CSlaveState = I2C_IDLE;
volatile DWORD I2CCmd;
volatile DWORD I2CMode;
volatile BYTE I2CMasterBuffer[BUFSIZE];
volatile BYTE I2CSlaveBuffer[BUFSIZE];
volatile DWORD I2CCount = 0;
volatile DWORD I2CReadLength;
volatile DWORD I2CWriteLength;
volatile DWORD RdIndex = 0;
volatile DWORD WrIndex = 0;
volatile char Status[0x20];
volatile char StatusIndex=0;
/*
From device to device, the I2C communication protocol may vary,
*/
/*****************************************************************************
** Function name: I2C0MasterHandler
**
** Descriptions: I2C0 interrupt handler, deal with master mode
** only.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void I2C2MasterHandler(void) __irq
{
BYTE StatValue;
/* this handler deals with master read and master write only */
StatValue = I22STAT;
IENABLE; /* handles nested interrupt */
Status[ StatusIndex++ ] = StatValue;
switch ( StatValue )
{
case 0x08: /* A Start condition is issued. */
I22DAT = I2CMasterBuffer[0];
I22CONSET = I2CONSET_AA;
I22CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
I2CMasterState = I2C_STARTED;
break;
case 0x10: /* A repeated started is issued */
if ( I2CCmd == AT24C16_READ )
{
I22DAT = I2CMasterBuffer[2];
}
I22CONSET = I2CONSET_AA;
I22CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
I2CMasterState = I2C_RESTARTED;
break;
case 0x18: /* Regardless, it's a ACK */
if ( I2CMasterState == I2C_STARTED )
{
I22DAT = I2CMasterBuffer[1+WrIndex];
WrIndex++;
I2CMasterState = DATA_ACK;
}
I22CONCLR = I2CONCLR_SIC;
break;
case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
case 0x30:
if ( WrIndex != I2CWriteLength )
{
I22DAT = I2CMasterBuffer[1+WrIndex];
WrIndex++;
if ( WrIndex != I2CWriteLength )
{
I2CMasterState = DATA_ACK;
}
else
{
if ( I2CReadLength != 0 )
{
I22CONSET = I2CONSET_STA; /* Set Repeated-start flag */
I2CMasterState = I2C_REPEATED_START;
}
else
{
I2CMasterState = DATA_NACK;
I22CONCLR = I2CONCLR_AAC;
}
}
}
else
{
if ( I2CReadLength != 0 )
{
I22CONSET = I2CONSET_STA; /* Set Repeated-start flag */
I2CMasterState = I2C_REPEATED_START;
}
else
{
I2CMasterState = DATA_NACK;
I22CONCLR = I2CONCLR_AAC;
}
}
I22CONCLR = I2CONCLR_SIC;
break;
case 0x40: /* Master Receive, SLA_R has been sent */
I22CONCLR = I2CONCLR_SIC;
break;
case 0x50: /* Data byte has been received, regardless following ACK or NACK */
case 0x58:
I2CMasterBuffer[3+RdIndex] = I22DAT;
RdIndex++;
if ( RdIndex != I2CReadLength )
{
I2CMasterState = DATA_ACK;
}
else
{
RdIndex = 0;
I2CMasterState = DATA_NACK;
I22CONCLR = I2CONCLR_AAC;
}
I22CONCLR = I2CONCLR_SIC;
break;
case 0x20: /* regardless, it's a NACK */
case 0x48:
I22CONCLR = I2CONCLR_SIC;
I2CMasterState = DATA_NACK;
break;
case 0x38: /* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I22CONCLR = I2CONCLR_SIC;
break;
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
}
/*****************************************************************************
** Function name: I2CStart
**
** Descriptions: Create I2C start condition, a timeout
** value is set if the I2C never gets started,
** and timed out. It's a fatal error.
**
** parameters: None
** Returned value: true or false, return false if timed out
**
*****************************************************************************/
DWORD I2CStart( void )
{
DWORD timeout = 0;
DWORD retVal = FALSE;
/*--- Issue a start condition ---*/
I22CONSET = I2CONSET_STA; /* Set Start flag */
/*--- Wait until START transmitted ---*/
while( 1 )
{
if ( I2CMasterState == I2C_STARTED )
{
retVal = TRUE;
break;
}
if ( timeout >= MAX_TIMEOUT )
{
retVal = FALSE;
break;
}
timeout++;
}
return( retVal );
}
/*****************************************************************************
** Function name: I2CStop
**
** Descriptions: Set the I2C stop condition, if the routine
** never exit, it's a fatal bus error.
**
** parameters: None
** Returned value: true or never return
**
*****************************************************************************/
DWORD I2CStop( void )
{
I22CONSET = I2CONSET_STO | I2CONSET_AA; /* Set Stop flag */
I22CONCLR = I2CONCLR_SIC; /* Clear SI flag */
/*--- Wait for STOP detected ---*/
while( I22CONSET & I2CONSET_STO );
return TRUE;
}
/*****************************************************************************
** 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
**
*****************************************************************************/
DWORD I2CInit( DWORD I2cMode )
{
PCONP |= (1 << 19);
PINSEL0 |= 0x00A00000; //选择引脚 I2C2
/*--- Clear flags ---*/
I22CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
/*--- Reset registers ---*/
I22SCLL = I2SCLL_SCLL;
I22SCLH = I2SCLH_SCLH;
if ( I2cMode == I2CSLAVE )
{
//I22ADR = SLAVE_ADDR;
}
/* Install interrupt handler */
if ( install_irq( I2C2_INT, (void *)I2C2MasterHandler, HIGHEST_PRIORITY ) == FALSE )
{
return( FALSE );
}
I22CONSET = 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.
**
*****************************************************************************/
DWORD I2CEngine( void )
{
char i;
I2CMasterState = I2C_IDLE;
RdIndex = 0;
WrIndex = 0;
StatusIndex=0;
for( i=0; i<0x20; i++)
{
Status[ i ] = 0;
}
if ( I2CStart() != TRUE )
{
sprintf( RUN_INFOR, "I2CStart Failed.\r\n" );
UARTSend( 0, (BYTE *)RUN_INFOR, BUFFER_SIZE );
I2CStop();
return ( FALSE );
}
while ( 1 )
{
if ( I2CMasterState == DATA_NACK )
{
I2CStop();
break;
}
}
for( i=0; i<StatusIndex; i++)
{
sprintf( RUN_INFOR, "Status[%d]=%XH.\r\n" , i , Status[ i ] );
UARTSend( 0, (BYTE *)RUN_INFOR, BUFFER_SIZE );
}
return ( TRUE );
}
/******************************************************************************
** End Of File
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -