標(biāo)題:
NXP LPC11xx I2C 驅(qū)動(dòng)程序
[打印本頁(yè)]
作者:
huge
時(shí)間:
2015-2-18 23:09
標(biāo)題:
NXP LPC11xx I2C 驅(qū)動(dòng)程序
本帖最后由 huge 于 2015-2-18 23:11 編輯
/****************************************************************************
* $Id:: i2c.c 3662 2010-06-03 19:47:02Z usb00423 $
* Project: NXP LPC11xx 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 "LPC11xx.h" /* LPC11xx Peripheral Registers */
#include "type.h"
#include "i2c.h"
volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint32_t I2CSlaveState = I2C_IDLE;
volatile uint32_t timeout = 0;
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;
/*
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 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;
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x10: /* A repeated started is issued */
RdIndex = 0;
/* Send SLA with R bit set, */
LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
break;
case 0x18: /* Regardless, it's a ACK */
if ( I2CWriteLength == 1 )
{
LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
I2CMasterState = I2C_NO_DATA;
}
else
{
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 */
LPC_I2C->CONSET = I2CONSET_AA; /* assert ACK after data is received */
}
else
{
/* Will go to State 0x58 */
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: 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
**
*****************************************************************************/
uint32_t I2CStart( void )
{
uint32_t timeout = 0;
uint32_t retVal = FALSE;
/*--- Issue a start condition ---*/
LPC_I2C->CONSET = 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
**
*****************************************************************************/
uint32_t I2CStop( void )
{
LPC_I2C->CONSET = I2CONSET_STO; /* Set Stop flag */
LPC_I2C->CONCLR = I2CONCLR_SIC; /* Clear SI flag */
/*--- Wait for STOP detected ---*/
while( LPC_I2C->CONSET & 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
**
*****************************************************************************/
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 */
/* IOCON may change in the next release, save change for future references. */
// LPC_IOCON->PIO0_4 |= (0x1<<10); /* open drain pins */
// LPC_IOCON->PIO0_5 |= (0x1<<10); /* open drain pins */
/*--- Clear flags ---*/
LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
/*--- Reset registers ---*/
#if FAST_MODE_PLUS
LPC_IOCON->PIO0_4 |= (0x2<<8);
LPC_IOCON->PIO0_5 |= (0x2<<8);
LPC_I2C->SCLL = I2SCLL_HS_SCLL;
LPC_I2C->SCLH = I2SCLH_HS_SCLH;
#else
LPC_I2C->SCLL = I2SCLL_SCLL;
LPC_I2C->SCLH = I2SCLH_SCLH;
#endif
if ( I2cMode == I2CSLAVE )
{
LPC_I2C->ADR0 = PCF8594_ADDR;
}
/* 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;
return ( I2CMasterState );
}
/******************************************************************************
** End Of File
******************************************************************************/
/****************************************************************************
* $Id:: i2c.h 3662 2010-06-03 19:47:02Z usb00423 $
* Project: NXP LPC11xx I2C example
*
* Description:
* This file contains I2C code header definition.
*
****************************************************************************
* 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.
****************************************************************************/
#ifndef __I2C_H
#define __I2C_H
/* If I2C SEEPROM is tested, make sure FAST_MODE_PLUS is 0.
For board to board test, this flag can be turned on. */
#define FAST_MODE_PLUS 0
#define BUFSIZE 64
#define MAX_TIMEOUT 0x00FFFFFF
#define I2CMASTER 0x01
#define I2CSLAVE 0x02
#define PCF8594_ADDR 0xA0
#define READ_WRITE 0x01
#define RD_BIT 0x01
#define I2C_IDLE 0
#define I2C_STARTED 1
#define I2C_RESTARTED 2
#define I2C_REPEATED_START 3
#define DATA_ACK 4
#define DATA_NACK 5
#define I2C_BUSY 6
#define I2C_NO_DATA 7
#define I2C_NACK_ON_ADDRESS 8
#define I2C_NACK_ON_DATA 9
#define I2C_ARBITRATION_LOST 10
#define I2C_TIME_OUT 11
#define I2C_OK 12
#define I2CONSET_I2EN (0x1<<6) /* I2C Control Set Register */
#define I2CONSET_AA (0x1<<2)
#define I2CONSET_SI (0x1<<3)
#define I2CONSET_STO (0x1<<4)
#define I2CONSET_STA (0x1<<5)
#define I2CONCLR_AAC (0x1<<2) /* I2C Control clear Register */
#define I2CONCLR_SIC (0x1<<3)
#define I2CONCLR_STAC (0x1<<5)
#define I2CONCLR_I2ENC (0x1<<6)
#define I2DAT_I2C 0x00000000 /* I2C Data Reg */
#define I2ADR_I2C 0x00000000 /* I2C Slave Address Reg */
#define I2SCLH_SCLH 0x00000180 /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL 0x00000180 /* I2C SCL Duty Cycle Low Reg */
#define I2SCLH_HS_SCLH 0x00000015 /* Fast Plus I2C SCL Duty Cycle High Reg */
#define I2SCLL_HS_SCLL 0x00000015 /* Fast Plus I2C SCL Duty Cycle Low Reg */
extern void I2C_IRQHandler( void );
extern uint32_t I2CInit( uint32_t I2cMode );
extern uint32_t I2CStart( void );
extern uint32_t I2CStop( void );
extern uint32_t I2CEngine( void );
#endif /* end __I2C_H */
/****************************************************************************
** End Of File
*****************************************************************************/
/****************************************************************************
* $Id:: i2ctest.c 3662 2010-06-03 19:47:02Z usb00423 $
* Project: NXP LPC11xx I2C example
*
* Description:
* This file contains I2C test modules, main entry, to test I2C APIs.
*
****************************************************************************
* 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 "LPC11xx.h" /* LPC11xx Peripheral Registers */
#include "type.h"
#include "i2c.h"
extern volatile uint32_t I2CCount;
extern volatile uint8_t I2CMasterBuffer[BUFSIZE];
extern volatile uint8_t I2CSlaveBuffer[BUFSIZE];
extern volatile uint32_t I2CMasterState;
extern volatile uint32_t I2CReadLength, I2CWriteLength;
/*******************************************************************************
** Main Function main()
*******************************************************************************/
int main (void)
{
uint32_t i;
SystemInit();
if ( I2CInit( (uint32_t)I2CMASTER ) == FALSE ) /* initialize I2c */
{
while ( 1 ); /* Fatal error */
}
/* In order to start the I2CEngine, the all the parameters
must be set in advance, including I2CWriteLength, I2CReadLength,
I2CCmd, and the I2cMasterBuffer which contains the stream
command/data to the I2c slave device.
(1) If it's a I2C write only, the number of bytes to be written is
I2CWriteLength, I2CReadLength is zero, the content will be filled
in the I2CMasterBuffer.
(2) If it's a I2C read only, the number of bytes to be read is
I2CReadLength, I2CWriteLength is 0, the read value will be filled
in the I2CMasterBuffer.
(3) If it's a I2C Write/Read with repeated start, specify the
I2CWriteLength, fill the content of bytes to be written in
I2CMasterBuffer, specify the I2CReadLength, after the repeated
start and the device address with RD bit set, the content of the
reading will be filled in I2CMasterBuffer index at
I2CMasterBuffer[I2CWriteLength+2].
e.g. Start, DevAddr(W), WRByte1...WRByteN, Repeated-Start, DevAddr(R),
RDByte1...RDByteN Stop. The content of the reading will be filled
after (I2CWriteLength + two devaddr) bytes. */
/* Write SLA(W), address and one data byte */
I2CWriteLength = 6;
I2CReadLength = 0;
I2CMasterBuffer[0] = PCF8594_ADDR;
I2CMasterBuffer[1] = 0x00; /* address */
I2CMasterBuffer[2] = 0x55; /* Data0 */
I2CMasterBuffer[3] = 0xAA; /* Data1 */
I2CMasterBuffer[4] = 0x12; /* Data0 */
I2CMasterBuffer[5] = 0x34; /* Data1 */
I2CEngine();
/* Be careful with below fixed delay. From device to device, or
even same device with different write length, or various I2C clock,
below delay length may need to be changed accordingly. Having
a break point before Write/Read start will be helpful to isolate
the problem. */
for ( i = 0; i < 0x200000; i++ ); /* Delay after write */
for ( i = 0; i < BUFSIZE; i++ )
{
I2CSlaveBuffer[i] = 0x00;
}
/* Write SLA(W), address, SLA(R), and read one byte back. */
I2CWriteLength = 2;
I2CReadLength = 4;
I2CMasterBuffer[0] = PCF8594_ADDR;
I2CMasterBuffer[1] = 0x00; /* address */
I2CMasterBuffer[2] = PCF8594_ADDR | RD_BIT;
I2CEngine();
/* Check the content of the Master and slave buffer */
while ( 1 );
return 0;
}
/******************************************************************************
** End Of File
******************************************************************************/
復(fù)制代碼
作者:
wjh96888
時(shí)間:
2015-4-1 16:57
您好,NXP的單片機(jī)用的多嗎,謝謝
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1