设计一款可显示时间、日历和闹钟的多功能数字时钟
初始化:默认为时钟状态为00—00—00,日历为20—07—02,闹钟为00—00—00。
按键功能
按键s1定义为状态切换键,可以按顺序切换时钟界面,日历界面,闹钟界面; 在设置状态下,按键s1定义为确认功能,完成设置;按键s2定义为设置键,在时钟界面下 通过该键可以进入时钟设置界面,通过该键可以切换新选择待调>整的时、分、秒,当前选择的显示单元以0.5s为间隔亮灭。在日历界面下同样做此功能 。在闹钟设置>界面下,在上述功能外增加调节闹钟持续时长功能;按键s3定义为“加”按键;按键s4定义为“减”按键;特殊说明: 按键s3,s4只在时钟设置,日历设置或者闹钟设置状态下有效。闹钟提示功能 用1KHZ的方波驱动蜂鸣器,初始持续时间为10s,可通过按键s2进行设置;闹钟提示状态下,按任意键可关闭蜂鸣器。代码:
#include <reg51.h> #include <absacc.h> sbit s1=P3^0; sbit s2=P3^1; sbit s3=P3^2; sbit s4=P3^3; sbit buzzer=P1^0; unsigned char code SMG_duanma[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};//共阳极数码管 unsigned char code SMG_position[9]={0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//位选 unsigned char yi,er,san,si,wu,liu,qi,ba; unsigned char SMGflag=1,s1_flag=1,s2_flag=1; unsigned char cnt,state=1,alarm1=0;//state:0.5s闪烁标志,alarm1:闹钟状态标志 signed char Timer[3]={0,0,0},Timer_set[3]={0,0,0};Alarm[3]={0,0,0},Calendar[3]={20,7,2},time=10;//time为闹钟时长 void Time_set(); void Rili_set(); void Alarm_set(); void delay_ms(unsigned int n) { unsigned int i=0,j=0; for(i=0;i<n;i++) for(j=0;j<123;j++); } void SMG_select(unsigned char pos,unsigned char dat) { XBYTE[0Xc000]=SMG_position[pos]; XBYTE[0Xe000]=SMG_duanma[dat]; } void SMG_control() //数码管控制 { if(SMGflag==1) Time_set(); else if(SMGflag==2) Rili_set(); else if(SMGflag==3) Alarm_set(); } void SMG_Display() { SMG_control(); SMG_select(1,yi) ;delay_ms(2); SMG_select(2,er) ;delay_ms(2); SMG_select(3,san);delay_ms(2); SMG_select(4,si) ;delay_ms(2); SMG_select(5,wu) ;delay_ms(2); SMG_select(6,liu);delay_ms(2); SMG_select(7,qi) ;delay_ms(2); SMG_select(8,ba) ;delay_ms(2); } void InitTimer()//初始化定时器 { TMOD=0X11; //定时器0,工作方式1 TH0=(65536-50000)/256;//定时50ms TL0=(65536-50000)%256; TH1=(65536-500)/256;//定时0.5ms产生1KHZ方波 TL1=(65536-500)%256; ET0=1; TR0=1; ET1=1; EA=1; PT0=1;//定时器0优先级高 } void Timer0() interrupt 1 //定时器0中断 { TH0=(65536-50000)/256;//定时50ms,装载初值 TL0=(65536-50000)%256; cnt++; if(cnt%10==0) state=!state;//0.5s闪烁一次 if(cnt==20) { cnt1=0; Timer[2]++; //秒++ if(Timer[2]==60)//60s时间到 { Timer[2]=0;//秒清零 Timer[1]++;//分++ if(Timer[1]==60)//60min时间到 { Timer[1]=0;//分清零 Timer[0]++;//时++ if(Timer[0]==24)//24小时时间到 { Timer[0]=0;//时清零 Calendar[2]++; //日++ if(Calendar[1]==1||Calendar[1]==3||Calendar[1]==5||Calendar[1]==7||Calendar[1]==8||Calendar[1]==10||Calendar[1]==12) {//大月 if(Calendar[2]==32) { Calendar[2]=1; Calendar[1]++;//月++ if(Calendar[1]==13) { Calendar[1]=1; Calendar[0]++;//年清0 if(Calendar[0]==100)Calendar[0]=0; } } } else if((Calendar[1]==4)||(Calendar[1]==6)||(Calendar[1]==9)||(Calendar[1]==11)&&(Calendar[2]==31)) {//小月 Calendar[2]=1; Calendar[1]++; if(Calendar[1]==13) { Calendar[1]=1; Calendar[0]++; if(Calendar[0]==100)Calendar[0]=0; } } else if(Calendar[0]%4==0&Calendar[0]%100!=0||Calendar[0]%400==0&Calendar[1]==2&Calendar[2]==30) {//闰二月 Calendar[2]=1; Calendar[1]++; if(Calendar[1]==13) { Calendar[1]=1; Calendar[0]++; if(Calendar[0]==100)Calendar[0]=0; } } else if(Calendar[1]==2&Calendar[2]==29) {//非闰二月 Calendar[2]=1; Calendar[1]++; if(Calendar[1]==13) { Calendar[1]=1; Calendar[0]++; if(Calendar[0]==100)Calendar[0]=0; } } } } } } } void Timer1() interrupt 3 { TH1=(65536-500)/256; TL1=(65536-500)%256; buzzer=!buzzer;//buzzer=0,蜂鸣器打开;buzzer=1,蜂鸣器关闭。 if((Timer[2]-Alarm[2])>time)//闹钟持续时长为time { alarm1=0; TR1=0; buzzer=1; } } void Time_set() //时间设置 { if(s1_flag==1)//时间设置界面 { if(s2_flag==1) //时钟开启 { //时钟状态‘-’字符1s闪烁一次 if(Timer[2]%2==0){yi=Timer[0]/10;er=Timer[0]%10;san=liu=10;si=Timer[1]/10;wu=Timer[1]%10;qi=Timer[2]/10;ba=Timer[2]%10;} else {yi=Timer[0]/10;er=Timer[0]%10;san=liu=11;si=Timer[1]/10;wu=Timer[1]%10;qi=Timer[2]/10;ba=Timer[2]%10;} } else if (s2_flag==2)//时设置,时0.5s闪烁一次 { san=liu=10;si=Timer_set[1]/10;wu=Timer_set[1]%10;qi=Timer_set[2]/10;ba=Timer_set[2]%10; if(state==1){yi=Timer_set[0]/10;er=Timer_set[0]%10;} else if(state==0) {yi=11;er=11;} //熄灭 } else if(s2_flag==3)//分设置,分0.5s闪烁一次 { yi=Timer_set[0]/10;er=Timer_set[0]%10;san=liu=10;qi=Timer_set[2]/10;ba=Timer_set[2]%10; if(state==1){si=Timer_set[1]/10;wu=Timer_set[1]%10;} else if(state==0) {si=11;wu=11;} } else if(s2_flag==4)//秒设置,秒0.5s闪烁一次 { yi=Timer_set[0]/10;er=Timer_set[0]%10;san=liu=10;si=Timer_set[1]/10;wu=Timer_set[1]%10; if(state==1){qi=Timer_set[2]/10;ba=Timer_set[2]%10;} else if(state==0) {qi=11;ba=11;} } } } void Rili_set() //日历设置 { if(s1_flag==2)//日历设置界面 { if(s2_flag==1) {yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10;qi=Calendar[2]/10;ba=Calendar[2]%10;} else if(s2_flag==2) //年设置 { san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10;qi=Calendar[2]/10;ba=Calendar[2]%10; if(state==1) {yi=Calendar[0]/10;er=Calendar[0]%10;} else {yi=11;er=11;} } else if(s2_flag==3) //月设置 { yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;qi=Calendar[2]/10;ba=Calendar[2]%10; if(state==1) {si=Calendar[1]/10;wu=Calendar[1]%10;} else {si=11;wu=11;} } else if(s2_flag==4) //日设置 { yi=Calendar[0]/10;er=Calendar[0]%10;san=liu=10;si=Calendar[1]/10;wu=Calendar[1]%10; if(state==1) {qi=Calendar[2]/10;ba=Calendar[2]%10;} else {qi=11;ba=11;} } } } void Alarm_set() //闹钟设置 { if(s1_flag==3)//闹钟设置界面 { if(s2_flag==1) {yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10;qi=Alarm[2]/10;ba=Alarm[2]%10;} else if (s2_flag==2)//时设置,时单元0.5s闪烁一次 { san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10;qi=Alarm[2]/10;ba=Alarm[2]%10; if(state==1){yi=Alarm[0]/10;er=Alarm[0]%10;} else if(state==0) {yi=11;er=11;} //熄灭 } else if(s2_flag==3)//分设置,分单元0.5s闪烁一次 { yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;qi=Alarm[2]/10;ba=Alarm[2]%10; if(state==1){si=Alarm[1]/10;wu=Alarm[1]%10;} else if(state==0) {si=11;wu=11;} } else if(s2_flag==4)//秒设置,秒单元0.5s闪烁一次 { yi=Alarm[0]/10;er=Alarm[0]%10;san=liu=10;si=Alarm[1]/10;wu=Alarm[1]%10; if(state==1){qi=Alarm[2]/10;ba=Alarm[2]%10;} else if(state==0) {qi=11;ba=11;} } else if(s2_flag==5)//闹钟时长设置界面 { yi=er=san=si=wu=liu=11;qi=time/10;ba=time%10; } } } void Alarming() //闹钟提醒模式 { if(Timer[0]==Alarm[0]&Timer[1]==Alarm[1]&Timer[2]==Alarm[2]) { alarm1=1; //闹钟标志位置1 TR1=1; //开启定时器T1 } } void keyscan()//按键扫描函数 { if(s1==0) //时钟、日历、闹钟切换 { delay_ms(10);//按键消抖 if(s1==0) { if(alarm1==0) //非闹钟提醒状态 { if(s2_flag==1)//非设置状态下,s1切换界面 { switch(s1_flag) { case 1:s1_flag=2;SMGflag=2;break;//日历界面 case 2:s1_flag=3;SMGflag=3;break;//闹钟界面 case 3:s1_flag=1;SMGflag=1;break;//时间界面 } } else if(s2_flag!=1)//设置状态下,s1为确认键 { s2_flag=1; if(s1_flag==1) {Timer[0]=Timer_set[0];Timer[1]=Timer_set[1];Timer[2]=Timer_set[2];} } } else {alarm1=0;buzzer=1;TR1=0;} //任意键关闭闹钟 } while(s1==0) SMG_Display(); //松手检测 } if(s2==0) //设置位置切换 { delay_ms(10);//按键消抖 if(s2==0) { if(alarm1==0)//非闹钟提醒状态 { if(s1_flag==1)//时间界面下 { switch(s2_flag) { case 1:s2_flag=2;break;//设置时 case 2:s2_flag=3;break;//设置分 case 3:s2_flag=4;break;//设置秒 case 4:s2_flag=2;break;//循环设置 } } else if(s1_flag==2)//日历界面下 { switch(s2_flag) { case 1:s2_flag=2;break;//设置年 case 2:s2_flag=3;break;//设置月 case 3:s2_flag=4;break;//设置日 case 4:s2_flag=2;break;//循环设置 } } else if(s1_flag==3)//闹钟界面下 { switch(s2_flag) { case 1:s2_flag=2;break;//设置时 case 2:s2_flag=3;break;//设置分 case 3:s2_flag=4;break;//设置秒 case 4:s2_flag=5;break;//设置闹钟持续时长 case 5:s2_flag=2;break;//循环设置 } } } else if(alarm1==1) {alarm1=0;buzzer=1;TR1=0;}//任意键关闭闹钟 } while(s2==0)SMG_Display();//松手检测 } if(s3==0) // s3 + { delay_ms(10);//按键消抖 if(s3==0) { if(alarm1==0) //非闹铃提醒状态 { if(s1_flag==1)//时间界面 { switch(s2_flag) { case 2:Timer_set[0]++;if(Timer_set[0]==24) Timer_set[0]=0;break;//时+ case 3:Timer_set[1]++;if(Timer_set[1]==60) Timer_set[1]=0;break;//分+ case 4:Timer_set[2]++;if(Timer_set[2]==60) Timer_set[2]=0;break;//秒+ } } else if(s1_flag==2)//日历界面 { switch(s2_flag) { case 2:Calendar[0]++;if(Calendar[0]==100) Calendar[0]=0; break;//年+ case 3:Calendar[1]++;if(Calendar[1]==13 ) Calendar[1]=1; break;//月+ case 4:Calendar[2]++;if(Calendar[2]==31 ) Calendar[2]=0; break;//日+ } } else if(s1_flag==3)//闹钟界面 { switch(s2_flag) { case 2:Alarm[0]++;if(Alarm[0]==24) Alarm[0]=0;break;//时+ case 3:Alarm[1]++;if(Alarm[1]==60) Alarm[1]=0;break;//分+ case 4:Alarm[2]++;if(Alarm[2]==60) Alarm[2]=0;break;//秒+ case 5:time++ ;if(time==61) time=0; break;//设置闹钟时长,最长为60s } } } else if(alarm1==1) {alarm1=0;buzzer=1;TR1=0;}//任意按键关闭闹钟 } while(s3==0)SMG_Display();//松手检测 } if(s4==0) // s4 - { delay_ms(10);//按键消抖 if(s4==0) { if(alarm1==0)//非闹铃提醒状态 { if(s1_flag==1)//时间界面 { switch(s2_flag) { case 2:Timer_set[0]--;if(Timer_set[0]==-1) Timer_set[0]=23;break;//时- case 3:Timer_set[1]--;if(Timer_set[1]==-1) Timer_set[1]=59;break;//分- case 4:Timer_set[2]--;if(Timer_set[2]==-1) Timer_set[2]=59;break;//秒- } } else if(s1_flag==2)//日历界面 { switch(s2_flag) { case 2:Calendar[0]--;if(Calendar[0]==0) Calendar[0]=99; break;//年- case 3:Calendar[1]--;if(Calendar[1]==0) Calendar[1]=12; break;//月- case 4:Calendar[2]--;if(Calendar[2]==0) Calendar[2]=31; break;//日- } } else if(s1_flag==3)//闹钟界面 { switch(s2_flag) { case 2:Alarm[0]--;if(Alarm[0]==-1) Alarm[0]=23;break;//时- case 3:Alarm[1]--;if(Alarm[1]==-1) Alarm[1]=59;break;//分- case 4:Alarm[2]--;if(Alarm[2]==-1) Alarm[2]=59;break;//秒- case 5:time-- ;if(time==-1) time=60; break;//设置闹钟时长- } } } else if(alarm1==1) {alarm1=0;buzzer=1;TR1=0;}//闹钟状态下,任意键可以关闭闹钟 } while(s4==0)SMG_Display();//松手检测 } } void main() { InitTimer(); while(1) { SMG_Display(); keyscan(); Alarming(); } }代码和proteus原理图 有问题的朋友可以来戳我哟