有關AT24C02芯片的斷電記憶功能總是無法實現 望各位指點指點!
/*12M晶振實現數碼管顯示時間,日期與年月,星期,鬧鐘,并實現信息可調*/
#include<at89x52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
bit write=0; //寫24c02的標志
sbit sda=P1^0;
sbit scl=P1^1;
sbit dula=P3^6;//段選
sbit wela=P3^7;//位選
uchar sec,tcnt;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xbf};
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
uchar n,a;
uchar hh,mm,ss;
uchar nhh,nmm,nss;
uint year,year3;
uchar day,mon,week,year1,year2;
uchar hhs,hhg,mms,mmg,sss,ssg;
uchar days,dayg,mons,mong;
uchar nhhs,nhhg,nmms,nmmg,nsss,nssg;
uchar set1=1,set2=1;
sbit fm=P3^4;
sbit k1=P3^0; //時間顯示切換鍵
sbit k2=P3^1; //移位功能鍵
sbit k3=P3^2; //加法按鍵
sbit k4=P3^3; //減法按鍵
uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //閏年
uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非閏年
void baoshi();
void alarm();
void set_time();
void set_alarm();
void set_mdw();
void key_change();
void key_set();
void display(uchar,uchar,uchar);
void display5(uchar);
void delay1()
{;}
void delay(uchar xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=0;j<300;j++);
}
void di()
{
fm=0;
delay(10);
fm=1;
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
void start() //開始函數
{
sda=1;
delay1();
scl=1;
delay1();
scl=0;
delay1();
}
void stop() //停止函數
{
sda=0;
delay1();
scl=1;
delay1();
sda=1;
delay1();
}
void respons() //回應函數
{
uchar i;
scl=1;
delay1();
while((sda==1)&&(i<250))i++;
scl=0;
delay1();
}
void write_byte(uchar date) //寫一個字節函數
{
uchar temp,i;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=1;
delay1();
sda=CY;
delay1();
scl=1;
delay1();
}
scl=0;
delay1();
sda=1;
delay1();
}
uchar read_byte() //讀一個字節函數
{
uchar i,k;
scl=0;
delay1();
sda=1;
delay1();
for(i=0;i<8;i++)
{
scl=1;
delay1();
k=(k<<1)|sda;
scl=0;
delay1();
}
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;
}
void init_24c02() //I2C初始化函數
{
sda=1;
delay1();
scl=1;
delay1();
}
void init()
{
dula=0; //關閉兩個鎖存器鎖存端,防止數碼管出現亂碼
wela=0;
hh=8;mm=0;ss=0; //時鐘
nhh=6;nmm=0;nss=0; //鬧鐘
year=2010;mon=7;day=3;week=6;
year3=year-year/100*100;
init_24c02();
display(year3,mon,day);
display(hh,mm,ss);
display(nhh,nmm,nss);
//display1(); //正常顯示年月日
year3=read_add(1);mon=read_add(2);day=read_add(3);
display(year3,mon,day);
delay(500);
hh=read_add(4);mm=read_add(5);ss=read_add(6);
display(hh,mm,ss);
delay(500);
nhh=read_add(7);nmm=read_add(8);nss=read_add(9);
display(nhh,nmm,nss);
delay(500);
TMOD=0x11;
TH0=0x3c;TL0=0xb1;
TH1=0x3c;TL1=0xb1;
EA=1;
TR0=1;ET0=1;
TR1=1;ET1=1;
}
void main()
{
hhs=hh/10%10;//時
hhg=hh%10;
mms=mm/10%10; //分
mmg=mm%10;
sss=ss/10%10; //秒
ssg=ss%10;
nhhs=nhh/10%10;//鬧鐘時
nhhg=nhh%10;
nmms=nmm/10%10; //鬧鐘分
nmmg=nmm%10;
nsss=nss/10%10; //鬧鐘秒
nssg=nss%10;
dayg=day/10%10; //日
days=day%10;
mons=mon/10%10; //月
mong=mon%10;
year1=year3/10%10; //年個位
year2=year3%10; //年十位
init();
while(1)
{
key_change(); //k1按鍵掃描
key_set(); //k2按鍵掃描
set_time(); //設置時間
set_mdw(); //設置年月日
set_alarm(); //設置鬧鐘
if(set1==1)display(read_add(1),read_add(2),read_add(3));
if(set1==2)display(read_add(1),read_add(2),read_add(3));
if(set1==3)display(read_add(4),read_add(5),read_add(6));
if(set1==4)display(read_add(4),read_add(5),read_add(6));
if(set1==5)display5(read_add(7));
if(set1==6)display(read_add(8),read_add(9),read_add(10));
if(set1==7)display(read_add(8),read_add(9),read_add(10));
}
}
void display(uchar a,uchar b,uchar c) //
{
uchar a1,a2;uchar b1,b2;uchar c1,c2;
a1=a/10%10;a2=a%10;
b1=b/10%10;b2=b%10;
c1=c/10%10;c2=c%10;
dula=1;P0=tab[a1];dula=0;P2=0xff;wela=1;P2=0x01;wela=0;delay(1);
dula=1;P0=tab[a2];dula=0;P2=0xff;wela=1;P2=0x02;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x04;wela=0;delay(1);
dula=1;P0=tab[b1];dula=0;P2=0xff;wela=1;P2=0x08;wela=0;delay(1);
dula=1;P0=tab[b2];dula=0;P2=0xff;wela=1;P2=0x10;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x20;wela=0;delay(1);
dula=1;P0=tab[c1];dula=0;P2=0xff;wela=1;P2=0x40;wela=0;delay(1);
dula=1;P0=tab[c2];dula=0;P2=0xff;wela=1;P2=0x80;wela=0;delay(1);
}
void diplay5(uchar a) //
{
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x01;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x02;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x04;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x08;wela=0;delay(1);
dula=1;P0=tab[a];dula=0;P2=0xff;wela=1;P2=0x10;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x20;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x40;wela=0;delay(1);
dula=1;P0=tab[10];dula=0;P2=0xff;wela=1;P2=0x80;wela=0;delay(1);
}
uchar incone(uchar n) //加1函數
{
if(k3==0)
{delay(20);
if(k3==0)
{
n++;
while(!k3);
di();
}
}
return(n);
}
uchar decone(uchar m) //減1函數
{
if(k4==0)
{
delay(20);
if(k4==0)
{
m--;
while(!k4);
di();
if(m<0)
{m=0;}
}
}
return(m);
}
void key_change() //k1按鍵掃描
{
if(k1==0)
{
delay(20);
if(k1==0) //確認切換鍵被按下
{
set1++; //紀錄切換鍵被按下次數
while(!k1); //釋放確定
di();
if(set1==8)
{set1=1;}
}
}
}
void key_set() //k2按鍵掃描
{
if(k2==0)
{
delay(20);
if(k2==0)
{
set2++;
while(!k2);
di();
if(set2==4)
{set2=1;}
}
}
}
void baoshi() //整點報時函數
{
if(mm==00&&ss==00)
{fm=0;}
if(ss==1)
{fm=1;}
}
void alarm() //鬧鐘函數
{
uchar x;
if(nhh==0)
{
goto end;
}
if(hh==nhh&&mm==nmm&&ss==nss)
{
for(x=0;x<6;x++)
{
fm=0;delay(30);fm=1;delay(20);
fm=0;delay(30);fm=1;delay(20);
fm=0;delay(30);fm=1;delay(20);
fm=0;delay(30);fm=1;delay(160);
}
}
end:;
}
void set_time() //設置時間函數
{
if(set1==4)
{
if(set2==1)
{
hh=incone(hh);
if(hh==24)
{hh=0;}
if(hh==-1)
{hh=23;}
hh=decone(hh);
write_add(4,hh);
}
if(set2==2)
{
mm=incone(mm);
if(mm==60)
{mm=0;}
if(mm==-1)
{mm=59;}
mm=decone(mm);
write_add(5,mm);
}
if(set2==3)
{
ss=incone(ss);
if(ss==60)
{ss=0;}
if(ss==-1)
{ss=59;}
ss=decone(ss);
write_add(6,ss);
}
}
}
void set_mdw() //設置年月日
{
if(set1==2)
{
if(set2==1)
{
year3=incone(year3);
if(year3>99)
{ year3=0;}
year3=decone(year3);
if(year3<0)
{ year3=0;}
write_add(1,year3); //在24C02的地址1中寫入數據year3年
}
if(set2==2)
{
mon=incone(mon);
if(mon==13)
{ mon=1;}
mon=decone(mon);
if(mon==0)
{mon=12;}
write_add(2,mon); //在24C02的地址2中寫入數據mon年
}
if(set2==3)
{
day=incone(day);
if(day==32)
{day=1;}
day=decone(day);
if(day==0)
{day=31;}
write_add(3,day); //在24C02的地址1中寫入數據day日
}
}
}
void set_alarm() //設置鬧鐘函數
{
if(set1==7)
{
if(set2==1)
{
nhh=incone(nhh);
if(nhh==24)
{nhh=0;write_add(8,nhh);}
if(nhh==-1)
{nhh=23;write_add(8,nhh);}
nhh=decone(nhh);
write_add(8,nhh);
}
if(set2==2)
{
nmm=incone(nmm);
if(nmm==60)
{nmm=0;write_add(9,nmm);}
nmm=decone(nmm);
if(nmm==-1)
{nmm=59;write_add(9,nmm);}
write_add(9,nmm);
}
if(set2==3)
{
nss=incone(nss);
if(nss==60)
{nss=0;write_add(10,nss);}
nss=decone(nss);
if(nss==-1)
{nss=59;write_add(10,nss);}
write_add(10,nss);
}
}
}
void timer1() interrupt 3
{
TH1=(65536-50000)/256;//再次裝定時器初值
TL1=(65536-50000)%256;
a++;
if(a<100)display(year3,mon,day);
if(a>100&&a<200)display(hh,mm,ss);
if(a>200&&a<300)display(nhh,nmm,nss);
if(a>300)a=0;
}
void timer0() interrupt 1//定時器0中斷服務程序
{
TH0=(65536-50000)/256;//再次裝定時器初值
TL0=(65536-50000)%256;
n++; //中斷次數累加
if(n==20) //20次50毫秒為1秒
{
n=0;
ss++;
if(ss==60)//秒加到60則進位分鐘
{
ss=0;//同時秒數清零
mm++;
if(mm==60)//分鐘加到60則進位小時
{
mm=0;//同時分鐘數清零
hh++;
if(hh==24)//小時加到24則小時清零
{
hh=0;
day++;week++;
if(week==8)
{week=0;}
write_add(7,week);
if(year%4==0&&year%100!=0||year%400==0) //閏年
{if(day==table1[mon]+1)
{ day=0;mon++;
if(mon==13)
{mon=0;year++;
write_add(1,year3);
}
write_add(2,mon);
}
write_add(3,day);
}
else //非閏年
{
if(day==table2[mon]+1)
{day=0;mon++;
if(mon==13)
{mon=0;year++;
write_add(1,year3);
}
write_add(2,mon);
}
write_add(1,day);
}
}
write_add(4,hh);//數據改變立即存入24C02
display(read_add(4),read_add(5),read_add(6));
}
write_add(5,mm);//數據改變立即存入24C02
display(read_add(4),read_add(5),read_add(6));
}
write_add(6,ss);//數據改變立即存入24C02
display(read_add(4),read_add(5),read_add(6));
}
}
|