单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2703|回复: 0
收起左侧

LPC11xx读写AT24C04主模式400KHz程序

[复制链接]
huge 发表于 2015-2-18 23:06 | 显示全部楼层 |阅读模式
IIC.c文件:
/*****************************************************************************
*   i2c.c:  I2C C file for NXP LPC11xx Family Microprocessors
*
*   Copyright(C) 2008, NXP Semiconductor
*   All rights reserved.
*
*   History
*   2008.07.19  ver 1.00    Preliminary version, first Release
*
*****************************************************************************/
#include "LPC11xx.h"                        /* LPC11xx Peripheral Registers */
#include "type.h"
#include "i2c.h"
#include "Delay.h"

volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint32_t I2CSlaveState = I2C_IDLE;

volatile uint32_t I2CMode;

volatile uint8_t  I2CMasterBuffer[I2C_BUFSIZE]={0};
volatile uint8_t  I2CSlaveBuffer[I2C_BUFSIZE] ={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;

  /* this handler deals with master read and master write only */
  StatValue = LPC_I2C->STAT;
  switch ( StatValue )
  {
/**************** Master write **********************************/
               
          case 0x08:                        /* A Start condition is issued. */
          WrIndex = 0;
          LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
          LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
          I2CMasterState = I2C_STARTED;
          break;
       
          case 0x10:                        /* A repeated started is issued */
          WrIndex = 0;
          /* Send SLA with R bit set, */
          LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
          LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
          I2CMasterState = I2C_RESTARTED;
          break;
       
          case 0x18:                        /* Regardless, it's a ACK */
          if ( I2CMasterState == I2C_STARTED )
          {
            LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
            I2CMasterState = DATA_ACK;
          }
          LPC_I2C->CONCLR = I2CONCLR_SIC;
          break;
       
          case 0x28:        /* Data byte has been transmitted, regardless ACK or NACK */
          case 0x30:
          if ( WrIndex < I2CWriteLength )
          {   
            LPC_I2C->DAT = I2CMasterBuffer[WrIndex++]; /* this should be the last one */
            I2CMasterState = DATA_ACK;
          }
          else
          {
            if ( I2CReadLength != 0 )
            {
                    LPC_I2C->CONSET = I2CONSET_STA;                 /* Set Repeated-start flag */
                    I2CMasterState = I2C_REPEATED_START;
            }
            else
            {
                    I2CMasterState = DATA_NACK;
                    LPC_I2C->CONSET = I2CONSET_STO;          /* Set Stop flag */
            }
          }
          LPC_I2C->CONCLR = I2CONCLR_SIC;
          break;
               
/**************** Master read *********************************/
               
          case 0x40:        /* Master Receive, SLA_R has been sent */
          LPC_I2C->CONSET = I2CONSET_AA;        /* assert ACK 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 < I2CReadLength )
          {   
            I2CMasterState = DATA_ACK;
          }
          else
          {
            I2CMasterState = DATA_NACK;
          }
          LPC_I2C->CONSET = I2CONSET_AA;        /* assert ACK after data is received */
          LPC_I2C->CONCLR = I2CONCLR_SIC;
          break;
       
          case 0x58:
          I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
          I2CMasterState = DATA_NACK;
          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->CONCLR = I2CONCLR_SIC;
          I2CMasterState = DATA_NACK;
          break;
       
          case 0x38:                /* Arbitration lost, in this example, we don't
                                        deal with multiple master situation */
          default:
          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 )
{
  /* It seems to be bit0 is for I2C, different from
  UM. To be retested along with SSP reset. SSP and I2C
  reset are overlapped, a known bug, for now, both SSP
  and I2C use bit 0 for reset enable. Once the problem
  is fixed, change to "#if 1". */
#if 1
  LPC_SYSCON->PRESETCTRL |= (0x1<<1);
#else
  LPC_SYSCON->PRESETCTRL |= (0x1<<0);
#endif
  //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;                   /*  I2C I/O config */
  LPC_IOCON->PIO0_5 |= 0x01;                         /* I2C SDA */

  /*--- Clear flags ---*/
  LPC_I2C->CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;   

  /*--- Reset registers ---*/
#if FAST_MODE_PLUS
  LPC_IOCON->PIO0_4 |= (0x1<<9);
  LPC_IOCON->PIO0_5 |= (0x1<<9);
  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 = AT24C_ADDR;
  }
       
  NVIC_EnableIRQ(I2C_IRQn);             /* Enable the I2C Interrupt */
  LPC_I2C->CONSET = I2CONSET_I2EN;      /* Enable I2C */
       
  return( TRUE );
}

/*****************************************************************************
**I2C_SendOneByte()启动I2C发送一个数据,Addr为从机地址,Data为将要发送的数据****
*****************************************************************************/
uint32_t I2C_SendOneByte(uint8_t Addr, uint8_t Data)
{
        /* Write SLA(W), address and one data byte */
  I2CWriteLength = 2;
  I2CReadLength  = 0;
  I2CMasterBuffer[0] = Addr;              /* Address Data and Write Bit */
  I2CMasterBuffer[1] = Data;              /* Data 0 */
       
        do                                      /*发送起始条件,直到起始条件成功发送,顺利接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while (1)
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}

/******************************************************************************************************
**I2C_SendOneByte()启动I2C发送多个数据,Addr为从机地址,Num为要发送的数据个数,pdata为数据首字节地址指针**
******************************************************************************************************/
uint32_t I2C_SendNumByte(uint8_t Addr, uint8_t Num, uint8_t *pdata)
{
        uint8_t x=0;
        /* Write SLA(W), address and one data byte */
  I2CWriteLength = Num+1;
  I2CReadLength  = 0;
  I2CMasterBuffer[0] = Addr;                        /* Address Data and Write Bit*/
       
        for(x=0;x<Num;x++)
        {
                I2CMasterBuffer[x+1] = pdata[x];                /* Data */
        }
       
        do                             /*发送起始条件,直到起始条件成功发送,顺利接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while (1)
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}
/*****************************************************************************
****I2C_ReadByte()启动I2C读取多个数据,Addr为从机地址,Num为要发送的数据个数
*****************************************************************************/
uint32_t I2C_ReadByte(uint32_t Num)
{
        I2CWriteLength = 1;
  I2CReadLength  = Num;
        I2CMasterBuffer[0] = AT24C_ADDR|READ_BIT;     /*Address Data and Write Bit*/
       
        do                                            /*发送起始条件,直到起始条件成功发送,接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while ( 1 )
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}

/*****************************************************************************
** 以下为AT24C04驱动程序**
*****************************************************************************/
uint32_t AT24C04_ByteWrite(uint8_t Page,uint8_t WordAddr,uint8_t Data)
{
        /* Write SLA(W), DeviceAddress+Page and one data byte */
  I2CWriteLength = 3;
  I2CReadLength  = 0;
  I2CMasterBuffer[0] = AT24C_ADDR|Page|WRITE_BIT;       /* DeviceAddress Data+Page and Write Bit*/
  I2CMasterBuffer[1] = WordAddr;                        /* Word Address*/
        I2CMasterBuffer[2] = Data;                            /* Data */
       
        do                                                    /*发送起始条件,直到起始条件成功发送,顺利接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while (1)
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}
/************************************************************************************************/
/* the microcontroller can transmit up to seven(1K/2K) or fifteen (4K, 8K, 16K) more data words.*/
/************************************************************************************************/
uint32_t AT24C04_PageWrite(uint8_t Page,uint8_t WordAddr,uint32_t Num,uint8_t *pdata)
{
        uint8_t x=0;
        if(Num>16)
        {
                Num=16;
        }
        /* Write SLA(W), DeviceAddress+Page and one data byte */
  I2CWriteLength = Num+2;
  I2CReadLength  = 0;
  I2CMasterBuffer[0] = AT24C_ADDR|Page|WRITE_BIT;       /* DeviceAddress Data+Page and Write Bit*/
  I2CMasterBuffer[1] = WordAddr;              /* Word Address*/
        for(x=0;x<=Num;x++)
        {
                I2CMasterBuffer[x+2] = pdata[x];          /* Data */
        }
       
        do                                          /*发送起始条件,直到起始条件成功发送,顺利接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while (1)
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}

/*****************************************************************************
**AT24C04_CurrAdrRead(),参数Page为0或者1,以选择所读取的页面*******************
**Word Address保持上次读写操作所用的Word Address地址,并自增1*****************
*****************************************************************************/
uint32_t AT24C04_CurrAdrRead(uint8_t Page)
{
        I2CWriteLength = 1;
  I2CReadLength  = 1;
        I2CMasterBuffer[0] = AT24C_ADDR|Page|READ_BIT;     /*DeviceAddress Data and Write Bit*/
       
        do                                            /*发送起始条件,直到起始条件成功发送,接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while ( 1 )
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}

/*******************************************************************************************
**AT24C04_RandomRead(),参数Page为0或者1,以选择所读取的页面,WordAddr为所选取页面的字节地址**
*******************************************************************************************/
uint32_t AT24C04_RandomRead(uint8_t Page,uint8_t WordAddr)
{
        /* Write SLA(W), address+Page and one data byte */
  I2CWriteLength = 2;
  I2CReadLength  = 1;
  I2CMasterBuffer[0] = AT24C_ADDR|Page|WRITE_BIT;   /* DeviceAddress Data+Page and Write Bit*/
  I2CMasterBuffer[1] = WordAddr;                    /* Word Address*/
       
        do                                                /*发送起始条件,直到起始条件成功发送,顺利接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);                       /* 接管总线后,发送DeviceAddress和WoraAddress */
       
        while (1)
  {
          if ( I2CMasterState == I2C_REPEATED_START )
          {
                        I2CWriteLength = 1;
      I2CMasterBuffer[0] = AT24C_ADDR|Page|READ_BIT;     /* DeviceAddress Data+Page and Write Bit*/
                       
                        while ( 1 )
      {
              if ( I2CMasterState == DATA_NACK )
              {
                I2CStop();
                break;
              }
      }
      return ( TRUE );
          }
  }
}

/*******************************************************************************************
**AT24C04_SequRead(),参数Page为0或者1,以选择所读取的页面,Num为读出的字节个数***************
*******************************************************************************************/
uint32_t AT24C04_SequRead(uint8_t Page,uint32_t Num)
{
        I2CWriteLength = 1;
  I2CReadLength  = Num;
        I2CMasterBuffer[0] = AT24C_ADDR|Page|READ_BIT;     /*DeviceAddress Data and Write Bit*/
       
        do                                            /*发送起始条件,直到起始条件成功发送,接管总线*/
        {
                ;
        }
        while(I2CStart() == FALSE);
       
        while ( 1 )
  {
          if ( I2CMasterState == DATA_NACK )
          {
            I2CStop();
            break;
          }
  }
  return ( TRUE );
}

/******************************************************************************
**                            End Of File
******************************************************************************/


IIC.h文件:
/*****************************************************************************
*   i2c.h:  Header file for NXP LPC Family Microprocessors
*
*   Copyright(C) 2006, NXP Semiconductor
*   All rights reserved.
*
*   History
*   2006.07.19  ver 1.00    Preliminary version, first Release
*
******************************************************************************/
#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               1

#define I2C_BUFSIZE                               6
#define MAX_TIMEOUT                         0x00FFFFFF

#define I2CMASTER                           0x01
#define I2CSLAVE                           0x02

#define I2C_ADDR                     0x80
#define AT24C_ADDR                   0xA0
#define AT24C_Page0                   0x00
#define AT24C_Page1                   0x02

#define WRITE_BIT                           0x00
#define READ_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 I2CONSET_I2EN                       0x00000040  /* I2C Control Set Register */
#define I2CONSET_AA                               0x00000004
#define I2CONSET_SI                               0x00000008
#define I2CONSET_STO                       0x00000010
#define I2CONSET_STA                       0x00000020

#define I2CONCLR_AAC                       0x00000004  /* I2C Control clear Register */
#define I2CONCLR_SIC                       0x00000008
#define I2CONCLR_STAC                       0x00000020
#define I2CONCLR_I2ENC               0x00000040

#define I2DAT_I2C                                 0x00000000  /* I2C Data Reg */
#define I2ADR_I2C                                 0x00000000  /* I2C Slave Address Reg */
#define I2SCLH_SCLH                               0x00000060  /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL                               0x00000060  /* 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 */

void I2C_IRQHandler(void);
uint32_t I2CStart( void );
uint32_t I2CStop( void );
uint32_t I2CInit( uint32_t I2cMode );
uint32_t I2CEngine( void );

uint32_t I2C_SendNumByte(uint8_t Addr, uint8_t Num, uint8_t *pdata);
uint32_t I2C_ReadByte(uint32_t Num);

uint32_t AT24C04_ByteWrite(uint8_t Page,uint8_t WordAddr,uint8_t Data);
uint32_t AT24C04_PageWrite(uint8_t Page,uint8_t WordAddr,uint32_t Num,uint8_t *pdata);
uint32_t AT24C04_CurrAdrRead(uint8_t Page);
uint32_t AT24C04_RandomRead(uint8_t Page,uint8_t WordAddr);
uint32_t AT24C04_SequRead(uint8_t Page,uint32_t Num);



#endif /* end __I2C_H */
/****************************************************************************
**                            End Of File
*****************************************************************************/








回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表