#include <reg51.h>
#define uchar unsigned char #define uint unsigned int uchar hour=23,min=59,sec=45; //定义小时、分钟和秒变量 uchar count_10ms; //定义10ms计数器 sbit K1 = P3^2; //定义K1键 sbit K2 = P3^3; //定义K2键 sbit K3 = P3^4; //定义K3键 sbit K4 = P3^5; //定义K4键 sbit BEEP=P3^7; //定义蜂鸣器 bit K1_FLAG=0; //定义按键标志位,当按下K1键时,该位置1,K1键未按下时,该位为0。 uchar code bit_tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选表,用来选择哪一只数码管进行显示 uchar code seg_data[]={0x28, 0x7E, 0xA2, 0x62, 0x74, 0x61, 0x21, 0x7A, 0x20, 0x60,0xff};//0,1,2,3,4,5,6,7,8,9,关显示,数码管码表 //0~F、熄灭符和字符"-"的显示码(字形码) uchar disp_buf[8]; //定义显示缓冲单元 /********以下是延时函数********/ void Delay_ms(uint xms) { uint i,j; for(i=xms;i>0;i--) //i=xms即延时约xms毫秒 for(j=110;j>0;j--); } /*********以下是蜂鸣器响一声函数********/ void beep() { BEEP=0; //蜂鸣器响 Delay_ms(100); BEEP=1; //关闭蜂鸣器 Delay_ms(100); } /********以下是走时转换函数,负责将走时数据转换为适合数码管显示的数据********/ void conv(uchar in1,in2,in3) //形参in1、in2、in3接收实参hour、min、sec传来的数据 { disp_buf[0] =in1/10; // 小时十位 disp_buf[1] = in1%10; // 小时个位 disp_buf[3] = in2/10; // 分钟十位 disp_buf[4] = in2%10; // 分钟个位 disp_buf[6] = in3/10; // 秒十位 disp_buf[7] = in3%10; // 秒个位 disp_buf[2] = 17; // 第3只数码管显示"-"(在 seg_data表的第17位) disp_buf[5] = 17; // 第6只数码管显示"-" }
/********以下是显示函数********/ void Display() { uchar tmp; //定义显示暂存 static uchar disp_sel=0; //显示位选计数器,显示程序通过它得知现正显示哪个数码管,初始值为0 tmp=bit_tab[disp_sel]; //根据当前的位选计数值决定显示哪只数码管 P2=tmp; //送P2控制被选取的数码管点亮 tmp=disp_buf[disp_sel]; //根据当前的位选计数值查的数字的显示码 tmp=seg_data[tmp]; //取显示码 P0=tmp; //送到P0口显示出相应的数字 disp_sel++; //位选计数值加1,指向下一个数码管 if(disp_sel==8) disp_sel=0; //如果8个数码管显示了一遍,则让其回0,重新再扫描 } /********以下是定时器T0中断函数, 用于数码管的动态扫描********/ void timer0() interrupt 1 { TH0 = 0xf8;TL0 = 0xcc; //重装计数初值,定时时间为2ms Display(); //调显示函数 } /********以下是定时器T1中断函数, 用于产生用于产生秒、分钟和小时信号********/ void timer1() interrupt 3 { TH1 = 0xdc;TL0 = 0x00; //重装计数初值,定时时间为10ms count_10ms++; //10ms计数器加1 if(count_10ms >= 100) { count_10ms = 0; //计数100次后恰好为1s,此时10ms计数器清0 sec++; //秒加1 if(sec == 60) { sec = 0; min++; //若到60秒,分钟加1 if(min ==60) { min = 0; hour++; //若到60分钟,小时加1 if(hour ==24) { hour = 0;min=0;sec=0; //若到24小时,小时、分钟和秒单元清0 } } } } } /********以下是按键处理函数,用来对按键进行处理********/ void KeyProcess() { TR1=0; //若按下K1键,则定时器T1关闭,时钟暂停 if(K2==0) //若按下K2键 { Delay_ms(10); //延时去抖 if(K2==0) { while(!K2); //等待K2键释放 beep(); hour++; //小时调整 if(hour==24) { hour = 0; } } } if(K3==0) //若按下K3键 { Delay_ms(10); if(K3==0) { while(!K3); //等待K3键释放 beep(); min++; //分钟调整 if(min==60) { min = 0; } } } if(K4==0) //若按下K4键 { Delay_ms(10); if(K4==0) { while(!K4); //等待K4键释放 beep(); TR1=1; //调整完毕后,时钟恢复走时 K1_FLAG=0; //将K1键按下标志位清0 } } } /*********以下是定时器T0/T1初始化函数********/ void timer_init() { TMOD = 0x11; // 定时器0, 1工作模式1, 16位定时方式 TH0 = 0xf8;TL0 = 0xcc; //装定时器T0计数初值,定时时间为2ms TH1 = 0xdc;TL1 = 0x00; // 装定时器T1计数初值,定时时间为10ms EA=1;ET0=1;ET1=1; //开总中断和定时器T0、T1中断 TR0 = 1;TR1 = 1; //启动定时器T0、T1 } /********以下是主函数********/ void main(void) { P0 = 0xff; P2 = 0xff; timer_init(); //调定时器T0、T1初始化函数 while(1) { if(K1==0) //若K1键按下 { Delay_ms(10); //延时10ms去抖 if(K1==0) { while(!K1); //等待K1键释放 beep(); //蜂鸣器响一声 K1_FLAG=1; //K1键标志位置1,以便进行时钟调整 } } if(K1_FLAG==1)KeyProcess(); //若K1_FLAG为1,则进行走时调整 conv(hour,min,sec); //调走时转换函数 } } |