|
本帖最后由 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ù)制代碼
|
|