51单片机之AT24C02

51单片机之AT24C02_第1张图片

  1. 引脚介绍
    A0,A1,A2是地址的编程位。
    WP为写保护输入端。当其为低电平的时候,可以对整个储存器进行正常的读写操作;当为高电平的时候,储存器具有写保护功能,但是仍然可以从中读数据
    SCL,SDA就是时钟线和数据线

  2. 储存结构与寻址
    储存容量为2k位,即2000bit,256个字节,256B。有芯片寻址和片内地址寻址。芯片地址是1010A0A1A2R/W。如果编程地址位是000,那么芯片地址为0xa0;片内子地址寻址,一共内部有256个寻址单元,寻址范围是00-FF。在IIc通信时。在芯片地址寻址之后,主机需要发送一个字节来完成片内地址的寻址。

  3. AT24C02的操作有字节操作和页操作的方式,这里只介绍字节操作,即字节写入方式和指定地址读操作。256个寻址单元就是有256个办公室隔间,我们可以把数据写进某一个特定的隔间,也可以从某个特定的隔间读取数据。至于是读还是写就看主机发送了什么样的指令

(1)把某数据写入AT24C02的某个片内地址

void write_add(uchar address,uchar date)//把某数据写进EEPROM的某地址,参数地址和参数数据可以是任意进制的数字,因为写入的时候都转成了16进制
{
     
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);//片内地址,就是某个小隔间
	respons();
	write_byte(date);
	respons();
	stop();
}

(2)把某个片内地址的数据读取出来

uchar read_add(uchar address)
{
     
	uchar date;
	start();
	write_byte(0xa0);//芯片地址寻址
	respons();
	write_byte(address);//片内地址寻址,我们准备从这个地方读数据
	respons();
	start();
	write_byte(0xa1);//芯片地址寻址,改变读写的方向
	respons();
	date=read_byte();//从上边指定的片内小隔间读取数据
	stop();
	return date;
}

实例:
利用定时器产生秒表,每过一秒把变化的数字写入AT24C02内部,然后从AT24C02内部读取储存的数据,并显示在数码管上。

  • 数码管显示
oid display(uchar shi,uchar ge)
{
     
	dula=1;
	P0=table[shi];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfe;
	wela=0;
	delayms(5);

	dula=1;
	P0=table[ge];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfd;
	wela=0;
	delayms(5);
		
}
  • 1ms延时
void delayms(uchar x)
{
     
	uchar a,b;
	for(a=x;a>0;a--)
	 for(b=110;b>0;b--);
}

完整代码如下:

#include
#define uchar unsigned char
sbit sda=P2^0;
sbit scl=P2^1;
bit write=0;
sbit dula=P2^6;
sbit wela=P2^7;
uchar temp;
uchar num,num_sec,address_point;

uchar code table[]={
     
     0x3f,0x06,0x5b,0x4f,
	 0x66,0x6d,0x7b,0x07,
	 0x7f,0x6f,0x77,0x7c,
	 0x39,0x5e,0x79,0x71};

void display(uchar,uchar);
void delay()
{
      ;; }
void start()  //开始信号
{
     	
	sda=1;
	delay();
	scl=1;
	delay();
	sda=0;
	delay();
}

void stop()   //停止
{
     
	sda=0;
	delay();
	scl=1;
	delay();
	sda=1;
	delay();
}

void respons()  //应答
{
     
	uchar i;
	scl=1;
	delay();
	while((sda==1)&&(i<250))i++;
	scl=0;
	delay();
}

void init()
{
     
	sda=1;
	delay();
	scl=1;
	delay();
}

void write_byte(uchar date)
{
     
	uchar i,temp;
	temp=date;


	for(i=0;i<8;i++)
	{
     
		temp=temp<<1;
		scl=0;
	    delay();
		sda=CY;
		delay();
		scl=1;
		delay();
	//	scl=0;
     //   delay();
	}
	scl=0;//传输完毕需要释放SDA线,如果不释放的话如果下次读写方向改变,数据线不空闲 
	delay();
	sda=1;
	delay();
}

uchar read_byte()
{
     
	uchar i,k;
	scl=0;
	delay();
	sda=1;
	delay();
	for(i=0;i<8;i++)
	{
     
		scl=1;
		delay();	
		k=(k<<1)|sda;
		scl=0;
		delay();	
	}
	return k;
}

void delayms(uchar x)
{
     
	uchar a,b;
	for(a=x;a>0;a--)
	 for(b=100;b>0;b--);
}

void write_add(uchar address,uchar date)//把某数据写进EEPROM的某地址,参数地址和参数数据可以是任意进制的数字,因为写入的时候都转成了16进制
{
     
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	write_byte(date);
	respons();
	stop();
}

uchar read_add(uchar address)
{
     
	uchar date;
	start();
	write_byte(0xa0);
	respons();
	write_byte(address);
	respons();
	start();
	write_byte(0xa1);
	respons();
	date=read_byte();
	stop();
	return date;
}

void main()
{
     	
	uchar shi,ge;
	init();
	TH1=(65535-45872)/256;
	TL1=(65535-45872)%256;
	TMOD=0x10;
	EA=1;
	ET1=1;
	TR1=1;	
	while(1)
	{
     
		write_add(address_point,num_sec);
		delayms(100);
		P1=read_add(address_point);
		temp=P1;
		shi=temp/10;
		ge=temp%10;
		display(shi,ge);
	}		
}

void display(uchar shi,uchar ge)
{
     
	dula=1;
	P0=table[shi];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfe;
	wela=0;
	delayms(5);

	dula=1;
	P0=table[ge];
	dula=0;
	P0=0xff;
	wela=1;
	P0=0xfd;
	wela=0;
	delayms(5);
		
}

void T1_time()interrupt 3
{
     
	TH1=(65535-45872)/256;
	TL1=(65535-45872)%256;
	num++;
	if(num==20)
	{
     
		num=0;
		num_sec++;	
		address_point++;
	}
	
}

你可能感兴趣的:(51单片机学习,芯片,单片机)