DS1302数字时钟设计.docx
《DS1302数字时钟设计.docx》由会员分享,可在线阅读,更多相关《DS1302数字时钟设计.docx(17页珍藏版)》请在冰豆网上搜索。
![DS1302数字时钟设计.docx](https://file1.bdocx.com/fileroot1/2023-1/10/875c5ca5-73de-4d1e-9ce4-87885eb41500/875c5ca5-73de-4d1e-9ce4-87885eb415001.gif)
DS1302数字时钟设计
DS1302数字时钟设计
本次万年历设计基于AT89C52单片机微控器、DS1302时钟芯片、DS18b20温度传感器、1602液晶,仅用4个按键实现调时、定时功能。
下面介绍本次设计仿真操作过程:
S1命名为“调时”;S2命名为“+”;S3命名为“-”;S3命名为“闹钟”
功能实现:
仿真开始后,液晶屏显示2012/03/24620:
25:
0026C并开始走。
(注:
6表示周六,由于℃为特殊字符,1602液晶暂不支持显示,故用C代替)。
调时功能:
按一下S1进入调时间模式,秒清零,同时分位闪烁约两下,提示按下S2或S3时,调节分,根据需要按S2或S3调到所需的分钟时刻,再按一下S1,时位闪烁约两下,提示按下S2或S3时,调节时,根据需要按S2或S3调到所需的小时时刻,再按一下S1,周位闪烁约两下,提示按下S2或S3时,调节周,根据需要按S2或S3调到所需的周时刻,再按一下S1,日位闪烁约两下,提示按下S2或S3时,调节日,根据需要按S2或S3调到所需的日时刻,再按一下S1,月位闪烁约两下,提示按下S2或S3时,调节月,根据需要按S2或S3调到所需的月时刻,再按一下S1,年位闪烁约两下,提示按下S2或S3时,调节年,根据需要按S2或S3调到所需的年时刻(注:
程序设定年范围为2000-2050),再按一下S1会看到,时间会按照设定好的新时间走下去
定时功能:
按一下S4进入定时模式,显示的时间停止,(DS1302仍在工作,只不过其时间没有显示出来),同上,再按S1和S2或S3进行定时时间的设定,设定好后,再按一下S4(表示确认设定的时间),时间会按原来的时间走,当到达设定的时间后,LED灯闪烁,再按一下S4,LED灯停止闪烁,时间会照常进行。
按DS18B20的上升、下降箭头,来调节温度,液晶上会动态的显示出来;
注:
本次设计虽然经过反复调试,但仍有不尽人意之处,例如:
误操作考虑的比较少等,但只要大家按照上面的严格操作,就可以实现调时、定时功能,谢谢大家。
。
。
附:
源程序:
#include"reg52.h"
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitdq=P2^2;
sbitsclk=P1^0;
sbitio=P1^1;
sbitrst=P1^2;
sbitbee=P2^3;
sbitdula=P2^6;
sbitwela=P2^7;
sbitkey1=P3^0;//S1
sbitkey2=P3^1;//S2
sbitkey3=P3^2;//S3
sbitkey4=P3^3;//S4
sbitlcden=P3^4;
sbitrs=P3^5;
sbitrd=P3^7;
sbitACC_0=ACC^0;
sbitACC_7=ACC^7;
uchartemp;
ucharcodetable0[]="0123456789";
ucharcodetable1[]="20/:
";
charflag,flag1,flag2,num,miao,fen,shi,zhou,ri,yue,nian,dfen,dshi;
ucharcodetime[]={0x12,0x03,0x24,0x06,0x20,0x25,0x00};
voidwrite_com(uchar);
voidwrite_date(uchar);
voidwrite_byte(uchar);
voidwrite_ds1302(uchar,uchar);
ucharread_ds1302(uchar);
voidinit();
voiddisplay_time();
voidread_time();
voidtiaoshi();
voiddelay(uint);
voidinit_b20();
voiddelay_us(uint);
ucharread_byte();
voidwrite_byte_b20(uchar);
ucharread_temp();
voidmain()
{
init();
init_b20();
while
(1)
{
temp=read_temp();
tiaoshi();
read_time();
display_time();
if((dshi==shi)&&(dfen==fen))
{
while(flag1==2)
{
bee=~bee;
tiaoshi();
read_time();
display_time();
delay(100);
}
bee=1;
}
}
}
charzhuan_date1(charaa)
{
ucharbb;
bb=16*(aa/10)+aa%10;
returnbb;
}
voidwrite_xintime()
{
write_ds1302(0x8e,0x00);
write_ds1302(0x8c,zhuan_date1(nian));//年
write_ds1302(0x88,zhuan_date1(yue));//月
write_ds1302(0x86,zhuan_date1(ri));//日
write_ds1302(0x8A,zhuan_date1(zhou));//星期
write_ds1302(0x84,zhuan_date1(shi));//时
write_ds1302(0x82,zhuan_date1(fen));//分
write_ds1302(0x80,zhuan_date1(miao));//秒
write_ds1302(0x8e,0x80);
}
voidtiaoshi()
{
if(key1==0)
{
if(key1==0)
{
while(!
key1)
{
write_com(0x0c);
}
flag=1;//进入调时模式下,时间不再走的标志
flag2=1;//调时间键按下的标志,防止误操作,+、-引起时间变化
num++;
//if(num==8)
//num=0;
switch(num)
{
case1:
{
miao=0;
write_com(0x80+0x47);
write_com(0x0d);//秒清零显示分的位置闪烁
delay(1200);
}break;
case2:
{
write_com(0x80+0x44);
write_com(0x0d);//时的位置闪烁
delay(1200);
}break;
case3:
{
write_com(0x80+0x0e);
write_com(0x0d);//周的位置闪烁
delay(1200);
}break;
case4:
{
write_com(0x80+0x0b);
write_com(0x0d);
delay(1200);//日的位置闪烁
}break;
case5:
{
write_com(0x80+0x08);
write_com(0x0d);
delay(1200);//月的位置闪烁
}break;
case6:
{
write_com(0x80+0x05);
write_com(0x0d);
delay(1200);//年的位置闪烁
}break;
case7:
{
flag=0;
num=0;
write_xintime();
}break;//将调好的新时间写入1302
//flag清零标志可以从1302中读时间
}
}
}
if((key2==0)&&(flag2==1))
{
if((key2==0)&&(flag2==1))
{
while(!
key2)
{
write_com(0x0c);
}
flag=1;
switch(num)
{
case1:
{
miao=0;
fen++;
if(fen==60)
fen=0;
}break;
case2:
{
shi++;
if(shi==24)
shi=0;
}break;
case3:
{
zhou++;
if(zhou==8)
zhou=1;
}break;
case4:
{
ri++;
if(ri==32)
ri=1;
}break;
case5:
{
yue++;
if(yue==13)
yue=1;
}break;
case6:
{
nian++;
if(nian==51)
nian=0;
}break;
}
}
}
if((key3==0)&&(flag2==1))
{
if((key3==0)&&(flag2==1))
{
while(!
key3)
{
write_com(0x0c);
}
flag=1;
switch(num)
{
case1:
{
fen--;
if(fen==-1)
fen=59;
}break;
case2:
{
shi--;
if(shi==-1)
shi=23;
}break;
case3:
{
zhou--;
if(zhou==0)
zhou=7;
}break;
case4:
{
ri--;
if(ri==0)
ri=31;
}break;
case5:
{
yue--;
if(yue==0)
yue=12;
}break;
case6:
{
nian--;
if(nian==-1)
nian=50;
}break;
}
}
}
if(key4==0)
{
if(key4==0)
{
while(!
key4)
{
write_com(0x0c);
}
flag1++;//闹钟键按下次数的简单计数
if(flag1==1)
flag=1;//按一次闹钟键,进入设置闹钟模式,标志不在从1302中读时间
if(flag1==2)
{
flag=0;//按闹钟键两次,闹钟时间设定确认,同时时钟照原来的时间走
dshi=shi;
dfen=fen;
}
if(flag1==3)
{
flag1=0;
num=0;
}
}
}
}
voiddisplay_time()
{
write_com(0x80+0x4a);
write_date(table0[miao%10]);
write_com(0x80+0x49);
write_date(table0[miao/10]);
write_com(0x80+0x47);
write_date(table0[fen%10]);
write_com(0x80+0x46);
write_date(table0[fen/10]);
write_com(0x80+0x44);
write_date(table0[shi%10]);
write_com(0x80+0x43);
write_date(table0[shi/10]);
write_com(0x80+0x0b);
write_date(table0[ri%10]);
write_com(0x80+0x0a);
write_date(table0[ri/10]);
write_com(0x80+0x08);
write_date(table0[yue%10]);
write_com(0x80+0x07);
write_date(table0[yue/10]);
write_com(0x80+0x0e);
write_date(table0[zhou]);
write_com(0x80+0x05);
write_date(table0[nian%10]);
write_com(0x80+0x04);
write_date(table0[nian/10]);
write_com(0x80+0x4e);
write_date(table0[temp%10]);
write_com(0x80+0x4d);
write_date(table0[temp/10]);
}
charzhuan_date(charaa)
{
ucharbb;
bb=10*(aa/16)+aa%16;
returnbb;
}
voidread_time()
{
if(flag==0)
{
miao=zhuan_date(read_ds1302(0x81));//秒寄存器
fen=zhuan_date(read_ds1302(0x83));//分
shi=zhuan_date(read_ds1302(0x85));//时
zhou=zhuan_date(read_ds1302(0x8b));//星期
ri=zhuan_date(read_ds1302(0x87));//日
yue=zhuan_date(read_ds1302(0x89));//月
nian=zhuan_date(read_ds1302(0x8d));//年
}
}
voidinit()
{
uchari;
dshi=-1;
dfen=-1;
dula=0;
wela=0;
rd=0;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);//1602初始化
write_com(0x82);
for(i=0;i<2;i++)
{
write_date(table1[i]);
}
write_com(0x80+0x06);
write_date(table1[2]);
write_com(0x80+0x09);
write_date(table1[2]);
write_com(0x80+0x45);
write_date(table1[3]);
write_com(0x80+0x48);
write_date(table1[3]);
write_com(0x80+0x4f);
write_date('C');//1602显示初始化
write_ds1302(0x8e,0x00);
write_ds1302(0x8c,time[0]);//年
write_ds1302(0x88,time[1]);//月
write_ds1302(0x86,time[2]);//日
write_ds1302(0x8A,time[3]);//星期
write_ds1302(0x84,time[4]);//时
write_ds1302(0x82,time[5]);//分
write_ds1302(0x80,time[6]);//秒
write_ds1302(0x8e,0x80);
}
voidinit_b20()
{
ucharn;
dq=1;
_nop_();
dq=0;
delay_us(80);
dq=1;
delay_us(8);
n=dq;
delay_us(4);
}
ucharread_ds1302(ucharadd)
{
uchari;
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
write_byte(add);
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC_7=io;
sclk=1;
sclk=0;
}
sclk=1;
_nop_();
rst=0;
return(ACC);
}
voidwrite_ds1302(ucharadd,uchardat)
{
rst=0;
_nop_();
sclk=0;
_nop_();
rst=1;
write_byte(add);
_nop_();
write_byte(dat);
sclk=1;//置高释放总线
_nop_();
rst=0;
}
voidwrite_byte(uchardat)
{
uchari;
ACC=dat;
for(i=8;i>0;i--)
{
io=ACC_0;
sclk=1;
sclk=0;
ACC=ACC>>1;
}
}
voidwrite_com(ucharcom)
{
rs=0;
P0=com;
delay
(1);
lcden=1;
delay
(1);
lcden=0;
}
voidwrite_date(uchardate)
{
rs=1;
P0=date;
delay
(1);
lcden=1;
delay
(1);
lcden=0;
delay
(1);
}
ucharread_temp()
{
uchara,b;
init_b20();
write_byte_b20(0xcc);
write_byte_b20(0x44);
delay_us(300);
init_b20();
write_byte_b20(0xcc);
write_byte_b20(0xbe);
a=read_byte();
b=read_byte();
b<<=4;
b+=(a&0xf0)>>4;
returnb;
}
voidwrite_byte_b20(uchardate)
{
uchari;
for(i=0;i<8;i++)
{
dq=0;
dq=date&0x01;
delay_us(4);
dq=1;
date>>=1;
}
delay_us(4);
}
ucharread_byte()
{
uchari,value=0;
for(i=0;i<8;i++)
{
dq=0;
value>>=1;
dq=1;
if(dq==1)
value=value|0x80;
delay_us(4);
}
returnvalue;
}
voiddelay(uintz)//z毫秒延时函数
{
uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
voiddelay_us(uintz)//z微秒延时函数
{
while(z--);
}