资源描述
一、 电子时钟、秒表和计数器设计
1、 实现功效:
1)有key0,key1两个功效按键,复位后,数码管会默认显示时钟模式 HH.MM 。
(HH表示小时,MM表示分钟),
key0短按一次就进入到了秒表模式,数码管显示格式S.SS.S,(分别表示百秒,秒,毫秒)
key0再短按一次就进入到了计数器模式,数码管显示格式CCCC(分别为千位百位十位个位)。
key0再短按一次,又进入到了时钟显示模式,就这么由key0控制模式转换。
2)有RST复位键,本身电路设计有上电自动复位功效,按下RST后,电路复位。
3)有ckey0,ckey1 两个计数按键,按下ckey0,计数加一,按下ckey1,计数减一。
4) 电子时钟和秒表时间计时方法是采取89S52内部计时器0一个工作方法(详见后面代码分析),经过计时器0中止来控制时间运行。
5)计数器是采取外部中止0和外部中止1这两个外部中止实现加1和减1操作。
(1) 电子时钟模式:(以下“长按”表示按下按键时间大于1秒,“短按”表示按下时间小于0.7 秒)
1)长按key1一次,会进入到调整分钟模式,短按key1一次,分钟会加一。
第二次长按key1,会进入到调整小时模式,短按key1一次,小时加一。
第三次长按key1,重新回到时钟显示模式,这时再短按key1,时间不会改变
2)长按key0一次,会进入到显示秒模式
(2) 秒表模式:
1) 由key0控制进入秒表模式后,短按key1一次,秒表计时开始,再短按key1一次计时结束
2) 长按key1一次,秒表清零
(3) 计数器模式
1) 按ckey0一下,计数加一,数码管对应显示数值加一,
按ckey1一下,计数减一,数码管对应显示数值减一,
因为数码管位数限制,最大只能显示到9999,此时按下ckey0无反应;考虑到
实际计数功效,没有设置负数,所以最小显示0000,这时按下ckey1 ,无反应。
2) 长按key1一次计数器清零。
2、 电路原理图
(1) 使用片内振荡器
(2) 含有上电复位和手动复位两个功效
(3) key0,key1分别接P1.0和P1.1引脚
(4) 由P0.0~P0.7输出到七段数码显示管
(5) 由P2.0~P2.3接三极管,驱动共阳七段数码显示管
(6) ckey0,ckey1接P3.2和P3.3两个引脚,为两个外部中止
4.电路焊接实物图
(1)正面
(2)反面:
因为显影、腐蚀过程做得不好,造成电路板过分腐蚀,不过经过修改以后,电路能够正常运行,并无大碍,只是不美观。
(4) 电路板工作时。此时为显示时钟秒
显示时钟
显示秒表
显示计数器
5、程序设计分析
(1)程序代码
#include<Reg51.h>
sbit key0=P1^0;
sbit key1=P1^1; //定义key0,key1接口
unsigned char flag,con,mcount; //flag为计数到一秒时给时钟发信号
unsigned char count = 0;
unsigned char seccount =0; //作为时钟秒计量单位
unsigned char hour = 0; //时钟时
unsigned char min = 0; //时钟分
unsigned char sec = 0; //时钟秒
unsigned char keypress0,keypress1,mode,ms,s,ss,start;
unsigned char
Displaynum[]={0x14,0xd7,0x4c,0x45,0x87,0x25,0x24,0x57,0x04,0x05, 0x10,0xd3,0x48,0x41,0x83,0x21,0x20,0x53,0x00,0x01,0xff,0xfb};
//数码管十六进制译码表
unsigned char controlnum[]={0x08,0x04,0x02,0x01}; //控制四个数码管显示
unsigned char DisplayBuff[]={0x00, 0x00, 0x00, 0x00}; //每个数码管值
void display_state(); //数码管显示子程序
void keyscan(); //键盘扫描子程序
void timer(); //秒表子程序
unsigned char count1,flag1,t_adjust=0,tm_adjust=0;
unsigned charbKey0Pressed = 0, bKey1Pressed = 0;
unsigned char ucStatus = 0;
void main()
{
TMOD = 0x01; //定时器0工作在模式1,GATE=0,C/t=0,16位模
TH0= (2^16-5000)/256;//定时器0 预存值,
TL0= (2^16-5000)%256;
TR0= 1; //定时器0 开启
ET0= 1; //定时器中止0 许可
EA= 1; //开中止
IT0=1; //外部中止0下降沿触发
IT1=1; //外部中止1 下降沿触发
EX0=1; //外部中止0许可
EX1=1; //外部中止1许可
PX1=1; //外部中止1 为高优先级中止
while(1) //死循环,
{
if(flag == 1) //时钟显示
{
flag = 0;
sec++;
if(sec ==60)
{sec = 0;
min++;
if(min ==60)
{min = 0;
hour ++;
if(hour == 24)
{
hour = 0;
}
}
}
}
display_state();
keyscan();
timer();
}
}
//////////////////////////////////ISR中止服务程序,每5ms产生一个定时器0 中止
void Display() interrupt 1
{
TH0 = (2^16-5000)/256;
TL0 = (2^16-5000)%256;
seccount ++;
mcount ++;
keypress0++;
keypress1++;
P2=0x00; //P2口先清零
P0 = Displaynum[DisplayBuff[count]]; //P0口输出
P2 = controlnum[count]; //P2口输出
count++;
if(count==4)
count=0;
if(seccount == 200) //200*5ms=1s
{ seccount =0;
flag =1; //每过1秒给时钟信号加一秒
}
}
///////////////////////////////////////////
void display_state()
{
if(mode == 0) //时钟模式,显示时间
{
DisplayBuff[0] = hour/10;
DisplayBuff[1] = (hour%10)+10; //“+10”是为了显示加点数字
DisplayBuff[2] = min/10;
DisplayBuff[3] = min%10;
}
if(mode == 1) //秒表模式,显示秒表
{
DisplayBuff[0] = ss +10; //“+10”是为了显示加点数字
DisplayBuff[1] = s/10;
DisplayBuff[2] = (s%10)+10;
DisplayBuff[3] = ms;
}
if(mode == 2) // 计数器模式,显示计数
{
DisplayBuff[0] = count1/1000; //千位
DisplayBuff[1] = (count1-(count1/1000)*1000)/100; //百位
DisplayBuff[2] = (count1-(count1/100)*100)/10; //十位
DisplayBuff[3] = count1%10; //个位
}
if(mode==3) //显示时钟秒,
{
DisplayBuff[0] = 20; //第一位不显示
DisplayBuff[1] = 21; //第二位显示一个点
DisplayBuff[2] = sec/10;//显示秒十位
DisplayBuff[3] = sec%10;//显示秒个位
}
}
//**************//
//键盘扫描子程序//
//**************//
void keyscan()
{
if(!key0 && bKey0Pressed == 0) //检测到key0按下
{
keypress0 = 0;
bKey0Pressed = 1; //预防重入此判定
while(!key0); //假如没放开,就等下去
}
if(key0 && bKey0Pressed == 1) //检测到key0放开
{
bKey0Pressed = 0; //预防重入此判定
if (keypress0<120) //假如是短按
{
if(ucStatus == 0x02)
{
ucStatus = 0x00;
mode = 0; //时钟模式
t_adjust=0;
}
else if(ucStatus == 0x00)
{
ucStatus = 0x01;
mode = 1; //秒表模式
}
else if(ucStatus == 0x01)
{
ucStatus = 0x02;
mode = 2; //计数模式
}
}
else if(keypress0>200) //假如是长按
mode=3; //显示时钟秒模式
}
////////////////////////////////
if(mode == 0) //进入时钟模式后
{
if(!key1 && (bKey1Pressed == 0))
{ keypress1 = 0;
bKey1Pressed = 1;
while(!key1);
}
if(key1 && (bKey1Pressed == 1))
{
bKey1Pressed = 0;
if(keypress1 >= 200) //假如是长按
{
t_adjust++;
if(t_adjust==3)
t_adjust=0;
}
else if(keypress1 < 120) 假如是短按
switch (t_adjust)
{
case 1:{ //调整分
min++;
sec = 0;
if(min == 60)
min = 0;
}
break;
case 2: { //调整时
hour ++ ;
sec = 0;
if(hour == 24)
hour = 0;
}
break;
default:break;
}
}
}
else if(mode == 1) //进入秒表模式
{
if(!key1 && bKey1Pressed == 0)
{
keypress1 = 0;
bKey1Pressed = 1;
while(!key1);
}
if(key1 && bKey1Pressed == 1)
{
bKey1Pressed = 0;
if(keypress1 < 120) //短按
{
if(flag1==0) { start=2;flag1=1;} //start=2代表秒表开始计时
else {start=0;flag1=0;} //start=0,秒表停止计时
}
else if(keypress1>200) //长按
start=1; //秒表清零
}
}
}
void timer() //秒表子程序
{
if(mode==1) //进入秒表模式才实施
{
if(start==1) //清零
{
ms = 0;
s = 0;
ss = 0;
mcount=0;
}
if(start==2) //秒表开始计时
{
if(mcount==20) //20*5ms=0.1s
{
mcount=0;
ms++;
if(ms == 10) // 10*0.1s=1s,s++
{ms = 0;
s ++;
if(s == 100) //100s
{s = 0;
ss ++;
if(ss == 10)
{ss = 0;
s = 0;
ms = 0;
}
}
}
}
}
if(start==0);//秒表停止
}
}
//////////////////////
void it0(void) interrupt 0 using 1 //外部中止0 服务程序
{
if(mode==2) //只有在计数模式才实施
{
count1++; //每响应一次,计数加一
if(count1==10000) //超出四位时,不能再加
count1 =9999;
}
}
void it2(void) interrupt 2 using 2 //外部中止0 服务程序
{
if(mode==2) //只有在计数模式才实施
{
if(count1!=0)
{count1--;} //计数减一,不显示负数,当减到零时便不能再减
}
}
展开阅读全文