Interfacing RTC1307 with I2C & LPC1317-64P

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Interfacing RTC1307 with I2C & LPC1317-64P

316 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by aamir ali on Mon Feb 18 23:59:23 MST 2013
I have used library code for I@c & used for communicating with DS1307.
I don't know sometimes data from RTC is wrong. Can someone check where is problem

However I wrote                               {10,10,01,02,26,11,12}
Like sometimes data read from slave buffer is {00,10,10,01,02,06,11}
Sometimes I read correct values

I2CSlaveBuffer

main.c

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;
extern volatile uint32_t I2CMasterState;

int main (void) 
{
    SystemCoreClockUpdate(); 
    I2CWriteLength = 9;                   // 9 bytes to write, 1 RTC address, 1 - address where to write, 7 bytes to write
    I2CReadLength = 0;
    I2CMasterBuffer[0] = RTC_ADDR;         //0xd0
    I2CMasterBuffer[1] = 0x00;          //address
    I2CMasterBuffer[2] = 0x10;       //sec
    I2CMasterBuffer[3] = 0x10;           //min
    I2CMasterBuffer[4] = 0x01;         //hr
    I2CMasterBuffer[5] = 0x02;         //day
    I2CMasterBuffer[6] = 0x26;        //date
    I2CMasterBuffer[7] = 0x11;          //month
    I2CMasterBuffer[8] = 0x12;             //year
    
    I2CInit(0);                // Initialize I2c
    I2CEngine( );         // write the 9 bytes first
    
    while(1)
    {                                              // Now read
        I2CWriteLength = 2;                            // to bytes to write, RTC address, & address from where to read       
        I2CReadLength = 7;                     // no of bytes to read
        I2CMasterBuffer[0] = RTC_ADDR;
        I2CMasterBuffer[1] = 0x00;   
        I2CMasterBuffer[2] = RTC_ADDR | 0x01;        
        I2CEngine( );
    }
}



i2c.c

#include "LPC13Uxx.h"                        /* LPC13xx definitions */
#include "i2c.h"

volatile uint32_t timeout = 0;

volatile uint32_t I2CMode;

volatile uint32_t I2CMasterState = I2C_IDLE;
volatile uint8_t I2CMasterBuffer[BUFSIZE];
volatile uint8_t I2CSlaveBuffer[BUFSIZE];
volatile uint32_t I2CReadLength;
volatile uint32_t I2CWriteLength;

volatile uint32_t RdIndex = 0;
volatile uint32_t WrIndex = 0;

/*****************************************************************************
** 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;
                  RdIndex = 0;
                  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];
                  LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
                  break;

        case 0x10:/* A repeated started is issued */
                  RdIndex = 0;
                  LPC_I2C->DAT = I2CMasterBuffer[WrIndex++];        /* Send SLA with R bit set, */
                  LPC_I2C->CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
                  break;

        case 0x18:
                  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 */
                    //  I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
                    LPC_I2C->CONSET = I2CONSET_AA;/* assert ACK after data is received */
                  }
                  else
                  {
                        /* Will go to State 0x58 */
                   //   I2CSlaveBuffer[RdIndex++] = LPC_I2C->DAT;
                    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: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 */


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


    LPC_I2C->SCLL   = I2SCLL_SCLL;
    LPC_I2C->SCLH   = I2SCLH_SCLH;   

    /* 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;
  
  if( I2CMasterState != I2C_OK)
  {
        while(1);
  }    
  
    return 0;
}
0 Kudos
1 Reply

221 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by aamir ali on Tue Feb 19 00:13:58 MST 2013
I had copied library code from LPC1343.

Also i2c.h

#define BUFSIZE             15

#define MAX_TIMEOUT         0x0FFF

#define I2CMASTER           0x01

#define RTC_ADDR            0xd0
 
#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 I2SCLH_SCLH         400  /* I2C SCL Duty Cycle High Reg */
#define I2SCLL_SCLL         400  /* I2C SCL Duty Cycle Low Reg */


#define TRUE   1
#define FALSE  0

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 );
0 Kudos