📄 i2c.c
字号:
/****************************************************************************
* $Id:: i2c.c 5865 2010-12-08 21:42:21Z usb00423 $
* Project: NXP LPC17xx I2C example
*
* Description:
* This file contains I2C code example which include I2C initialization,
* I2C interrupt handler, and APIs for I2C access.
*
****************************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
****************************************************************************/
#include "lpc17xx.h"
#include "type.h"
#include "i2c.h"
volatile uint32_t I2CMasterState[I2C_PORT_NUM] = {I2C_IDLE,I2C_IDLE,I2C_IDLE};
volatile uint32_t timeout[I2C_PORT_NUM] = {0, 0, 0};
volatile uint8_t I2CMasterBuffer[I2C_PORT_NUM][BUFSIZE];
volatile uint8_t I2CSlaveBuffer[I2C_PORT_NUM][BUFSIZE];
volatile uint32_t I2CCount[I2C_PORT_NUM] = {0, 0, 0};
volatile uint32_t I2CReadLength[I2C_PORT_NUM];
volatile uint32_t I2CWriteLength[I2C_PORT_NUM];
volatile uint32_t RdIndex0 = 0, RdIndex1 = 0, RdIndex2 = 0;
volatile uint32_t WrIndex0 = 0, WrIndex1 = 0, WrIndex2 = 0;
/*
From device to device, the I2C communication protocol may vary,
in the example below, the protocol uses repeated start to read data from or
write to the device:
For master read: the sequence is: STA,Addr(W),offset,RE-STA,Addr(r),data...STO
for master write: the sequence is: STA,Addr(W),offset,RE-STA,Addr(w),data...STO
Thus, in state 8, the address is always WRITE. in state 10, the address could
be READ or WRITE depending on the I2C command.
*/
/*****************************************************************************
** Function name: I2C_IRQHandler
**
** Descriptions: I2C interrupt handler, deal with master mode only.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void I2C0_IRQHandler(void)
{
uint8_t StatValue;
timeout[0] = 0;
/* this handler deals with master read and master write only */
StatValue = LPC_I2C0->STAT;
switch ( StatValue )
{
case 0x08: /* A Start condition is issued. */
WrIndex0 = 0;
LPC_I2C0->DAT = I2CMasterBuffer[0][WrIndex0++];
LPC_I2C0->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10: /* A repeated started is issued */
RdIndex0 = 0;
/* Send SLA with R bit set, */
LPC_I2C0->DAT = I2CMasterBuffer[0][WrIndex0++];
LPC_I2C0->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18: /* Regardless, it's a ACK */
if ( I2CWriteLength[0] == 1 )
{
LPC_I2C0->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[0] = I2C_NO_DATA;
}
else
{
LPC_I2C0->DAT = I2CMasterBuffer[0][WrIndex0++];
}
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
if ( WrIndex0 < I2CWriteLength[0] )
{
LPC_I2C0->DAT = I2CMasterBuffer[0][WrIndex0++]; /* this should be the last one */
}
else
{
if ( I2CReadLength[0] != 0 )
{
LPC_I2C0->CONSET = I2CONSET_STA; /* Set Repeated-start flag */
}
else
{
LPC_I2C0->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[0] = I2C_OK;
}
}
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x30:
LPC_I2C0->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[0] = I2C_NACK_ON_DATA;
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x40: /* Master Receive, SLA_R has been sent */
if ( (RdIndex0 + 1) < I2CReadLength[0] )
{
/* Will go to State 0x50 */
LPC_I2C0->CONSET = I2CONSET_AA; /* assert ACK after data is received */
}
else
{
/* Will go to State 0x58 */
LPC_I2C0->CONCLR = I2CONCLR_AAC; /* assert NACK after data is received */
}
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x50: /* Data byte has been received, regardless following ACK or NACK */
I2CSlaveBuffer[0][RdIndex0++] = LPC_I2C0->DAT;
if ( (RdIndex0 + 1) < I2CReadLength[0] )
{
LPC_I2C0->CONSET = I2CONSET_AA; /* assert ACK after data is received */
}
else
{
LPC_I2C0->CONCLR = I2CONCLR_AAC; /* assert NACK on last byte */
}
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x58:
I2CSlaveBuffer[0][RdIndex0++] = LPC_I2C0->DAT;
I2CMasterState[0] = I2C_OK;
LPC_I2C0->CONSET = I2CONSET_STO; /* Set Stop flag */
LPC_I2C0->CONCLR = I2CONCLR_SIC; /* Clear SI flag */
break;
case 0x20: /* regardless, it's a NACK */
case 0x48:
LPC_I2C0->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[0] = I2C_NACK_ON_ADDRESS;
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
case 0x38: /* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I2CMasterState[0] = I2C_ARBITRATION_LOST;
LPC_I2C0->CONCLR = I2CONCLR_SIC;
break;
}
return;
}
/*****************************************************************************
** Function name: I2C_IRQHandler
**
** Descriptions: I2C interrupt handler, deal with master mode only.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void I2C1_IRQHandler(void)
{
uint8_t StatValue;
timeout[1] = 0;
/* this handler deals with master read and master write only */
StatValue = LPC_I2C1->STAT;
switch ( StatValue )
{
case 0x08: /* A Start condition is issued. */
WrIndex1 = 0;
LPC_I2C1->DAT = I2CMasterBuffer[1][WrIndex1++];
LPC_I2C1->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10: /* A repeated started is issued */
RdIndex1 = 0;
/* Send SLA with R bit set, */
LPC_I2C1->DAT = I2CMasterBuffer[1][WrIndex1++];
LPC_I2C1->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18: /* Regardless, it's a ACK */
if ( I2CWriteLength[1] == 1 )
{
LPC_I2C1->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[1] = I2C_NO_DATA;
}
else
{
LPC_I2C1->DAT = I2CMasterBuffer[1][WrIndex1++];
}
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x28: /* Data byte has been transmitted, regardless ACK or NACK */
if ( WrIndex1 < I2CWriteLength[1] )
{
LPC_I2C1->DAT = I2CMasterBuffer[1][WrIndex1++]; /* this should be the last one */
}
else
{
if ( I2CReadLength[1] != 0 )
{
LPC_I2C1->CONSET = I2CONSET_STA; /* Set Repeated-start flag */
}
else
{
LPC_I2C1->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[1] = I2C_OK;
}
}
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x30:
LPC_I2C1->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[1] = I2C_NACK_ON_DATA;
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x40: /* Master Receive, SLA_R has been sent */
if ( (RdIndex1 + 1) < I2CReadLength[1] )
{
/* Will go to State 0x50 */
LPC_I2C1->CONSET = I2CONSET_AA; /* assert ACK after data is received */
}
else
{
/* Will go to State 0x58 */
LPC_I2C1->CONCLR = I2CONCLR_AAC; /* assert NACK after data is received */
}
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x50: /* Data byte has been received, regardless following ACK or NACK */
I2CSlaveBuffer[1][RdIndex1++] = LPC_I2C1->DAT;
if ( (RdIndex1 + 1) < I2CReadLength[1] )
{
LPC_I2C1->CONSET = I2CONSET_AA; /* assert ACK after data is received */
}
else
{
LPC_I2C1->CONCLR = I2CONCLR_AAC; /* assert NACK on last byte */
}
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x58:
I2CSlaveBuffer[1][RdIndex1++] = LPC_I2C1->DAT;
I2CMasterState[1] = I2C_OK;
LPC_I2C1->CONSET = I2CONSET_STO; /* Set Stop flag */
LPC_I2C1->CONCLR = I2CONCLR_SIC; /* Clear SI flag */
break;
case 0x20: /* regardless, it's a NACK */
case 0x48:
LPC_I2C1->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState[1] = I2C_NACK_ON_ADDRESS;
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
case 0x38: /* Arbitration lost, in this example, we don't
deal with multiple master situation */
default:
I2CMasterState[1] = I2C_ARBITRATION_LOST;
LPC_I2C1->CONCLR = I2CONCLR_SIC;
break;
}
return;
}
/*****************************************************************************
** Function name: I2C_IRQHandler
**
** Descriptions: I2C interrupt handler, deal with master mode only.
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void I2C2_IRQHandler(void)
{
uint8_t StatValue;
timeout[2] = 0;
/* this handler deals with master read and master write only */
StatValue = LPC_I2C2->STAT;
switch ( StatValue )
{
case 0x08: /* A Start condition is issued. */
WrIndex2 = 0;
LPC_I2C2->DAT = I2CMasterBuffer[2][WrIndex2++];
LPC_I2C2->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10: /* A repeated started is issued */
RdIndex2 = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -