- #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();
- }
- }
復制代碼 |