51单片机-AT24C

哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处

http://blog.csdn.net/woshixingaaa/archive/2010/10/03/5919459.aspx

AT24C02是由ATMEL公司提供的,IIC总线串行EEPROM(electronic eraser programmer read only memory),其容量为2kbit(256B),工作电压在2.7v~5.5v之间,生产工艺是CMOS。

51单片机-AT24C_第1张图片

一般数字芯片都在左下角和右上角为GND,VCC。容量的计算方法:AT24Cxx :01~1024

容量 = xx * 1kbit。

写入过程:

AT24C系列EEPROM芯片的固定部分为1010,A2,A1,A0引脚接高低电平后得到确定的3位编码,形成7位编码即为该器件的地址码。

单片机进行写操作时,首先发送该器件的7位地址码和写方向位”0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为响应,单片机收到应答后就可以传送数据了。传送数据时,单片机首先发送一个字节的被写入存储器的首地址,收到存储器器件的应答后,单片机就逐个发送数据字节,但每发送一个字节后都要等待应答。AT24C系列片内地址在接收到每一个数据字节地址后自动加1,在芯片的“一次装载字节数”限度内,只需输入首地址。装载字节数超过芯片的“一次装载字节数”时,数据地址将“上卷”,前面的数据将被覆盖。

image

字节写:

51单片机-AT24C_第2张图片

页写:

51单片机-AT24C_第3张图片

读入过程:

单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。
然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。

image

当前地址读:

51单片机-AT24C_第4张图片

随机读:

51单片机-AT24C_第5张图片

有序读:

51单片机-AT24C_第6张图片

IIC总线模拟时序图:

51单片机-AT24C_第7张图片

IIC总线应答时序图:

51单片机-AT24C_第8张图片

设备地址:

51单片机-AT24C_第9张图片

写周期:

51单片机-AT24C_第10张图片

两次写之间要有一个10ms的twR间隔

写入EEPROM一个2,然后读出,在数码管上显示出来:

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCL = P3^6;
sbit SDA = P3^7;
 
void delay()
{ ;; }                //5us       
void delay1(uchar x)
{
	uchar a,b;
	for(a=x;a>0;a--)
	 for(b=100;b>0;b--);
}

void Init(){
	SCL = 1;
	SDA = 1;
}

void start(){
	SDA = 1;
	delay();
	SCL = 1;
	delay();
	SDA = 0;
	delay();
}

void stop(){
	SDA = 0;
	delay();
	SCL = 1;
	delay();
	SDA = 1;
	delay();
}

void write(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();
	SDA=1;
	delay();
}

uchar read()
{
	uchar i,k;
	SCL=0;
	delay();
	SDA=1;
	delay();
	for(i=0;i<8;i++)
	{
		SCL=1;
		delay();	
		k=(k<<1)|SDA;			  // 将SDA赋给K的每一位
		SCL=0;
		delay();	
	}
	return k;
}


void response(){
	int i;
	SCL = 1;					       //在SCL为高电平期间,进行应答
	delay();
	while((SDA == 1) && (i < 170))i++; //SCL释放总线,等待从设备应答,从设备会把SDA拉低
	SCL = 0;						  
	delay();
}

void At24c_Write(uchar address, uchar value){
	start();
	write(0xa0);			 //写入设备地址
	response();
	write(address);			 //写入首地址
	response();
	write(value);			 //写入数据
	response();
	stop();	
}

uchar At24c_Read(uchar address){
   uchar value;
   start();
   write(0xa0);				 //伪写,先写入设备地址
   response();
   write(address);			 //再写入要读取数据的首地址
   response();
   start();					 //再次
   write(0xa1);				 //写入要读取数据的地址,方向为1
   response();
   value = read();			 //读取数据
   stop();
   return value;
}

void main(){
	P1 = 0x0;            //	位选,使最地位数码管被选中
	Init();
	At24c_Write(23,0x5b);  // 在EEPROM的23这个地址上写数据0x5b
	delay1(100);		   // 在写和读之间要多延时一会儿,否则器件处理不完
	P2 = At24c_Read(23);   // 读取23地址的数据,也就是刚才写入的数据
	while(1);
}

掉电后数据不丢失,复位后,仍然从刚才掉电的数字开始往下显示。从0~9
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit SCL = P3^6;
sbit SDA = P3^7;
uchar temp, sum;
uint flag;
unsigned char code duan[]={ 
	0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
	0x77,0x7C,0x39,0x5E,0x79,0x71};
 
void delay()
{ ;; }                //5us       
void delay1(uchar x)
{
	uchar a,b;
	for(a=x;a>0;a--)
	 for(b=100;b>0;b--);
}

void Init(){
	SCL = 1;
	SDA = 1;
}

void start(){
	SDA = 1;
	delay();
	SCL = 1;
	delay();
	SDA = 0;
	delay();
}

void stop(){
	SDA = 0;
	delay();
	SCL = 1;
	delay();
	SDA = 1;
	delay();
}

void write(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();
	SDA=1;
	delay();
}

uchar read()
{
	uchar i,k;
	SCL=0;
	delay();
	SDA=1;
	delay();
	for(i=0;i<8;i++)
	{
		SCL=1;
		delay();	
		k=(k<<1)|SDA;			  // 将SDA赋给K的每一位
		SCL=0;
		delay();	
	}
	return k;
}


void response(){
	int i;
	SCL = 1;					       //在SCL为高电平期间,进行应答
	delay();
	while((SDA == 1) && (i < 170))i++; //SCL释放总线,等待从设备应答,从设备会把SDA拉低
	SCL = 0;						  
	delay();
}

void At24c_Write(uchar address, uchar value){
	start();
	write(0xa0);			 //写入设备地址
	response();
	write(address);			 //写入首地址
	response();
	write(value);			 //写入数据
	response();
	stop();	
}

uchar At24c_Read(uchar address){
   uchar value;
   start();
   write(0xa0);				 //伪写,先写入设备地址
   response();
   write(address);			 //再写入要读取数据的首地址
   response();
   start();					 //再次
   write(0xa1);				 //写入要读取数据的地址,方向为1
   response();
   value = read();			 //读取数据
   stop();
   return value;
}

void main(){
	uint i;
	flag = 1;
	P1 = 0x0;            //	位选,使最地位数码管被选中
	EA = 1;
	ET0 = 1;
	sum = 0;
	temp = 0;
	TMOD = 0x01;
	TH0 = (65536 - 50000) / 256;
	TL0 = (65536 - 50000) % 256;
	TR0 = 1;
	Init();
	P2 = At24c_Read(23);
	for(i = 0; i < 10; i++)
		if(duan[i] == P2){
			sum = i;
			break;
			flag = 0;
		}
	while(1){
		if(temp == 20){
			temp = 0;
			if(sum == 10){
				sum = 0;
			}
			if(flag == 1){			
				At24c_Write(23,duan[sum]);
				delay1(100);
		    	P2 = duan[sum];
			}
			sum++;
		}
	}
}

void time0() interrupt 1{
	TH0 = (65536 - 50000) / 256;
	TL0 = (65536 - 50000) % 256;
	temp++;
} 


你可能感兴趣的:(Blog)