LPC23xx reads and writes AT24C64 via I2C interface

Publisher:北极星小鹏Latest update time:2016-07-25 Source: eefocusKeywords:LPC23xx Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
The examples on the Internet about reading and writing AT24C series E2PROM through I2C interface of Philips 32-bit ARM microcontroller are basically read and written through interrupt mode, including Zhou Ligong's book. In this way, complex processing must be performed in the interrupt service program, and the program is difficult to understand. It is more convenient to program in non-interrupt mode and easy to understand. The following program has been tested on LPC2364. Some constants in the program are briefly explained. For details, please refer to the user manual of LPC23xx series microcontrollers.

I2C.h

#define AT24C64NW 0xA0
#define AT24C64NR 0xA1

#define MAX_TIMEOUT 0x00FFFFFF
#define I2CONSET_I2EN 0x00000040 /* I2C Control Set Register */
#define I2CONSET_AA 0x00000004
#define I2CONSET_SI 0x00000008
#define I2CONSET_STO 0x00000010
#define I2CONSET_STA 0x 00000020

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


#define SDA0 0x08000000 //p0.27
#define SCL0 0x10000000 //p0.28
#define SDA0CON 0x08000000
#define SCL0CON 0x10000000
extern DWORD I2CInit( UINT32 Fi2c );
extern DWORD I2CStart( void );
extern DWORD I2CS top( void );
extern DWORD I2CStartAgain( void );
extern DWORD I2C_ReadByte(BYTE ACK, BYTE *RcvData);
extern DWORD I2C_SendNByte(UINT16 SubAddr,UINT8 *Data,UINT8 Length);
extern DWORD I2C_ReadNByte(UINT16 SubAddr,UINT8 *Data,UINT8 Length);

I2C.c

DWORD I2CInit( UINT32 Fi2c )

{

       if (Fi2c > 400000)

              Fi2c = 400000;

      

    PINSEL1 &= ~0x03C00000;

       PINSEL1 |= 0x01400000; /* set PIO0.27 and PIO0.28 to I2C0 SDA and SCK */

                                         

       I20SCLH = (Fpclk/Fi2c + 1) / 2; /* Set I2C clock */

       I20SCLL = (Fpclk/Fi2c)/2;

       I20CONCLR = 0x2C;//clear STA, SI,AA

       I20CONSET = 0x40; // SET I2EN /* Enable master I2C */ 

    return( TRUE );

}

 

DWORD I2CStart( void )

{

    DWORD timeout = 0;

    DWORD returnValue = FALSE;

    /*--- Issue a start condition ---*/

       I20CONCLR=I2CONCLR_SIC|I2CONCLR_AAC|I2CONCLR_STAC;

    I20CONSET=I2CONSET_STA|I2CONSET_I2EN; /* Set Start flag */

      

    /*--- Wait until START transmitted ---*/

    while( 1 )

    {

              if (I20STAT==0x08)

              {

                  returnValue = TRUE;

                  break;    

              }

              if ( timeout >= MAX_TIMEOUT )

              {

                  returnValue = FALSE;

                  break;

              }

              timeout++;

    }

    return(returnValue);

}

DWORD I2CStartAgain( void )

{

    DWORD timeout = 0;

    DWORD returnValue = FALSE;

 

    /*--- Issue a start condition ---*/

       I20CONCLR = I2CONCLR_SIC|I2CONCLR_AAC|I2CONCLR_STAC; // Be sure to clear SI before sending a repeated start condition

    I20CONSET = I2CONSET_STA|I2CONSET_I2EN; /* Set Start flag */

   

    /*--- Wait until START transmitted ---*/

    while( 1 )

    {

              if ( I20STAT == 0x10 )

              {

                  returnValue = TRUE;

                  break;    

              }

              if ( timeout >= MAX_TIMEOUT )

              {

                  returnValue = FALSE;

                  break;

              }

              timeout++;

    }

    return(returnValue);

}

DWORD I2CStop( void )

{

    I20CONSET = I2CONSET_STO; /* Set Stop flag */

    I20CONCLR = I2CONCLR_SIC|I2CONCLR_STAC|I2CONCLR_AAC; /* Clear SI flag */// modified

           

    /*--- Wait for STOP detected ---*/

    while( I20CONSET & I2CONSET_STO );

    return TRUE;

}

void I2C_SendByte(UINT8 SData)

{

  I20DAT=SData;

  I20CONCLR =0x28; /* Clear SI, STA */

  while (!(I20CONSET&I2CONCLR_SIC));// wait interrupt flag (waiting for SI==1)

}

DWORD I2C_SendNByte(UINT16 SubAddr,UINT8 *Data,UINT8 Length)

{

       BYTE i;

    I2CStart();

       if(I20STAT==0x08) /* Start condition has been sent */

       {

       I2C_SendByte(AT24C64NW); // Device Address

          if(I20STAT==0x18) /* SLA+W has been sent, ACK has been received */

          {

           I2C_SendByte((SubAddr>>8)&(0x00FF));

                 if(I20STAT==0x28) /* SubAddr_H has been sent, ACK has been received */

                 {

                    I2C_SendByte(SubAddr&(0x00FF));

                    if(I20STAT==0x28) /* SubAddr_L has been sent, ACK has been received */

                    {

                                   for(i=0;i

                                  {

                                        do{

                                                     I2C_SendByte(Data[i]);

                                            }while(I20STAT!=0x28);

                                     }

                                    

                                    if(I2CStop())

                                    {                                      

                                       DelayNS(5); //10ms

                                        return TRUE;

                                    }

                                    return FALSE;                            

                            }

                             return FALSE;

                   }

                 return FALSE;

            }

          return FALSE;

       }

       return FALSE;

}

DWORD I2C_ReadByte(BYTE ACK, BYTE *RcvData)

{

           if (ACK==1) // send ACK

          {

                 I20CONSET=I2CONSET_AA;

           }

          else // send NOACK

          if(ACK==0)

          {

             I20CONCLR=I2CONCLR_AAC;

          }

 

         I20CONCLR=I2CONCLR_SIC|I2CONCLR_STAC; // clear SI SAT

         while (!(I20CONSET&I2CONCLR_SIC));// wait interrupt flag (waiting for SI==1) 

 

         if(ACK==1)

        {

               if((I20STAT&0xF8)==0x50) // receive data and get ack

              {

                     *RcvData=I20DAT;

                     return TRUE;

               }

              else

                     return FALSE ;

         }

        else

        if(ACK==0)

        {

              if((I20STAT&0xF8)==0x58) // receive data and get NoAck (the last data you want to get)

           {

                     *RcvData=I20DAT;

                     return TRUE;

           }

              else

                     return FALSE ;

         }

         return FALSE ;

}

DWORD I2C_ReadNByte(UINT16 SubAddr,UINT8 *Data,UINT8 Length)

{

       BYTE i;

    if (!I2CStart()) 

       {

        return FALSE;

       }

       if(I20STAT==0x08) /* Start condition has been sent */

       {

         I2C_SendByte(AT24C64NW); // Device Address

               if(I20STAT==0x18) /* SLA+W has been sent, ACK has been received */

               {

            I2C_SendByte((SubAddr>>8)&(0x00FF));

                     if(I20STAT==0x28) /* SubAddr_H has been sent, ACK has been received */

                     {

                           I2C_SendByte(SubAddr&(0x00FF));

                            if(I20STAT==0x28) /* SubAddr_L has been sent, ACK has been received */

                            {

                                   if (I2CStartAgain()) //Send repeated start condition to switch to master receiving mode

                                   {

                                          I2C_SendByte(AT24C64NR);

                                          if(I20STAT==0x40)/*SLA+R sent, ACK received*/

                                          {                                                     

                                                    for(i=0;i

                                                    {

                                                         if(!(I2C_ReadByte(1,&Data[i])))

                                                         {

                                                               return FALSE;

                                                          }

                                                    }                                            

                                                     if( !( I2C_ReadByte(0, &Data[Length-1]) ) ) //Read the last data

                                                    {

                                                           return FALSE;   

                                                     }                                            

                                                      if (I2CStop()) //Send stop condition

                                                      {

                                                            return TRUE;

                                                       }                                            

                                                         return FALSE;

                                          }

                                       return FALSE;

                                   }

                                   return FALSE;

                            }

                            return FALSE;

                     }

                     return FALSE;

            }

               return FALSE;

       }

    return FALSE;

}

Keywords:LPC23xx Reference address:LPC23xx reads and writes AT24C64 via I2C interface

Previous article:Immediate values ​​in ARM assembly
Next article:ADC function implementation of LPC23xx

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号