当前位置:文档之家› ds1302定时钟程序

ds1302定时钟程序

#include
#define uchar unsigned char
#define uint unsigned int
sbit beep=P1^5; //蜂鸣器位定义
sbit SCK=P1^6; //DS1302相关操作线定义
sbit SDA=P3^5;
sbit RST=P1^7;
sbit key1=P1^0; //按键定义,key1切换键,key2加,key3减,key4闹钟,年月日周
sbit key2=P1^1;
sbit key3=P1^2;
sbit key4=P1^3;
sbit mm=P1^4;
uchar i,j,mod,flag,flag1=1,s=7; //控制定时器动态扫描数码管的第几位,j是定时读取时间。mod是对key1按下次数计数。flag切换闹钟,日期,和周.flag1为闹钟标志位
//uchar code write_addr[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 写地址
//uchar code read_addr[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分时日月周年 读地址
uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //共阴数码管码表,表示0-9和-。-表示时分秒的间隔.
uchar disbuf[8]={0x06,0x06,0x40,0x06,0x5b,0x40,0x3f,0x07}; //显示缓冲区,初始化的时候为11-7-23。
struct time //定义时间日期的结构类型
{
uchar second;
uchar minute;
uchar hour;
uchar week;
uchar day;
uchar month;
uchar year;
}current_time;
#define ctime current_time
uchar asec,amin,ahour; //定义闹钟的时分秒变量


void delay(uint ms)
{
uchar i;
while(ms--)
for(i=110;i>0;i--);
}


void di() //滴一声,用来按键伴音,因为我的开发板上的是无源的蜂鸣器,所以响起了不太容易
{
uchar i;
for(i=0;i<40;i++)
{
beep=0;
delay(1);
beep=1;
delay(1);
}
}


void didi() //滴滴,连续响两下。用来闹钟提醒。
{
uchar i;
for(i=2;i>0;i--)
{
di();
delay(140);
}
}


void write(uchar addr,uchar dat) //DS1302的写驱动,传入参数为一个地址和数据
{
uchar i;
RST=0;
SCK=0;
RST=1;
for(i=0;i<8;i++)
{
SCK=0;
SDA=(bit)(addr&0x01);
addr>>=1;
SCK=1;
}
for(i=0;i<8;i++)
{
SCK=0;
SDA=(bit)(dat&0x01);
dat>>=1;
SCK=1;
}
RST=0;
}



uchar read(uchar addr) //DS1302的读驱动,传入参数为一个地址,返回参数为读到的数据
{
uchar i,dat;
RST=0;
SCK=0;
RST=1;
for(i=0;i<8;i++)
{
SCK=0;
SDA=(bit)(addr&0x01);
addr>>=1;
SCK=1;
}
for(i=0;i<8;i++)
{
SCK=0;
dat>>=1;
if(SDA)
dat|=0x80;
SCK=1;
}

RST=0;
dat=(dat/16*10)+(dat&0x0f);
return(dat);
}



void read_time() //读取DS1302的时间和日期
{
ctime.second=read(0x81);
ctime.minute=read(0x83);
ctime.hour=read(0x85);
ctime.day=read(0x87);
ctime.month=read(0x89);
ctime.week=read(0x8b);
ctime.year=read(0x8d);
}



void set_time() //设定时间和日期
{
if(!flag)
{
write(0x8e,0x00);
write(0x80,((ctime.second/10)<<4|(ctime.second%10)));
write(0x82,((ctime.minute/10)<<4|(ctime.minute%10)));
write(0x84,((ctime.hour/10)<<4|(ctime.hour%10)));
write(0x8e,0x80);
}
else
{
write(0x8e,0x00);
write(0x86,

((ctime.day/10)<<4|(ctime.day%10)));
write(0x88,((ctime.month/10)<<4|(ctime.month%10)));
write(0x8a,((ctime.week/10)<<4|(ctime.week%10)));
write(0x8c,((ctime.year/10)<<4|(ctime.year%10)));
write(0x8e,0x80);
}
flag1=1;
}


void refbuf() //刷新显示缓冲区
{
switch(flag)
{
case 1:
disbuf[0]=table[ctime.day%10];
disbuf[1]=table[ctime.day/10];
disbuf[2]=0x40;
disbuf[3]=table[ctime.month%10];
disbuf[4]=table[ctime.month/10];
disbuf[5]=0x40;
disbuf[6]=table[ctime.year%10];
disbuf[7]=table[ctime.year/10];
break;
case 2:
disbuf[0]=table[ctime.week];
disbuf[1]=0x06;
disbuf[2]=0x40;
disbuf[3]=0x40;
disbuf[4]=0x40;
disbuf[5]=0x40;
disbuf[6]=0x40;
disbuf[7]=0x40;
break;
case 3:
disbuf[0]=table[asec%10];
disbuf[1]=table[asec/10];
disbuf[2]=0x40;
disbuf[3]=table[amin%10];
disbuf[4]=table[amin/10];
disbuf[5]=0x40;
disbuf[6]=table[ahour%10];
disbuf[7]=table[ahour/10];
break;
default:
disbuf[0]=table[ctime.second%10];
disbuf[1]=table[ctime.second/10];
disbuf[2]=0x40;
disbuf[3]=table[ctime.minute%10];
disbuf[4]=table[ctime.minute/10];
disbuf[5]=0x40;
disbuf[6]=table[ctime.hour%10];
disbuf[7]=table[ctime.hour/10];
}
}



void keyscan() //键盘扫描
{
if(key1==0)
{
delay(5);
if(key1==0)
{
while(!key1); //key1用来调节时间和日期、闹钟
mod++; //mod标示调节时间的时候对应的闪烁位,mod=1秒位或天或闹钟的秒,mod=2是分位,mod=3是小时位,
di();
if(mod==4) //退出调节功能,返回正常显示
{
set_time();
mod=0;
}
}
}
if(key2==0) //调节加1,因为涉及到时分秒,年月日周和闹钟的调节,所以写的比较复杂,应该有更精简的代码。
{
delay(5);
if(key2==0)
{
while(!key2);
di();
switch(mod)
{
case 1:ctime.second++;
if(ctime.second==60)
ctime.second=0;
break;
case 2:ctime.minute++;
if(ctime.minute==60)
ctime.minute=0;
break;
case 3:ctime.hour++;
if(ctime.hour==24)
ctime.hour=0;
break;
}
if(flag==1) //flag=0时默认调节时分秒,=1时调节年月日,=2时调节周,=3时调节闹钟,=4时就返回正常显示,flag又key4来控制。
{
switch(mod)
{
case 1:ctime.day++;
if(ctime.day==32)
ctime.day=0;
break;
case 2:ctime.month++;
if(ctime.month==13)
ctime.month=0;
break;
case 3:ctime.year++;
if(ctime.year==100)
ctime.year=0;
break;
}
}
if(flag==2)
{
if(mod==1)
{
ctime.week++;
if(ctime.week==8)
ctime.week=1;
}
}
if(flag==3)
{
switch(mod)
{
case 1:asec++;
if(asec==60)
asec=0;

break;
case 2:amin++;
if(amin==60)
amin=0;
break;
case 3:ahour++;
if(ahour==24)
ahour=0;
break;
}
}
}
}
if(key3==0) //调节减1,功能与key2相似。
{
delay(5);
if(key3==0)
{
while(!key3);
di();
switch(mod)
{
case 1:if(ctime.second==0)
ctime.second=60;
ctime.second--;
break;
case 2:if(ctime.minute==0)
ctime.minute=60;
ctime.minute--;
break;
case 3:if(ctime.hour==0)
ctime.hour=24;
ctime.hour--;
break;
}
if(flag==1)
{
switch(mod)
{
case 1:if(ctime.day==0)
ctime.day=32;
ctime.day--;
break;
case 2:if(ctime.month==0)
ctime.month=13;
ctime.month--;
break;
case 3:if(ctime.year==0)
ctime.year=100;
ctime.year--;
break;
}
}
if(flag==2)
{
if(mod==1)
{
if(ctime.week==1)
ctime.week=8;
ctime.week--;
}
}
if(flag==3)
{
switch(mod)
{
case 1:if(asec==0)
asec=60;
asec--;
break;
case 2:if(amin==0)
amin=60;
amin--;
break;
case 3:if(ahour==0)
ahour=24;
ahour--;
break;
}
}
}
}
if(key4==0)
{
delay(5);
if(key4==0)
{
while(!key4);
di();
flag++;
if(flag==4)
{
flag=0;
flag1=1;
}
}
}
}




void init() //初始化,定时器定时2ms用来动态扫描数码管显示
{
TMOD=0X01;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TR0=1;
EA=1;
ET0=1;
/*write(0x8e,0x00); //第一次写DS1302芯片,不然开始显示乱码,只需要初始化一次就行了,以后就屏蔽掉
write(0x80,0X10);
write(0x82,0X10);
write(0x84,0X10);
write(0x86,0x23);
write(0x88,0x07);
write(0x8a,0x06);
write(0x8c,0x11);
write(0x8e,0x80);*/
read_time(); //每次初始化的时候都读取时钟芯片的时间,用来显示。
}




void main()
{

mm=0;
init();
while(1)
{
keyscan();
if(amin==ctime.minute&&ahour==ctime.hour&&flag1) //闹钟判断,默认响1min,同时按下key2和key3关掉闹钟
{
didi();
if((key2==0)&&(key3==0))
{
delay(5);
if((key2==0)&&(key3==0))
flag1=0;
}
}
}
}




void time0() interrupt 1
{
TH0=(65536-3000)/256;
TL0=(65536-3000)%256;
if(i==8)
{
s=7;
i=0;
j++;
}
if(mod|flag) //实现调节是闪烁的效果
{
if(j==10)
{
switch(mod)
{
case 1:disbuf[0]=0xff;disbuf[1]=0xff;break;
case 2:disbuf[3]=0xff;disbuf[4]=0xff;break;
case 3:disbuf[6]=0xff;disbuf[7]=0xff;break;
}
}
}
P2=s;
P0=disbuf[i];
s--;
i++;
if(j==20) //3msx8x20,大约480ms从DS1302芯片读取一

下时间
{
j=0;
refbuf();
if(mod==0)
read_time();
}


}


相关主题
文本预览
相关文档 最新文档