1、这里介绍的电子钟,电路可称得上极简,它仅使用单片的 20 引脚单片机完成电子钟的全部功能,而笔者见到的其它设计方案均采用二片以上的多片 IC 实现。电路见图 1。一片 20 引脚的单片机 AT89C2051 为电子钟主体,其显示数据从 P1 口分时输出,P3.03.3 则输出对应的位选通信号。由于 LED 数码管点亮时耗电较大,故使用了四只 PNP 型晶体管 VT1VT4 进行放大。本来笔者还有一种更简的设计方案(见图 2),可省去 VT1VT4 及 R1R4 八个元件,但这种设计由于单片机输出口的灌入电流有限(约 20mA),数码管亮度较暗而不向读者介绍,除非你采用了高亮度的发光数码管。P3
2、.4、P3.5、3.7 外接了三个轻触式按键,这里我们分别命名为:模式设定键set(P3.4)、时调整键 hour(P3.5)、分调整键 min(P3.7)。C1、R13 组成上电复位电路。VT5 及蜂鸣器 Bz 为闹时讯响电路。三端稳压器 7805 输出的 5V 电压供整个系统工作。此电子钟可与任何 920V/100mA 的交直流电源适配器配合工作,适应性强。电子钟功能1.走时:通过模式设定键 set 选择为走时,U1、U2 显示小时,U3、U4 显示分。U2的小数点为秒点,每秒闪烁一次。2.走时调整:通过模式设定键 set 选择为走时调整,按下 hour 键对 U1、U2 的走时“时”显示
3、进行调整(每 0.2 秒递加 1)。按下 min 键对 U3、U4 的走时“分”显示进行调整(每 0.2 秒递加 1)。3.闹时调整:通过模式设定键 set 选择为闹时调整,按下 hour 键对 U1、U2 的闹时“时”显示进行调整(每 0.2 秒递加 1)。按下 min 键对 U3、U4 的闹时“分”显示进行调整(每 0.2 秒递加 1)。4.闹时启/停设定:通过模式设定键 set 选择为闹时启/停设定,按下 min 键 U3 的小数点点亮,闹时功能启动;按下 hour 键 U3 的小数点熄灭,闹时功能关停。由于电路设计得极其简单,因此丰富的功能只能由软件完成,这里软件设计成为了关键。下面介
4、绍软件设计要点。图 3 为主程序状态流程。图 3运行时建立的主要状态标志如下:flag掉电标志。掉电后,flag 内为一随机数;重新设定时间后 flag 内写入标志数 55H。set工作模式设定标志。hour走时“时”单元。min走时“分”单元。sec走时“秒”单元。deda走时 5mS 计数单元t_hour闹时“时”单元。t_min闹时“分”单元。d_05s0.5 秒位标志。每秒钟的前 0.5 秒置 1,后 0.5 秒置 0,以使秒点闪烁。o_f闹时启/停位标志。闹时启动置 1,闹时关停置 0。另外将定时器 T0 设定为 5mS 的定时中断。这里晶振频率为 12MHz,因此 5mS 的初值为
5、-5000,但实际上程序还要作其它运算,使得时间偏长,经调整为-4800 后试验刚好。计时单元 deda 每次中断均加 1。走时函数判断 deda=200 时即令秒单元 sec 加 1。同理秒单元 sec 满 60 后令分单元 min 加 1。分单元 min 满 60 后令时单元 hour 加 1。时单元 hour 满 24 后清 0。上电后,首先进行初始化,对各状态标志、输入输出口及定时器 T0 进行初始化工作,以适应后面程序的要求。随后程序判断有无 set 键按下,如按下,则 set 键值从 0 起加 1。set 键值只能从0 加到 3,然后又回到 0。接下来,根据键值进行散转。若 set
6、=0,运行走时程序;若 set=1,进入调整闹时时间程序;若 set=2,进入调整走时时间程序;若 set=3,显示已调好的闹时时间,同时进入启/停闹时程序。散转完后,进行判断掉电标志 flag 是否等于 55H。若不等,说明刚开机上电或运行过程中掉过电,这时四个数码管以 1Hz 的频率闪烁四个 8 字,提示时间不准;若相等,说明未掉电,RAM 区内容未变化,时间准确。再下来程序又转回到初始化之后进行循环运行。由于使用了四只数码管密集排列,因此只能采用双面印刷板设计,图 4、5 分别为正面(元件面)、反面的印板图。尺寸 3000milx4000mil(7.62cmx10.16cm)。图6 为计
7、算机输出的三维仿真印制板。图 4图 5图 6元件选用为了走时准确,晶振 X 最好选用温漂小的。四个数码管 U1U4 可选用发绿光的,这样光泽较柔和。蜂鸣器 Bz 要购买绕线型的电动式蜂鸣器(市场上有一种加电压即工作的蜂鸣器这里不适用),因驱动信号为脉冲信号。其它元件一般无特殊要求。使用方法上电后,四个 LED 数码管闪烁四个 8 字。按一下 set 键,闪烁现象消失(此时 set=1),U1 的小数点亮,说明此刻可以调整闹时时间。按下 hour 键,U1、U2 作加法;按下 min 键,U3、U4 作加法。这些调整好的数据被同时送入 RAM 区的闹时记忆“时”单元 t_hour 和闹时记忆“分
8、”单元t_min。再按一下 set 键,set=2,U2 的小数点亮,此刻可以调整走时时间。按下 hour 键,U1、U2 作加法;按下 min 键,U3、U4 作加法。这些调整好的数据也被同步送入RAM 区的“时”记忆单元 hour 和“分”记忆单元 min。再按一下 set 键,set=3,显示刚才调整的闹时时间,此刻可以选择启动/关停闹时。按下 min 键,o_f 位标志置 1,U3 的小数点亮,闹时启动;按下 hour 键,o_f 位标志置 0,U3 的小数点灭,闹时关闭。若再按一下 set 键,set=0,电路进入走时状态,U1、U2 显示小时,U3、U4 显示分。U2 的小数点作秒
9、点闪烁。在闹时启动的情况下,走时到达设定闹时,则蜂鸣器 Bz 鸣响一分钟进行提醒。附:用 C51 编写的源程序清单(已由实验板运行通过)#include /*包含器件配置文件*/#define uchar unsigned char#define uint unsigned intchar DATA_7SEG10=0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,;/*09 的数码管段码*/uchar hour=0,min=0,sec=0; /*时、分、秒单元清零*/uchar deda=0; /*5mS 计数单元清零*/uchar t_hou
10、r=0,t_min=0; /*闹时时、分单元清零*/bit d_05s=0; /*0.5 秒标志*/bit o_f=0; /*闹时启/停标志*/uchar set=0; /*模式设定标志*/uchar m=0;uchar flag=0; /*RAM 掉电标志*/void delay(uint k); /*延时子函数*/void conv(); /*走时单元转换*/void p_out(); /*判别闹时到否子函数*/void dirve(); /*走时时间输出驱动子函数*/void t_dirve(); /*闹时时间输出驱动子函数*/*闹时启/停子函数*/void time1_of() uch
11、ar m;if(P3_7=0)delay(1);if(P3_7=0)o_f=1;for(m=0;m=4)set=0;if(set=1)flag=0x55;F0:if(P3_4=0)goto F0; /*按键未释放,在此等候*/*延时子函数*/void delay(uint k)uint i,j;for(i=0;ifor(j=0;j=200)sec+;deda=0;if(sec=60)min+;sec=0;if(min=60)hour+;min=0;if(hour=24)hour=0;/*走时时间输出驱动子函数*/void dirve()P1=DATA_7SEGhour/10;P3=0xf7;d
12、elay(1);P1=DATA_7SEGhour%10;P3=0xfb;delay(1);if(d_05s=1)if(P3_2=0)P1_7=0;else P1_7=1;delay(1);P1=DATA_7SEGmin/10;P3=0xfd;delay(1);if(o_f=1)if(P3_1=0)P1_7=0;else P1_7=1;delay(1);P1=DATA_7SEGmin%10;P3=0xfe;delay(1);/*闹时时间输出驱动子函数*/void t_dirve()P1=DATA_7SEGt_hour/10;P3=0xf7;delay(1);if(P3_3=0)P1_7=0;el
13、se P1_7=1;delay(1);P1=DATA_7SEGt_hour%10;P3=0xfb;delay(1);P1=DATA_7SEGt_min/10;P3=0xfd;delay(1);P1=DATA_7SEGt_min%10;P3=0xfe;delay(1);/*判别闹时到否子函数*/void p_out()if(o_f=1)if(t_hour=hour)if(t_min=min)if(P3_0=0)P1_7=0;delay(1);else P1_7=1;/*主函数*/void main()init_timer(); /*定时器 T0 初始化*/while(1) /*无限循环*/if(
14、P3_4=0)scan_key(); /*有按键,调用按键扫描子函数*/switch(set) /*根据 set 键值散转*/case 0:time();break; /*走时时间程序*/case 1:time1_adj();break; /*闹时时间调整*/case 2:time_adj();break; /*走时时间调整*/case 3:time1_of();break; /*启/停闹时*/default:break; /*其它退出*/if(flag!=0x55) /*判断掉电标志*/for(m=0;m100;m+) /*点亮四个 8 字 400mS*/P1=0x80;P3=0xf7;delay(1);P1=0x80;P3=0xfb;delay(1);P1=0x80;P3=0xfd;delay(1);P1=0x80;P3=0xfe;delay(1);P1=0xff;P3=0xff;delay(400); /*熄灭四个 8 字 400mS*/