给别人做的个东西,要求数据掉电保存,大的框架很早就搭建起来了,但是到了24C02这,卡住了。不是无法实现存储,只是我的数据量比较大,好几天在网上搜索24C02相关的程序,几乎把所有的能看的都看遍了,我失望的才发现,大同小异,大家都是互相抄来抄去的,没有一个能很好用的,而且有的程序又是缺个括号,或者只有括号的一半,另一半和里边的变量都不知道跑哪去了,看的很是郁闷啊,开始想,不到万不得已,坚决不看英文的技术手册,今早一大早泡图书馆看书查资料,复印了好几十页,到了实验室又打印了技术文档,边看边查单词边翻译,还有在我的好兄弟的一起协助下,终于轻松实现了24C02存储255个数据。同时也大体明白了24C02得工作原理。
1、24C02是2Kbits 意思是有2048bit,换算成字节是256Byte,也就是说最多可以存储255个字节的数据;
2、ATMEl24C02(应该其他厂家的24C02也是这样子吧。。。)有32页,每页可以存放8个字节;
3、24C02有两种工作模式:(1)、字节写入模式:结合技术文档我认为该模式是这样工作的:首先是可以再任意的地址(0x00~0xFF)写入一个字节,也可以在某一地址连续的写入N字节,而且不需要翻页,从技术手册得知,答题时说字节写入模式下,页指针根写入数据的多少来自动增加实现翻页功能,不用自己在程序里边实现;
(2)、页写入模式:页写入模式下,手册上写着,一页可以存8字节,当存储的数据大于8时,则会覆盖先前保存的数据,例如,有16个数据 uchar data[16]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15},从24C02的0x00地址开始存放,当存完一页(8个)时,第9个数据会保存在0x00,覆盖掉开始保存的1,后边的数据一次类推,这样的现象叫做“翻转”,如果想写完一页后将剩余的数据保存在下一页,页指针需要自己来设定。
我觉着,字节写入模式相对更简单些。
下边,附上我的程序,供大家参考,如有疑问的地方,欢迎大家交流!
///使用单片机:89S51
///晶振:12MHz
#include<reg52.h>
#include "INTRINS.H"
#define uchar unsigned char
#define uint unsigned int
sbit scl = P3^2;
sbit sda = P3^3;
/*********74H573控制端*********/
sbit dula = P2^7;//段选
sbit wela = P2^6;//位选
sbit LED = P2^5;//秒显示
uchar tt=0;
uchar i=0,j=0,temp=0,a=0,b=0,c=0;
/*******数码管段选_时间********/
uchar code table_duan[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
/*********数码管位选**********/
uchar code table_wei[]={0xfe,0xfd,0xfb,0xf7,0xef};
void delay1(uint x)
{
uint i,j ;
for(i=x;i--;i>0)
for(j=110;j--;j>0);
}
/**************************** 显示函数 **************************/
void display(uchar wee,uchar H_hour,uchar L_hour,uchar H_min,uchar L_min)
{
dula=1;
P0=table_duan[wee];//数码管5位,星期
dula=0;
wela=1;
P0=table_wei[0];
wela=0;
delay1(1);
dula=1;
P0=table_duan[H_hour];//数码管4位,小时十位
dula=0;
wela=1;
P0=table_wei[1];
wela=0;
delay1(1);
dula=1;
P0=table_duan[L_hour];//数码管3位,小时个位
dula=0;
wela=1;
P0=table_wei[2];
wela=0;
delay1(1);
dula=1;
P0=table_duan[H_min];//数码管2位,分钟十位
dula=0;
wela=1;
P0=table_wei[3];
wela=0;
delay1(1);
dula=1;
P0=table_duan[L_min];//数码管1位,分钟个位
dula=0;
wela=1;
P0=table_wei[4];
wela=0;
delay1(1);
}
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;
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 write_add(uchar address,uchar date)
{
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;
}
/*-------------------------------------------------------------
主程序
功能:实现存储器EEPROM AT24C02的数据读写操作
------------------------------------------------------------*/
void main()
{
TMOD=0x01;//设置定时器0为工作方式1
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;//开总中断
ET0=1;//开定时器0中断
TR0=0;//启动定时器0
P2=P2&0xc0;
init();
for(i=0; i<255; i++)
{
write_add(i,i);
delay1(1);
}
TR0=1;
while(1)
{
if(j == 255)j=0;
TR0=0;
temp=read_add(j);
TR0=1;
a=temp/100;
b=temp%100/10;
c=temp%100%10;
display(a,b,c,0,0);
}
}
void timer0() interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
tt++;
if(tt == 5)
{
tt = 0;
LED = ~LED;//用于指示是否工作正常
j++;
}
}
不会的。最简单的办法,你可以把数据放到一个数组里,每循环一次检查一下标志位,如果空闲就写下一个字节。这样就相当于软中断。
一周热门 更多>