|
#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); //调走时转换函数
}
}
|
|