i黑马网:89s52+ds1302电子钟
来源:百度文库 编辑:中财网 时间:2024/03/29 06:54:21
/*===================================
/--------------------------------------
项目名称:89s52+ds1302电子钟
功能说明:6位数码管显示-时--分--秒,约30秒钟。然后显示星期--月--年约10秒钟
设置说明:
P0--段,P2--位(p2.5为个位),自带充电功能(470UF电容作为电源)
作者:朱世民
说明:通过实验板验证通过
时间:2010.2.11
==========================================*/
#include "reg51.h"
#include "ds1302.h" //自建库文件
//unsigned char code tab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
// 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E};
//0~~9段码 abcdefgh,共阳
unsigned char code tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
0x7F,0x6F,0x77,0x7C,0x39,0x80,0x79,0xC0};
// 师大版显示代码
/*************************ds1302与at89s52引脚连接********************/
sbit k1=P1^0; //调时分秒按键(移位)
sbit k2=P1^1; //加1按键
sbit k3=P1^3; //调星期,月,日,按键(移位)
sbit k4=P1^4; //加1按键
sbit flag=P3^1; //秒显标志(板上接p3.1)
unsigned char k,ks;
unsigned char time[6]; //秒,分,时寄存器初始值
/***********************显示程序**********************************************/
/* 动态扫描条件(单个LED在1秒内): count >=50次 //点亮次数 */
/* */
/* DS1302秒,分,时寄存器是BCD码形式: 用16求商和余进行"高4位"和"低4位"分离 */
/* 0xdf,0xef,0xf7,0xfb,0xfd,0xfe : 位选 */
/****************************************************************************/
void disp()//
{ unsigned char m; //m为缓冲;
m=time[0]; //把
P0=tab[m%16]; //取秒低4位BCD码
P2=0xdf; //显示秒(个位);
delay(500); //持续2ms
P2=0xff; //消影
P0=tab[m/16]; //取高4位BCD码:显示秒(十位);
P2=0xef;
delay(500);
P2=0xff;
m=time[1]; //把分--送缓存
P0=tab[m%16]; //第3个数码管:显示分(个位)
P2=0xf7;
delay(500);
P2=0xff;
P0=tab[m/16]; //第4个数码管:显示分(十位)
P2=0xfb;
delay(500);
P2=0xff;
m=time[2]; //把时--送缓存
P0=tab[m%16]; //第5个数码管:显示时(个位)
P2=0xfd;
delay(500);
P2=0xff;
P0=tab[m/16]; //第6个数码管:显示时(十位)
P2=0xfe;
delay(500);
P2=0xff;
}
//==============
//显示星期---月---日
void disp2()
{ unsigned char m; //m为缓冲;
m=time[3]; //把日
P0=tab[m%16]; //取秒低4位BCD码
P2=0xdf; //显示秒(个位);
delay(500); //持续2ms
P2=0xff; //消影
P0=tab[m/16]; //取高4位BCD码:显示秒(十位);
P2=0xef;
delay(500);
P2=0xff;
m=time[4]; //把月--送缓存
P0=tab[m%16]; //第3个数码管:显示分(个位)
P2=0xf7;
delay(500);
P2=0xff;
m=m/16;
if(m==0) m=13;//若十位为0,关闭显示 0x80
P0=tab[m]; //第4个数码管:显示分(十位)
P2=0xfb;
delay(500);
P2=0xff;
m=time[5]; //把星期--送缓存
P0=tab[15]; //第5个数码管:显示时(个位)
P2=0xfd;
delay(500);
P2=0xff;
P0=tab[m%16]; //第6个数码管:显示时(十位)
P2=0xfe;
delay(500);
P2=0xff;
}
//========初始化
void Write_time()
{ unsigned char i,addr;
addr=0x80;
write_1302(0x8e,0x00); //WP=0 写操作
for(i=0;i<6;i++)
{
write_1302(addr,time[i]);
addr+=2;
}
write_1302(0x8e,0x80); //WP=1 写保护
}
//===================================
void testk1()
{k1=1;
if(!k1)//
{disp();//延时去抖
if(!k1)//
{while(!k1)disp();//等待松开
if(++k>6)k=0; //移位标志,只调
}
}
}
//=======加一键=================
void testk2()
{ unsigned char n,buf;
k2=1;
if(!k2)
{disp();disp();disp();
if(!k2)
do //按键没有松开,连续加
{disp();disp();disp();
switch(k)
{case 6:buf=time[0];//
buf&=0xf0; //保留高四位;
if(++n>9)n=0; //加数
time[0]=buf|n;break;//秒的个wei加一
case 5:buf=time[0]; buf&=0x0f; if(++n>5)n=0; time[0]=buf+n*16;break;//分的十位加1
case 4:buf=time[1]; buf&=0xf0; if(++n>9)n=0; time[1]=buf|n;break;//分的个wei加一
case 3:buf=time[1]; buf&=0x0f; if(++n>5)n=0; time[1]=buf+n*16;break;//分的十位加1
case 2:buf=time[2];buf&=0xf0; if(++n>9)n=0; time[2]=buf|n;break;//时的个位加一
case 1:buf=time[2];buf&=0x0f; if(++n>2)n=0; time[2]=buf+n*16; break;//
//时十位加1
default:break;
}
disp();disp();disp();
}
while(!k2);//直到按键松开
Write_time(); //写进1302去
}
}
//==========
void testk3()
{k3=1;
if(!k3)//
{disp2();//延时去抖
if(!k3)//
{while(!k3)disp2();//等待松开
if(++ks>5)ks=0; //移位标志,只调
}
}
}
//=======加一键=================
void testk4()
{ unsigned char n,buf;
k4=1;
if(!k4)
{disp2();disp2();
if(!k4)
do //按键没有松开,连续加
{disp2();disp2();disp2();
switch(ks)
{case 5:buf=time[3];//
buf&=0xf0; //保留高四位;
if(++n>9)n=0; //加数
time[3]=buf|n;break;//秒的个wei加一
case 4:buf=time[3]; buf&=0x0f; if(++n>3)n=0; time[3]=buf+n*16;break;//分的十位加1
case 3:buf=time[4]; buf&=0xf0; if(++n>9)n=0; time[4]=buf|n;break;//分的个wei加一
case 2:buf=time[4]; buf&=0x0f; if(++n>1)n=0; time[4]=buf+n*16;break;//分的十位加1
case 1:buf=time[5];buf&=0xf0; if(++n>7)n=1; time[5]=buf|n;break;//时的个位加一
//时十位加1
default:break;
}
disp2();disp2();
}
while(!k4);//直到按键松开
Write_time(); //写进1302去
}
}
/************************主程序**********************************************/
void main(void)
{ unsigned char i,addr,s,n;
k=0,ks=0;
write_1302(0x8e,0x00); //WP=0 写操作
write_1302(0x90,0xa5); // 开涓流充电
write_1302(0x8e,0x80); //WP=1 写保护
write_1302(0x80,0x00);
while(1)
{
testk1(); //调时移位键k=1,2,3,4分别分个、十,时个,十
while(k!=0) //若进入调节
{ testk2();disp();testk1(); }//调时间
{ //否则取数,显示
for(n=0;n<100;n++)
{ addr=0x81;
for(i=0;i<3;i++)
{
time[i]=read_1302(addr);// 读出时间
disp(); //星期,月,日
addr+=2;//地址加2
}
if(time[0]!=s) // 读出秒,和上次比较不等
{flag=!flag;//秒闪指示(变化一次闪一次)
s=time[0]; // 将秒的值送入缓存,以便下次比较,取出跳变
}
}
}
testk3(); //调时移位键k=1,2,3,4分别调节星期,月,日
while(ks!=0) //若进入调节星期,月,日
{ testk4();disp2();testk3(); }//进入调节
{ addr=0x87;
for(i=3;i<6;i++)
{
time[i]=read_1302(addr);// 读出星期,月,日
addr+=2;//地址加2
}
for(n=0;n<80;n++) disp2();//显示星期,月,日
}
}
}