本程序可以实现时间的显示以及秒表的计时两个模式,两个模式可以同时工作互不干扰。
只需选择时钟/秒表模式进行显示即可。
使用说明:
LED指示灯 | |
D1 |
亮的时候表示时钟正在运行,不亮表示时钟进入调节档位 |
D6 | 不亮表示当数码管表示的是时钟模式,亮则表示当前数码管表示的是秒表模式 |
D8 | 不亮表示,秒表暂停;亮表示,秒表正在运行 |
独立按键 | |
k4 | 模式切换(时钟/秒表) |
在时钟模式下:
k1 | 按一次暂停时钟运行,进入更改时档位,第二次进入更改分档位,第三次进入更改秒档位,第四次启动时钟 |
k2 | 时/分/秒 数值加一 |
k3 | 时/分/秒 数值减一 |
在秒表模式下:
k1 | 无 |
k2 | 秒表 暂停/起动 |
k3 | 秒表清零 |
实现代码:
#include<REGX52.h> typedef unsigned char uchar; //共阴极段码 uchar code leddata[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //带小数点的共阴数码管段码 uchar code ledxiaoshudian[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef}; uchar mode=0; unsigned int Stopwatch=0,sec=55,min=59;//秒表 char s=56,m=59,h=23; int n0=0,n1=0; //延时函数 void Delay(unsigned int xms){ unsigned char i, j; while(xms--){ i = 2; j = 239; do{ while (--j); } while (--i); } } void Timer0Init(void) //50毫秒@12.000MHz { TMOD &= 0xF0; //设置定时器模式 TMOD |= 0x01; //设置定时器模式 TL0 = 0xB0; //设置定时初值 TH0 = 0x3C; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 EA=1; ET0=1; //定时器T0中断小开关 } void Timer1Init(void) //1毫秒@12.000MHz { TMOD &= 0x0F; //设置定时器模式 TMOD |= 0x10; //设置定时器模式 TL1 = 0x18; //设置定时初值 TH1 = 0xFC; //设置定时初值 TF1 = 0; //清除TF1标志 //TR1 = 1; //定时器1开始计时 ET1=1; //定时器T1中断小开关 EA=1; } //显示时钟 //由定时器0来进行计数 void display_Clock(uchar hour,uchar minute,uchar second){ int i; for(i=1;i<=8;i++){ switch(i){ case 1: P2_4=0;P2_3=0;P2_2=0;P0=leddata[second%10];break; case 2: P2_4=0;P2_3=0;P2_2=1;P0=leddata[second/10];break; case 3: P2_4=0;P2_3=1;P2_2=0;P0=0x40;break;//显示 — case 4: P2_4=0;P2_3=1;P2_2=1;P0=leddata[minute%10];break; case 5: P2_4=1;P2_3=0;P2_2=0;P0=leddata[minute/10];break; case 6: P2_4=1;P2_3=0;P2_2=1;P0=0x40;break;//显示 — case 7: P2_4=1;P2_3=1;P2_2=0;P0=leddata[hour%10];break; case 8: P2_4=1;P2_3=1;P2_2=1;P0=leddata[hour/10];break; } Delay(1); P0=0; //消影 } } //显示秒表 //参数为当前秒表将要显示的数,由定时器1来进行计数 void display_Stopwatch(){ int i; for(i=1;i<=8;i++){ switch(i){ case 1: P2_4=0;P2_3=0;P2_2=0;P0=leddata[Stopwatch%10];break; case 2: P2_4=0;P2_3=0;P2_2=1;P0=leddata[Stopwatch/10%10];break; case 3: P2_4=0;P2_3=1;P2_2=0;P0=leddata[Stopwatch/100%10];break; case 4: P2_4=0;P2_3=1;P2_2=1;P0=ledxiaoshudian[sec%10];break; case 5: P2_4=1;P2_3=0;P2_2=0;P0=leddata[sec/10];break; case 6: P2_4=1;P2_3=0;P2_2=1;P0=P0=0x40;break; case 7: P2_4=1;P2_3=1;P2_2=0;P0=leddata[min%10];break; case 8: P2_4=1;P2_3=1;P2_2=1;P0=leddata[min/10];break; } Delay(1); P0=0; //消影 } } void key_scan(){ static uchar flag=0; if(P3_1==0){ //档位选择 Delay(20); while(P3_1==0); Delay(20); TR0=0;//关闭T0中断请求 flag++; P2_5=1; if(flag==4){ P2_0=0; flag=0; TR0=1; } } if(P3_3==0){//模式切换按键 Delay(20); while(P3_3==0); Delay(20); mode++; P2_5=~P2_5;//将D6作为模式的指示灯(亮着进入秒表模式,不亮就是时钟模式) if(mode==2)//模式切换成时钟模式 mode=0; } if(mode==0){ //时钟模式 if(flag!=0){ switch(flag){ case 1:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);h++; if(h>23) h=0;}break; case 2:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);m++; if(m>59) m=0;}break; case 3:if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);s++; if(s>59) s=0;}break; default:break; } switch(flag){ case 1:if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);h--; if(h<0) h=23;}break; case 2:if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);m--; if(m<0) m=59;}break; case 3:if(P3_2==0){ Delay (20);while(P3_2==0);Delay(20);s--; if(s<0) s=59;}break; default:break; } } }else {//秒表模式 if(P3_2==0){ Delay(20);while(P3_2==0);Delay(20);Stopwatch=0,min=0,sec=0;}/*秒表清零*/ if(P3_0==0){ Delay(20);while(P3_0==0);Delay(20);TR1=~TR1;P2_7=~P2_7;}/*秒表 暂停/启动*/ } } void main(){ Timer0Init();//定时器0 初始化 Timer1Init();//定时器1 初始化 P2_0=0; //时钟正常工作指示灯,正常工作时亮,反之不亮 while(1){ switch(mode){ case 0:display_Clock(h,m,s);break; case 1:display_Stopwatch();break; } key_scan(); } } //定时器0的溢出中断函数 void timer0() interrupt 1 { TL0 = 0xB0; //设置定时初值 TH0 = 0x3C; //设置定时初值 n0++; if(n0==20) { n0=0; s++; if(s>=60) { s=0; m++; if(m>=60) { m=0; h++; if(h>=24) h=0; } } } } //定时器1的溢出中断函数 void timer1() interrupt 3 { TL1 = 0x18; //设置定时初值 TH1 = 0xFC; //设置定时初值 Stopwatch++; if(Stopwatch>=1000){ //秒表进位 Stopwatch=0; sec++; if(sec>=60){ //秒满60分进位 sec=0; min++; if(min>=60){ Stopwatch=0,min=0,sec=0; } } } }
运行环境:普中51开发板。
电路如下: