This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LPC1768 + AT24C08 - Timeout problem

Hello, I am using a AT24C08 for store some datas and I'm having trouble. I am using code sample for I2C. The data is being written and read perfectly, but the function I2CStart() return always "timeout". This "problem" causes a delay in my routines of W/R. I believe it is necessary some modification in I2C0_IRQHandler() function. Someone could review my code?

I implemented a matricial keypad for tests of write and read.

Parents
  • main.c

    int main (void)
    {
            char temp[16];
            unsigned char c = 0;
            unsigned int i = 0;
    
            SystemInit();
            SysTick_Config(SystemFrequency/100);  /* Generate interrupt each 10 ms      */
    
            if ( I2CInit( (uint32_t)I2CMASTER ) == FALSE )  /* initialize I2c */
            {
                    while ( 1 );                            /* Fatal error */
            }
    
            /* Initialize RTC with RTCCAL and RTCDIR values */
            InitRTC();
            /* start RTC */
            StartRTC();
    
            init_KEYPAD();
            lcd_clear();
    
            while(1)
            {
                    c = get_KEYPAD();
                    if(c == '1')
                    {
                            for ( i = 0; i < BUFSIZE; i++ )      /* clear buffer */
                            {
                                    I2CMasterBuffer[i] = 0;
                            }
    
                            I2CWriteLength = 5;
                            I2CReadLength = 0;
                            I2CMasterBuffer[0] = AT24C08_ADDR;
                            I2CMasterBuffer[1] = 0x00;              /* address offset for user seq. */
    
                            I2CMasterBuffer[2] = LPC_RTC->HOUR;
                            I2CMasterBuffer[3] = LPC_RTC->MIN;
                            I2CMasterBuffer[4] = LPC_RTC->SEC;
                            I2CEngine();
                    }
                    if(c == '2')
                    {
                            for ( i = 0; i < BUFSIZE; i++ )
                            {
                                    I2CSlaveBuffer[i] = 0x00;
                            }
                            /* Write SLA(W), address, SLA(R), and read one byte back. */
                            I2CWriteLength = 2;
                            I2CReadLength = 20;
                            I2CMasterBuffer[0] = AT24C08_ADDR;
                            I2CMasterBuffer[1] = 0x00;              /* address */
                            I2CMasterBuffer[2] = AT24C08_ADDR | RD_BIT;
                            I2CEngine();
    
                    }
                    lcd_gotoxy(0,0);
                    sprintf(temp,"%d:%d:%d",I2CSlaveBuffer[0],I2CSlaveBuffer[1],I2CSlaveBuffer[2]);
                    lcd_print(temp);
            }
    
            return 0;
    

Reply
  • main.c

    int main (void)
    {
            char temp[16];
            unsigned char c = 0;
            unsigned int i = 0;
    
            SystemInit();
            SysTick_Config(SystemFrequency/100);  /* Generate interrupt each 10 ms      */
    
            if ( I2CInit( (uint32_t)I2CMASTER ) == FALSE )  /* initialize I2c */
            {
                    while ( 1 );                            /* Fatal error */
            }
    
            /* Initialize RTC with RTCCAL and RTCDIR values */
            InitRTC();
            /* start RTC */
            StartRTC();
    
            init_KEYPAD();
            lcd_clear();
    
            while(1)
            {
                    c = get_KEYPAD();
                    if(c == '1')
                    {
                            for ( i = 0; i < BUFSIZE; i++ )      /* clear buffer */
                            {
                                    I2CMasterBuffer[i] = 0;
                            }
    
                            I2CWriteLength = 5;
                            I2CReadLength = 0;
                            I2CMasterBuffer[0] = AT24C08_ADDR;
                            I2CMasterBuffer[1] = 0x00;              /* address offset for user seq. */
    
                            I2CMasterBuffer[2] = LPC_RTC->HOUR;
                            I2CMasterBuffer[3] = LPC_RTC->MIN;
                            I2CMasterBuffer[4] = LPC_RTC->SEC;
                            I2CEngine();
                    }
                    if(c == '2')
                    {
                            for ( i = 0; i < BUFSIZE; i++ )
                            {
                                    I2CSlaveBuffer[i] = 0x00;
                            }
                            /* Write SLA(W), address, SLA(R), and read one byte back. */
                            I2CWriteLength = 2;
                            I2CReadLength = 20;
                            I2CMasterBuffer[0] = AT24C08_ADDR;
                            I2CMasterBuffer[1] = 0x00;              /* address */
                            I2CMasterBuffer[2] = AT24C08_ADDR | RD_BIT;
                            I2CEngine();
    
                    }
                    lcd_gotoxy(0,0);
                    sprintf(temp,"%d:%d:%d",I2CSlaveBuffer[0],I2CSlaveBuffer[1],I2CSlaveBuffer[2]);
                    lcd_print(temp);
            }
    
            return 0;
    

Children
  • i2c.c

    #include "lpc17xx.h"
    #include "type.h"
    #include "i2c.h"
    #include "lcd.h"
    
    volatile uint32_t I2CMasterState = I2C_IDLE;
    volatile uint32_t I2CSlaveState = I2C_IDLE;
    
    volatile uint32_t I2CCmd;
    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;
    
    
    void I2C0_IRQHandler(void)
    {
      uint8_t StatValue;
    
      /* this handler deals with master read and master write only */
      StatValue = LPC_I2C0->I2STAT;
    
            switch ( StatValue )
      {
            case 0x08:                      /* A Start condition is issued. */
            WrIndex = 0;
            LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
            LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
            break;
    
            case 0x10:                      /* A repeated started is issued */
            RdIndex = 0;
            /* Send SLA with R bit set, */
            LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
            LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
            break;
    
            case 0x18:                      /* Regardless, it's a ACK */
            if ( I2CWriteLength == 1 )
            {
              LPC_I2C0->I2CONSET = I2CONSET_STO;      /* Set Stop flag */
              I2CMasterState = I2C_NO_DATA;
            }
            else
            {
              LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++];
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x28:      /* Data byte has been transmitted, regardless ACK or NACK */
            if ( WrIndex < I2CWriteLength )
            {
              LPC_I2C0->I2DAT = I2CMasterBuffer[WrIndex++]; /* this should be the last one */
            }
            else
            {
              if ( I2CReadLength != 0 )
              {
                    LPC_I2C0->I2CONSET = I2CONSET_STA;   /* Set Repeated-start flag */
              }
              else
              {
                    LPC_I2C0->I2CONSET = I2CONSET_STO;      /* Set Stop flag */
                    I2CMasterState = I2C_OK;
              }
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x30:
            LPC_I2C0->I2CONSET = I2CONSET_STO;      /* Set Stop flag */
            I2CMasterState = I2C_NACK_ON_DATA;
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x40:      /* Master Receive, SLA_R has been sent */
            if ( (RdIndex + 1) < I2CReadLength )
            {
              /* Will go to State 0x50 */
              LPC_I2C0->I2CONSET = I2CONSET_AA;  /* assert ACK after data is received */
            }
            else
            {
              /* Will go to State 0x58 */
              LPC_I2C0->I2CONCLR = I2CONCLR_AAC; /* assert NACK after data is received */
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x50:      /* Data byte has been received, regardless following ACK or NACK */
            I2CSlaveBuffer[RdIndex++] = LPC_I2C0->I2DAT;
            if ( (RdIndex + 1) < I2CReadLength )
            {
              LPC_I2C0->I2CONSET = I2CONSET_AA;  /* assert ACK after data is received */
            }
            else
            {
              LPC_I2C0->I2CONCLR = I2CONCLR_AAC; /* assert NACK on last byte */
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x58:
            I2CSlaveBuffer[RdIndex++] = LPC_I2C0->I2DAT;
            I2CMasterState = I2C_OK;
            LPC_I2C0->I2CONSET = I2CONSET_STO;   /* Set Stop flag */
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;   /* Clear SI flag */
            break;
    
            case 0x20:              /* regardless, it's a NACK */
            case 0x48:
            LPC_I2C0->I2CONSET = I2CONSET_STO;      /* Set Stop flag */
            I2CMasterState = I2C_NACK_ON_ADDRESS;
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x38:              /* Arbitration lost, in this example, we don't
                                            deal with multiple master situation */
            default:
            I2CMasterState = I2C_ARBITRATION_LOST;
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
      }
    }
    
    uint32_t I2CStart( void )
    {
      uint32_t timeout = 0;
      uint32_t retVal = FALSE;
    
      /*--- Issue a start condition ---*/
      LPC_I2C0->I2CONSET = I2CONSET_STA; /* Set Start flag */
    
    
    
      /*--- Wait until START transmitted ---*/
      while( 1 )
      {
            if ( I2CMasterState == I2C_STARTED )
            {
              retVal = TRUE;
              break;
            }
            if ( timeout >= MAX_TIMEOUT )
            {
                    lcd_gotoxy(1,0);
                    lcd_print("MAX_TIMEOUT");
              retVal = FALSE;
              break;
            }
            timeout++;
      }
      return( retVal );
    }
    
    
    uint32_t I2CStop( void )
    {
      LPC_I2C0->I2CONSET = I2CONSET_STO;  /* Set Stop flag */
      LPC_I2C0->I2CONCLR = I2CONCLR_SIC;  /* Clear SI flag */
    
      /*--- Wait for STOP detected ---*/
      while( LPC_I2C0->I2CONSET & I2CONSET_STO );
      return TRUE;
    }
    
    
    uint32_t I2CInit( uint32_t I2cMode )
    {
      LPC_SC->PCONP |= (1 << 7);
    
      /* set PIO0.27 and PIO0.28 to I2C0 SDA and SCL */
      /* function to 01 on both SDA and SCL. */
      LPC_PINCON->PINSEL1 &= ~((0x03<<22)|(0x03<<24));
      LPC_PINCON->PINSEL1 |= ((0x01<<22)|(0x01<<24));
    
      /*--- Clear flags ---*/
      LPC_I2C0->I2CONCLR = I2CONCLR_AAC | I2CONCLR_SIC | I2CONCLR_STAC | I2CONCLR_I2ENC;
    
      LPC_PINCON->I2CPADCFG &= ~((0x1<<0)|(0x1<<2));
      LPC_I2C0->I2SCLL   = I2SCLL_SCLL;
      LPC_I2C0->I2SCLH   = I2SCLH_SCLH;
    
      /* Install interrupt handler */
      NVIC_EnableIRQ(I2C0_IRQn);
    
      LPC_I2C0->I2CONSET = I2CONSET_I2EN;
      return( TRUE );
    }
    
    
    uint32_t I2CEngine( void )
    {
      I2CMasterState = I2C_IDLE;
      RdIndex = 0;
      WrIndex = 0;
      lcd_clear();
      if ( I2CStart() != TRUE )
      {
            I2CStop();
            return ( FALSE );
      }
    
      while ( 1 )
      {
            if ( I2CMasterState == DATA_NACK )
            {
              I2CStop();
              break;
            }
      }
    
      return ( TRUE );
    }
    

  • i2c.h

    #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                     0x00000080  /* I2C SCL Duty Cycle High Reg */
    #define I2SCLL_SCLL                     0x00000080  /* I2C SCL Duty Cycle Low Reg */
    #define I2SCLH_HS_SCLH          0x00000008  /* Fast Plus I2C SCL Duty Cycle High Reg */
    #define I2SCLL_HS_SCLL          0x00000008  /* Fast Plus I2C SCL Duty Cycle Low Reg */
    
    extern void I2C0_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 */
    

  • => but the function I2CStart() return always "timeout".
    Do you mean that I2CStart() returns FALSE due to timeout?

    uint32_t I2CStart( void )
    {
      uint32_t timeout = 0;
      uint32_t retVal = FALSE;
    
      /*--- Issue a start condition ---*/
      LPC_I2C0->I2CONSET = I2CONSET_STA; /* Set Start flag */
    
    
    
      /*--- Wait until START transmitted ---*/
      while( 1 )
      {
            if ( I2CMasterState == I2C_STARTED )
            {
              retVal = TRUE;
              break;
            }
    

    But it seems you never assign an I2C_STARTED to I2CMasterState.

    Search "I2CMasterState" (10 hits in 1 files)
      new  1 (10 hits)
            Line 6: volatile uint32_t I2CMasterState = I2C_IDLE;
            Line 48:           I2CMasterState = I2C_NO_DATA;
            Line 71:                 I2CMasterState = I2C_OK;
            Line 79:         I2CMasterState = I2C_NACK_ON_DATA;
            Line 112:         I2CMasterState = I2C_OK;
            Line 120:         I2CMasterState = I2C_NACK_ON_ADDRESS;
            Line 127:         I2CMasterState = I2C_ARBITRATION_LOST;
            Line 146:         if ( I2CMasterState == I2C_STARTED )
            Line 201:   I2CMasterState = I2C_IDLE;
            Line 213:         if ( I2CMasterState == DATA_NACK )
    

  • Yes, the I2CStart() returns FALSE. This code is a driver sample of NXP for PCA8581, but don't work with my 24C08. I tried using the code below, but don't work. There is some error in I2C0_IRQHandler() that I can't find.

    void I2C0_IRQHandler(void)
    {
      uint8_t StatValue;
    
      /* this handler deals with master read and master write only */
      StatValue = LPC_I2C0->I2STAT;
    
      switch ( StatValue )
      {
            case 0x08:                      /* A Start condition is issued. */
            LPC_I2C0->I2DAT = I2CMasterBuffer[0];
            LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
            I2CMasterState = I2C_STARTED;
            break;
    
            case 0x10:                      /* A repeated started is issued */
            LPC_I2C0->I2CONCLR = (I2CONCLR_SIC | I2CONCLR_STAC);
            I2CMasterState = I2C_RESTARTED;
            break;
    
            case 0x18:                      /* Regardless, it's a ACK */
            if ( I2CMasterState == I2C_STARTED )
            {
              LPC_I2C0->I2DAT = I2CMasterBuffer[1+WrIndex];
              WrIndex++;
              I2CMasterState = DATA_ACK;
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x28:      /* Data byte has been transmitted, regardless ACK or NACK */
            case 0x30:
            if ( WrIndex != I2CWriteLength )
            {
              LPC_I2C0->I2DAT = I2CMasterBuffer[1+WrIndex]; /* this should be the last one */
              WrIndex++;
              if ( WrIndex != I2CWriteLength )
              {
                    I2CMasterState = DATA_ACK;
              }
              else
              {
                    I2CMasterState = DATA_NACK;
                    if ( I2CReadLength != 0 )
                    {
                      LPC_I2C0->I2CONSET = I2CONSET_STA; /* Set Repeated-start flag */
                      I2CMasterState = I2C_REPEATED_START;
                    }
              }
            }
            else
            {
              if ( I2CReadLength != 0 )
              {
                    LPC_I2C0->I2CONSET = I2CONSET_STA;   /* Set Repeated-start flag */
                    I2CMasterState = I2C_REPEATED_START;
              }
              else
              {
                    I2CMasterState = DATA_NACK;
                    LPC_I2C0->I2CONSET = I2CONSET_STO;      /* Set Stop flag */
              }
            }
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x40:      /* Master Receive, SLA_R has been sent */
            LPC_I2C0->I2CONSET = I2CONSET_AA;    /* assert ACK after data is received */
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x50:      /* Data byte has been received, regardless following ACK or NACK */
            case 0x58:
            I2CMasterBuffer[3+RdIndex] = LPC_I2C0->I2DAT;
            RdIndex++;
            if ( RdIndex != I2CReadLength )
            {
              I2CMasterState = DATA_ACK;
            }
            else
            {
              RdIndex = 0;
              I2CMasterState = DATA_NACK;
            }
            LPC_I2C0->I2CONSET = I2CONSET_AA;    /* assert ACK after data is received */
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
    
            case 0x20:              /* regardless, it's a NACK */
    
            case 0x48:
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            I2CMasterState = DATA_NACK;
            break;
    
            case 0x38:              /* Arbitration lost, in this example, we don't
                                            deal with multiple master situation */
            default:
            LPC_I2C0->I2CONCLR = I2CONCLR_SIC;
            break;
      }
    }
    

  • => I tried using the code below, but don't work

    What do you mean by [but don't work] in this case?