《深入浅出AT24C02芯片使用指南》

AT24C02简介

      AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节,有一个16字节页写缓冲器。该器件通过IIC总线接口进行操作,有专门的写保护功能。应用于AT24C02制造过程的先进CMOS技术实质上减少了器件的功耗。

           

AT24C02特性

      1、采用I2C 总线传输数据。

      2、工作电压范围:1.8V ~6.0V。

      3、采用低功耗CMOS 技术制造。

      4、当WP 为高电平时,AT24C02进入写保护状态。

      5、页写缓冲器。

      6、自定时擦写周期。

      7、1,000,000 编程/擦除周期。

      8、寿命长,可保存数据100 年。

      9、2种封装:8脚DIP SOIC 或TSSOP 封装。

      10、温度范围:商业级、工业级和汽车级。 

AT24C02管脚描述

      1、SCL 串行时钟管脚

      AT24C02串行时钟输入管脚用于产生该器件所有数据发送或接收的时钟,SCL 串行时钟管脚是一个输入管脚。

      2、SDA 串行数据

      AT24C02的双向串行数据管脚SDA,用于该器件所有数据的发送或接收。SDA 管脚是一个开漏输出管脚。

      3、A0、A1、A2 器件地址输入端

      这3个输入管脚用于多个器件级联时设置器件地址,当这些管脚悬空时默认值为0。AT24C02 最大可级联8个器件。如果只有一个AT24C02被总线寻址,这三个地址输入脚(A0、A1、A2 )可悬空或连接到Vss 或 GND。

      4、WP写保护

      如果WP管脚连接到Vcc,AT24C02中所有的内容都被写保护只能读。当WP管脚连接到Vss 或 GND 或悬空时,允许AT24C02器件进行正常的读/写操作。

      5、VCC管脚

      AT24C02的VCC管脚接+1.8V~+6.0V 工作电压的正极。

     6、VSS管脚

      AT24C02的VSS管脚接+1.8V~+6.0V 工作电压的负极(即GND)。

AT24C02的器件寻址

      AT24C02的芯片地址为1010,其地址控制字格式为1010A2A1A0R/W。

       A2,A1,A0为可编程地址选择位(这3位必须与相应的硬件接线输入引脚相比较,对应AT24C02的管脚1、2 和3)。A2,A1,A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该AT24C02器件的地址码。R/W为AT24C02读写控制位:为1,表示对AT24C02进行读操作;为0,表示对AT24C02进行写操作。

AT24C02写操作

      在字节写模式下主器件发送起始命令和从器件地址信息(R/W 位置零)给从器件。在从器件产生应答信号后,主器件发AT24C02的字节地址,主器件在收到从器件的另一个应答信号后,再发送数据到被寻址的存储单元。AT24C02再次应答,并在主器件产生停止信号后开始内部数据的擦写,在内部擦写过程中AT24C02不再应答主器件的任何请求。

      页写操作的启动和字节写是相同的。不同在于主器件在第一个数据字节被写入后并不产生停止信号。主器件可以发送多达7 (1K/2K)或15 (4K, 8K, 16K)个额外的字节。每发送一个字节数据后AT24C02会产生一个应答位并将字节地址低位加1,而高位保持不变。

      当AT24C02内部接收的数据字节到达页面边界时,后续的数据字节会被放置在同一页面的开头(即开头原有的数据字节会被覆盖掉)。 

读操作

      对AT24C02的读操作的初始化方式和写操作时一样,只是把R/W 位置为1。有三种不同的读操作方式:立即地址读、选择读和连续读。

      立即地址读

      AT24C02的地址计数器内容为最后操作字节的地址加1。也就是说如果上次读/写的操作地址为N,则立即读的地址从地址N+1开始。但当N+1超过页面边界时,将会“翻转”到0(即从当前页的最后一个字节翻转到同一页的第一个字节),且继续输出数据。

      AT24C02接收到从器件地址信号后(R/W 位置1),它首先发送一个应答信号,然后发送一个8位字节数据。主器件不需发送一个应答信号,但要产生一个停止信号。

选择性读

      选择性读操作允许主器件对从器件寄存器的任意字节进行读操作。主器件首先通过发送起始信号、从器件地址和它想读取的字节数据的地址执行一个伪写操作。在从器件应答之后,主器件重新发送起始信号和从器件地址,此时R/W 位置1,AT24C02响应并发送应答信号,然后输出所要求的一个8位字节数据,主器件不发送应答信号但产生一个停止信号。

      选择读时序

 

连续读

      连续读操作可通过立即读或选择性读操作启动。在AT24C02发送完一个8 位字节数据后,主器件产生一个应答信号来响应,告知AT24C02,主器件要求更多的数据。对应每个主器件产生的应答信号,AT24C02将发送一个8 位数据字节。当主器件不发送应答信号而发送停止位时结束此操作。

      当读取的字节超过页面边界时,地址计数器将翻转到零,并继续输出数据字节。

一个例程:

/****************EEPROM读写多个数据*****************   

*单片机型号:STC89C52RC,频率:11.0592M

*开发环境:KEIL

*功能:EEPROM读写多个数据,根据数据点亮LED

***********************************************************/

#include<reg51.h>

#define uint unsigned int

#define uchar unsigned char

sbit sda = P2^0;                        

sbit scl = P2^1;

sbit LED = P1^0;

uchar code data1[40] = {

                         0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,

                         0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,

                         0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,

                         0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,0xf0,0x0f,

                         0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff

                        };

uchar buffer[40];                         //用于缓存从24c02中读取的数据。    

                 

void delay1(uint z)

{

 uchar x,x1;

 for(;z>0;z–)

 {

  for(x=0;x<114;x++)

  {for(x1=0;x1<1;x1++);}

 }

}

void delay_5us()

{

 int i;

 for(i=0;i<1;i++){;}

}

void delay(int In,int Out)              //定义延时函数 

{

 int i,j;

 for(i=0;i<In;i++)

 {for(j=0;j<Out;j++){;}}

}

void star()                                    //开始

{

 sda=1;delay_5us();

 scl=1;delay_5us();

 sda=0;delay_5us();

}

void stop()                                 //停止

{

 sda=0;delay_5us();

 scl=1;delay_5us();

 sda=1;delay_5us();

}

void ack()                                //应答

{

 uchar z=0;

 while((sda==1)&&(z<50))z++;

 scl=0;

 delay_5us();

}

//写一个数据函数

//器件写地址 slave_write_address

//字节地址 byte_address

//待写入数据 data_data

void write(uchar slave_write_address,uchar byte_address,uchar data_data)

//写一个数据

{

 uchar temp,temp1,i,ii;

 star();                                              //开始

 for(ii=0;ii<3;ii++)                             //按顺序送:器件写地址,字节地址,数据

 {

  if(ii==0)

  {

   temp=slave_write_address;        //送器件写地址

   temp1=slave_write_address;

  }

  else if(ii==1)

  {

   temp=byte_address;                  //送字节地址

   temp1=byte_address;

  }

  else if(ii==2)

  {

   temp=data_data;                      //送数据

   temp1=data_data;

  }

  for(i=0;i<8;i++)

  {

   scl=0;

   delay_5us();                             //5us延时

   temp=temp1;

   temp=temp&0x80;                   //相与后,把不相关的位清零     

  if(temp==0x80)                 

  //根据前面相与后,判断temp是否等于0x80,是则该位为 1

    sda=1;

    else

    sda=0;

    delay_5us();                           //5us延时

    scl=1;

    delay_5us();                           //5us延时

    scl=0;

    delay_5us();                           //5us延时

    temp1=temp1<<1;                 //向左移出1位

   }

   sda=1;

   delay_5us();                            //5us延时

   scl=1;

   delay_5us();                            //5us延时

   ack();

  }

  stop();                                       //停止

 }

//读一个数据函数

//器件写地址 slave_write_address

//器件读地址 slave_read_address

//字节地址 byte_address

//读出的数据 data_data

uchar read(uchar slave_write_address,uchar byte_address,uchar slave_read_address)

//读一个数据

{

 uchar temp,temp1,i,ii,x,data_data;

 star();                                                            //开始

 for(ii=0;ii<3;ii++)                     

 //按顺序送:器件写地址,字节地址,器件读地址

 {

  if(ii==0)

  {

   temp=slave_write_address;                       //送器件写地址

   temp1=slave_write_address;

  }

  else if(ii==1)

  {

   temp=byte_address;                                  //送字节地址

   temp1=byte_address;

  }

  else if(ii==2)

  {

   star();                                                         //开始

   temp=slave_read_address;                       //送器件读地址

   temp1=slave_read_address;

  }

for(i=0;i<8;i++)                                              //开始读数据

  {

   scl=0;

   delay_5us();

   temp=temp1;

   temp=temp&0x80;                                    //相与后,把不相关的位清零

   if(temp==0x80)                         

   //根据前面相与后,判断temp是否等于0x80,是则该位为 1

   sda=1;

   else

   sda=0;

   delay_5us();

   scl=1;

   delay_5us();

   scl=0;

   delay_5us();

   temp1=temp1<<1;                         //向左移出1位

  }

  sda=1;

  delay_5us();

  scl=1;

  delay_5us();

  ack();                                               //应答

 }

 for(x=0;x<8;x++)

 {

  data_data=data_data<<1;                 //向左移入1位

  sda=1;

  delay_5us();

  scl=0;

  delay_5us();

  scl=1;

  delay_5us();

  if(sda==1)                                   //判断 数据线是否是高电平

  data_data|=0x01;                        //把读到的数据或0X01

 }

 ack();                                           //应答

 stop();                                          //停止

 return data_data;                        //返回读到的数据 

}

void main()

{

 uchar i;

 for(i=0;i<=39;i++)

 {

  write(0xa0,i,data1[i]);

  delay1(20);

  LED = ~LED;                

 }

 LED=0;delay(50,1000);

 LED=1;

 delay(50,1000);   

 for(i=0;i<=39;i++)

 {

  buffer[i]=read(0xa0,i,0xa1);delay1(20);

  LED=~LED;

 }

 LED=0;delay(50,1000);

 LED=1;delay(50,1000);

 LED=0;delay(50,1000);

 LED=1;delay(50,1000);

 for(i=0;i<=39;i++)

 {

  P1=buffer[i];

  delay(50,1000);

 }

 while(1);

}

与例程对应的电路图

 

 

物联沃分享整理
物联沃-IOTWORD物联网 » 《深入浅出AT24C02芯片使用指南》

发表评论