本程序可以实现时间的显示以及秒表的计时两个模式,两个模式可以同时工作互不干扰。
只需选择时钟/秒表模式进行显示即可。
使用说明:
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开发板。
电路如下: