万年历制作原理图和代码分享给大家,本人是一个机械出生,自己喜欢搞电子分享给大家,希望大家做自己的个性时钟吧。
怕大家误会时间不准,本只做用了ds1302,三个电容断电记忆5个小时保持没问题,
日期和礼拜不需要再编程的
#include<stc.h>
#define uchar unsigned char
#define uint unsigned int
#define write_second 0x80
#define write_minute 0x82
#define write_hour 0x84
#define write_tian 0x86
#define write_yue 0x88
#define write_nian 0x8c
#define write_zhou 0x8a
#define read_miao 0x81
#define read_fen 0x83
#define read_xiaoshi 0x85
#define read_tian 0x87
#define read_yue 0x89
#define read_nian 0x8d
#define read_zhou 0x8b
#define write_protect 0x8e
sbit rst=P2^2;
sbit sclk=P2^1;
sbit io=P2^0;
sbit change=P2^6;
sbit set=P2^7;
sbit shi=P2^5;
sbit fen=P2^4;
sbit miao=P2^3;
sbit sh=P3^2;
sbit ds=P3^3;
sbit st=P3^4;
sbit sh1=P3^5;
sbit ds1=P3^6;
sbit st1=P3^7;
uchar temp=0;
uchar count,bian;
uchar hou,miu,sec,nian,yue,ri,xinqi,zhou;
uchar g,s,b,q,w,sw;
uchar g1,s1,b1,q1,w1,sw1;
unsigned char code numtab[16]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0xbf};
uchar code wx[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
//74hc595驱动函数
dr_595(unsigned char dat)
{
unsigned char temp1;
st=0;
for(temp1=0;temp1<8;temp1++)
{
sh=0;
dat=dat<<1;
ds=CY;
sh=1;
sh=0;
}
st=1;
st=0;
}
dr_595_1(unsigned char dat)
{
unsigned char temp1;
st1=0;
for(temp1=0;temp1<8;temp1++)
{
sh1=0;
dat=dat<<1;
ds1=CY;
sh1=1;
sh1=0;
}
st1=1;
st1=0;
}
//写8位字符串数据
void DS1302_Write(uchar D)
{
uchar i;
for(i=0;i<8;i++)
{
io=D&0x01;
sclk=1;
sclk=0;
D=D>>1;
}
}
//写地址和数据
void WDS1302(uchar ucAddr, uchar ucDat)
{
rst = 0;
sclk = 0;
rst = 1;
DS1302_Write(ucAddr);
DS1302_Write(ucDat);
sclk = 1;
rst = 0;
}
//读一串数据
uchar DS1302_Read()
{
uchar TempDat=0,i;
for(i=0;i<8;i++)
{
TempDat>>=1;
if(io) TempDat=TempDat|0x80;
sclk=1;
sclk=0;
}
return TempDat;
}
//写地址然后读数据
uchar read1302(uchar ucAddr)
{
uchar ucDat;
rst = 0;
sclk = 0;
rst = 1;
DS1302_Write(ucAddr);
ucDat=DS1302_Read();
sclk = 1;
rst = 0;
return ucDat;
}
//////////////////////////////////////////////////////////
void init()
{
WDS1302(0x8e,0x00);//关闭保护寄存器
WDS1302(0x80,0x58);//秒
WDS1302(0x82,0x30);//分
WDS1302(0x84,0x12);//时
WDS1302(0x8A,0x07);//星期
WDS1302(0x86,0x16);//日
WDS1302(0x88,0x07);//月
WDS1302(0x8C,0x14);//年
WDS1302(0x90,0xa5);//充电
WDS1302(0x8e,0x80);//开保护
}
void InitTimer0(void)
{
TMOD = 0x01;
TL0 = 0x91; //设置定时初值
TH0 = 0xFF; //设置定时初值
EA = 1;
ET0 = 1;
TR0 = 1;
}
chuli_t()
{
sec=read1302(read_miao);
miu=read1302(read_fen);
hou=read1302(read_xiaoshi);
nian=read1302(read_nian);
yue=read1302(read_yue);
ri=read1302(read_tian);
zhou=read1302(read_zhou);
g=sec%16;
g1=zhou%16;
s=sec/16;
//s1=ri/16;
b=miu%16;
b1=ri%16;
q=miu/16;
q1=ri/16;
w=hou%16;
w1=yue%16;
sw=hou/16;
sw1=yue/16;
}
chuli_n()
{
sec=read1302(read_miao);
miu=read1302(read_fen);
hou=read1302(read_xiaoshi);
nian=read1302(read_nian);
yue=read1302(read_yue);
ri=read1302(read_tian);
zhou=read1302(read_zhou);
g=sec%16;
g1=ri%16;
s=sec/16;
s1=ri/16;
b=miu%16;
b1=yue%16;
q=miu/16;
q1=yue/16;
w=hou%16;
w1=nian%16;
sw=hou/16;
sw1=nian/16;
}
void Delay100us() //@16MHz
{
unsigned char i, j;
i = 10;
j = 83;
do
{
while (--j);
} while (--i);
}
void main(void)
{
InitTimer0();
xinqi=0;
while(change==0)init();
while(1)
{
xinqi=0;
chuli_t();
while(change==0)
{
chuli_t();
WDS1302(0x8e,0x00);
if(miao==0)
{
count=read1302(read_miao)%16+read1302(read_miao)/16*10;
while(miao==0);
Delay100us();
count++;
if(count==60)
count=0;
bian=count%10+count/10*16;
WDS1302(write_second,bian);
}
else if(fen==0)
{
count=read1302(read_fen)%16+read1302(read_fen)/16*10;
while(fen==0); Delay100us();
count++;
if(count==60)
count=0;
bian=count%10+count/10*16;
WDS1302(write_minute,bian);
}
else if(shi==0)
{
count=read1302(read_xiaoshi)%16+read1302(read_xiaoshi)/16*10;
while(shi==0); Delay100us();
count++;
if(count==24)
count=0;
bian=count%10+count/10*16;
WDS1302(write_hour,bian);
}
chuli_t();
WDS1302(0x8e,0x80);
}
while(shi==0)
{
chuli_t();
WDS1302(0x8e,0x00);
if(miao==0)
{
count=read1302(read_zhou)%16+read1302(read_zhou)/16*10;
while(miao==0);
Delay100us();
count++;
if(count==8)
count=1;
bian=count%10+count/10*16;
WDS1302(write_zhou,bian);
}
WDS1302(0x8e,0x80);
}
while(set==0)
{ xinqi=1;
chuli_n();
WDS1302(0x8e,0x00);
if(miao==0)
{
count=read1302(read_tian)%16+read1302(read_tian)/16*10;
while(miao==0); Delay100us();
count++;
if(count==32)
count=1;
bian=count%10+count/10*16;
WDS1302(write_tian,bian);
}
else if(fen==0)
{
count=read1302(read_yue)%16+read1302(read_yue)/16*10;
if(fen==0)
{
while(fen==0); Delay100us();
count++;
if(count==13)
count=1;
bian=count%10+count/10*16;
WDS1302(write_yue,bian);
miu=read1302(read_yue);
}
}
else if(shi==0)
{
count=read1302(read_nian)%16+read1302(read_nian)/16*10;
if(shi==0)
{
while(shi==0); Delay100us();
count++;
if(count==21)
count=14;
bian=count%10+count/10*16;
WDS1302(write_nian,bian);
}
}
WDS1302(0x8e,0x80);
}
}
}
void Timer0Interrupt(void) interrupt 1
{
TL0 = 0x91; //设置定时初值
TH0 = 0xFF; //设置定时初值
temp++;
if(temp==8)temp=0;
switch(temp)
{
case 0:P0=0xff;
dr_595(numtab[g]);
if(xinqi==1)
dr_595_1(numtab[g1]);
else dr_595_1(numtab[g1]);
P0=wx[7];
break;
case 1:P0=0xff;
dr_595(numtab[s]);
if(xinqi==1)
{
dr_595_1(numtab[s1]);
}
else dr_595_1(0xff);
P0=wx[6];
break;
case 2:P0=0xff;
dr_595(0xbf);
if(xinqi==1)
dr_595_1(0xbf);
else dr_595_1(0xff);
P0=wx[5];
break; //第6位显示横码
case 3:P0=0xff;
dr_595(numtab
); dr_595_1(numtab[b1]); P0=wx[4]; break; case 4:P0=0xff; dr_595(numtab[q]); dr_595_1(numtab[q1]); P0=wx[3]; break; case 5:P0=0xff; dr_595(0xbf); dr_595_1(0xbf); P0=wx[2]; break; //第三位显示横码 case 6:P0=0xff; dr_595(numtab[w]); dr_595_1(numtab[w1]); P0=wx[1]; break; case 7:P0=0xff; dr_595(numtab[sw]); dr_595_1(numtab[sw1]); P0=wx[0]; break; } }
[ 此帖被sworderchina在2015-03-12 20:50重新编辑 ]