- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int//蜂鸣器位定义
- sbit beep = P3^3 ;//DS1302相关操作线定义
- sbit RST = P1^1 ;
- sbit SCK = P1^2 ;
- sbit SDA = P1^3 ; //按键定义,key1切换键,key2加,key3减,key4闹钟,年月日周
- sbit key1 = P1^4 ;
- sbit key2 = P1^5 ;
- sbit key3 = P1^6 ;
- sbit key4 = P1^7 ;
- uchar i,j,mod,flag,flag1=1 ;//控制定时器动态扫描数码管的第几位,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}; //秒分时日月周年 读地址
- //共阳数码管码表,表示0-9和-。-表示时分秒的间隔.
- uchar code LED[11] =
- {
- 0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,
- };
- uchar disbuf[8] =
- {
- 0x62,0xa2,0xf7,0x7a,0x28,0xf7,0x7e,0x7e
- };//定义时间日期的结构类型
- 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=135;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);
- }
- }//DS1302的写驱动,传入参数为一个地址和数据
- void write(uchar addr,uchar dat)
- {
- 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 ;
- }
- //DS1302的读驱动,传入参数为一个地址,返回参数为读到的数据
- uchar read(uchar addr)
- {
- 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 ;
- }
- //读取DS1302的时间和日期
- void read_time()
- {
- 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] = LED[ctime.day%10];
- disbuf[1] = LED[ctime.day/10];
- disbuf[2] = 0xbf ; //10111111 -
- disbuf[3] = LED[ctime.month%10];
- disbuf[4] = LED[ctime.month/10];
- disbuf[5] = 0xbf ;
- disbuf[6] = LED[ctime.year%10];
- disbuf[7] = LED[ctime.year/10];
- break ;
- /*case 2 :
- disbuf[0] = 0xbf ;
- disbuf[1] = 0xbf ;
- disbuf[2] = 0xbf ;
- disbuf[3] = 0xbf ;
- disbuf[4] = LED[ctime.week] ;
- disbuf[5] = 0xbf ;
- disbuf[6] = 0xbf ;
- disbuf[7] = 0xbf ;
- break ;*/
- case 2 :
- disbuf[0] = LED[asec%10];
- disbuf[1] = LED[asec/10];
- disbuf[2] = 0xbf;
- disbuf[3] = LED[amin%10];
- disbuf[4] = LED[amin/10];
- disbuf[5] = 0xbf;
- disbuf[6] = LED[ahour%10];
- disbuf[7] = LED[ahour/10];
- break ;
- default :
- disbuf[0] = LED[ctime.second%10];
- disbuf[1] = LED[ctime.second/10];
- disbuf[2] = 0xbf;
- disbuf[3] = LED[ctime.minute%10];
- disbuf[4] = LED[ctime.minute/10];
- disbuf[5] = 0xbf;
- disbuf[6] = LED[ctime.hour%10];
- disbuf[7] = LED[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 ;
- }
- }
- } //调节加1,因为涉及到时分秒,年月日周和闹钟的调节,所以写的比较复杂,应该有更精简的代码。
- if(key2==0)
- {
- 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 ;
- } //flag=0时默认调节时分秒,=1时调节年月日,=2时调节周,=3时调节闹钟,=4时就返回正常显示,flag又key4来控制。
- if(flag==1)
- {
- 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==2)
- {
- 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 ;
- }
- }
- }
- }//调节减1,功能与key2相似。
- if(key3==0)
- {
- 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==2)
- {
- 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==3)
- {
- flag=0 ;
- flag1=1 ; //KEY4按一次显示日期,按2次显示闹钟
- }
- }
- }
- }
- //初始化,定时器定时3ms用来动态扫描数码管显示
- void init()
- {
- TMOD = 0X01 ;
- TH0 = (65536-3000)/256 ;
- TL0 = (65536-3000)%256 ;
- TR0 = 1 ;
- ET0 = 1 ;
- EA = 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()
- {
- init();
- while(1)
- {
- keyscan();
- //闹钟判断,默认响1min,同时按下key2和key3关掉闹钟
- if(amin==ctime.minute&&ahour==ctime.hour&&flag1)
- {
- 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)
- {
- 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=~(0x80>>i);
- P0=disbuf[i];
- i++;
- //3msx8x20,大约480ms从DS1302芯片读取一下时间
- if(j==20)
- {
- j=0 ;
- refbuf();
- if(mod==0)
- read_time();
- }
- }
复制代码 |