LPC23xx通过I2C接口读写AT24C64

发布者:北极星小鹏最新更新时间:2016-07-25 来源: eefocus关键字:LPC23xx  I2C接口  读写AT24C64 手机看文章 扫描二维码
随时随地手机看文章
网上关于philips的32位ARM微控制器通过I2C接口读写AT24C系列E2PROM的例子基本都是通过中断方式读写的,包括周立功的书上也是用中断方式的,用这种方式,要在中断服务程序中进行复杂的处理,程序比较难以理解,使用非中断方式编程比较方便,便于理解。以下程序本人在LPC2364上测试通过。程序中的一些常量做了简要说明,具体课查看LPC23xx系列微控制器的用户手册。

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  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   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 I2CStop( 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;/* 设定I2C时钟 */

       I20SCLL = (Fpclk/Fi2c)/2;

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

       I20CONSET = 0x40;// SET I2EN /* 使能主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;//发送重复起始条件前一定要清零SI

    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;  /* 清零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)  /* 已发送起始条件 */

       {

       I2C_SendByte(AT24C64NW);  // Device Address

          if(I20STAT==0x18) /* 已发送SLA+W,已接收ACK */

          {

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

                 if(I20STAT==0x28)  /* 已发送SubAddr_H,已接收ACK */

                 {

                    I2C_SendByte(SubAddr&(0x00FF));

                    if(I20STAT==0x28) /* 已发送SubAddr_L,已接收ACK */

                    {

                                   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)  /* 已发送起始条件 */

       {

         I2C_SendByte(AT24C64NW);  // Device Address

               if(I20STAT==0x18) /* 已发送SLA+W,已接收ACK */

               {

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

                     if(I20STAT==0x28)  /* 已发送SubAddr_H,已接收ACK */

                     {

                           I2C_SendByte(SubAddr&(0x00FF));

                            if(I20STAT==0x28) /* 已发送SubAddr_L,已接收ACK */

                            {

                                   if (I2CStartAgain())//发送重复起始条件 切换为主接受模式

                                   {

                                          I2C_SendByte(AT24C64NR);

                                          if(I20STAT==0x40)/*已发送SLA+R,已接收ACK*/

                                          {                                                     

                                                    for(i=0;i

                                                    {

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

                                                         {

                                                               return FALSE;

                                                          }

                                                    }                                            

                                                     if( !( I2C_ReadByte(0, &Data[Length-1]) ) ) //读最后一个数据

                                                    {

                                                           return FALSE;   

                                                     }                                            

                                                      if (I2CStop())//发送停止条件

                                                      {

                                                            return TRUE;

                                                       }                                            

                                                         return FALSE;

                                          }

                                       return FALSE;

                                   }

                                   return FALSE;

                            }

                            return FALSE;

                     }

                     return FALSE;

            }

               return FALSE;

       }

    return FALSE;

}

关键字:LPC23xx  I2C接口  读写AT24C64 引用地址:LPC23xx通过I2C接口读写AT24C64

上一篇:ARM 汇编中的立即数
下一篇:LPC23xx的ADC功能实现

推荐阅读最新更新时间:2024-03-16 15:01

I2C接口的数字温度传感器TMP101及其应用
摘要:TMP101是TI公司生产的12位低功耗、高精度数字温度传感器,较宽的温度测量范围和较高的分辨率使其可以广泛应用于许多温度测量场合。TMP101可通过串行总线接口方便地与数字系统相连,同时还具有关闭模式和报警输出。文中介绍了TMP101的内部结构和主要特性,并给出了与PrPMC800模块的接口应用。 关键词:温度传感器;I2C;SMBus;PrPMC800;TMP101 1 TMP101的引脚功能和主要特性 TMP101是TI公司生产的12位低功耗、高精度的数字温度传感器它采用与I2C和SMBus相兼容的2线数字接口,可应用于许多高分辨率和宽量程温度测量场合,如温度控制系统、个人计算机保护、电子测试仪器、办公设备以
[传感技术]
Linux的I2C 设备驱动 -- mini2440 上i2c接口触摸屏驱动
本篇记录在友善之臂 mini2440 平台上挂载I2C接口触摸屏的驱动开发过程。 内核版本linux-2.6.32.2, 平台是ARM9 S3C2440+I2C接口的触摸屏 如上篇 Linux的I2C驱动体系结构讲述 http://www.lupaworld.com/273398/viewspace-204237.html 要挂载新的I2C设备,需要实现3部分: 1) 适配器的硬件驱动: 内核中已经实现mini2440,i2c适配器驱动,可以在如下目录i2c-s3c2410.c中看到相关代码 linux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c 2) I2C 设配器的algorithm 同
[单片机]
I2C之知(六)--s3c2440用I2C接口访问EEPROM
        在前面阅读理解了I2C的官方协议文档后,就拿s3c2440和EEPROM来验证一下.         本来是想用s3c2440的SDA和SCL管脚复用为GPIO来模拟的,但在没有示波器的情况下搞了一周,怎么都出不来,最后还是放弃了.甚至参考了linux下i2c-algo-bit.c和i2c-gpio.c,依然没调出来.如果有示波器,可能很快就能找到原因,现在完全不知道问题出在哪里.其实想用GPIO模拟I2C的目的很简单,以一种简单而又深刻的方式来理解I2C.         既然这条路暂时没法走,退而求其次,用s3c2440的I2C接口来访问EEPROM,只要按照datasheet的来做,基本上不用考虑时序咯.
[嵌入式]
51单片机OLED12864 I2C接口使用教程
现在能买到的OLED12864显示屏大多为SPI和I2C接口的,I2C通信协议只需要两条总线就可以进行通信,下面介绍一下如何用51单片机使用I2C接口的OLED12864。 首先介绍一下I2C通信协议,I2C(Inter-Integrated Circuit)字面上的意思是集成电路之间,它其实是I2CBus简称,所以中文应该叫集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。I2C的正确读法为“I平方C”( I-squared-C )。 I2C只使用两条双向漏极开路(Open Drain)(串行数据(SDA)及串行时钟频率(S
[单片机]
51单片机OLED12864 <font color='red'>I2C接口</font>使用教程
MSP430单片机对AT24C64读写操作子程序
/*----------------------------------- MSP430单片机对AT24C64的读写操作子程序 来源:晖创电子网www.schuitron.comMSP430程序 ---------------------------------------*/ #ifndef_I2C_H #define_I2C_H #defineSDA_1P4OUT|=0x02//SDA=1 #defineSDA_0P4OUT&=~0x02//SDA=0 #defineSCL_1P4OUT|=0x01//SCL=1 #defineSCL_0P4OUT&=~0x01//SCL=0 #defineSDA_INP4
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved