lpcware

Interfacing RTC1307 with I2C & LPC1317-64P

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
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;
}

Outcomes