| 这是一个数字时钟电路,它可以定时开关一路使用交流电的设备。
简介
这个定时控制电路既可以在实际中应用,也可以作为一个学习用C51控制定时器中断0、七段LED数码管和键盘扫描的例子。它可输出一路控制信号来控制一个继电器或可控硅等。那些需要七位数码显示和键盘接口的电路也可从这个电路和单片机程序得到启发。
工作原理
P1.0-1.7采用倒灌方式驱动七段共阳数码管。P3.0-3.3驱动4个PNP三极管2N2907。如图所示,第三个数码管旋转了180度, 这样第三个数码管的那个点和第二个数码管的那个点用来表示数字时钟上的那两个点,它们每秒闪动一次。P3.0-3.3同时连接到四个微动开关,微动开关的另一脚连接到P3.4。在显示和键盘扫描期间,从P3.0到P3.3轮替输出一个逻辑0,如果这时某个微动开关被按下,P3.4将变成低电平。P3.7输出一路控制信号,可以通过一个三极管来控制一个继电器。
原理图如下:

程序
clock.c程序是用C语言写的,用Micro-C编译的。内存模式是TINY。clock.hex是它的十六进制文件。clock1.c是用为C51编译器修改过的。
修正实时钟的子程序已被移到定时中断0中。
程序的扩展
clock.c中的time()函数没有放在定时中断0中。scanLED()函数中有一个位延迟功能用于时钟延迟,你可写个子程序来调整时钟。因为还有足够的程序空间,所以你可以再写一些程序来完成第二组定时功能。
重负载
如果要控制的负载很重的话,建议使用合适的固态继电器,大多数固态继电器可以使用3-30V来驱动。
CLOCK V1.0 89C2051 + 4-digit 7-SEG led + 4-key switch Simple Digital Clock demostrates scanning LED and key switch. The clock has 1-bit output port P3.7 for driving AC load through MOC3040+triac. The source program was modified for Proview32 C51 Compiler. 3 November 2542
set set time manual HOUR MIN ON/OFF ON/OFF
Copyright (c) 1999 W.SIRICHOTE */ #include <reg52.h> /* special function register declarations */ #include <stdio.h> /* for the AT89C52 */
unsigned char sec100,sec,sec5,min,hour,flag1,command,temp,opto; /* above must be defined as register for tiny model */ unsigned char i,digit,buffer[4],onHour1,onMin1,offHour1,offMin1; char cputick,key,delay,count1; char convert[10] = {0x3F,0x0c,0x76,0x5e,0x4d,0x5b,0x7b,0x0e,0x7f,0x5f}; void pause(int); void scanLED(); void manualOnOff(); void savetimeOnOff1(); void setmin(); void sethour(); void showOnce(); void savetimeOff1(); void time(); void timeToBuffer(); void blink(); void offmsd(); void keyexe(); void keydelay(); void comparetime(); void timer0int (void) interrupt 1 using 1 { TH0 |= 0xdc; // reload timer 0 with 0DC00H cputick++; time(); // update realtime clock } void main() { EA = 1; ET0 = 1; // or IE |= 0x82; /* set bit EA and Timer0 enable */ TMOD |= 0x01; /* timer 0 run 16 bit counter */ TR0 = 1; //or TCON |= 0x10; /* run timer 0 */ opto = 0xff; cputick = 0; hour = 18; min = 0; sec = 0; key = -1; flag1 = 0; onHour1 = 18; /* 18:30 turn lamp on */ onMin1 = 01; offHour1 = 18; /* 21:30 turn off */ offMin1 = 02; count1 = 0; buffer[0] = 0x40; buffer[1] = 0x40; buffer[2] = 0x40; buffer[3] = 0x40; // serinit(9600); /* must be invoked for tiny model */ while(1) { while ( cputick < 1) scanLED(); cputick = 0; /*------------- the following tasks execute every 10ms ------*/ // time(); timeToBuffer(); blink(); offmsd(); keyexe(); keydelay(); comparetime(); /*-----------------------------------------------------------*/ } } /* ****************** change constant below for other X-tal ********/ void time () /* update real-time clock */ { sec100++; if (sec100 >= 100) /* 100 * 10 ms = 1 s */ {sec100 = 0; flag1 |= 0x05; /* set bit 0, bit 2 */ temp = 50; sec++; if (sec >= 60) {sec = 0; flag1 |= 0x02; /* set bit 1 */ min++; if (min >= 60) {min = 0; hour++; if (hour >= 24) {hour = 0; } } } } } void scanLED() /* scan 4-digit LED and 4-key switch, if key pressed key = 0-3 else key = -1 */ { int i; digit = 0x08; key = -1; for( i = 0; i < 4; i++) /* 4-DIGIT scanning */ { P3 = ~digit & opto; /* send complement[digit] */ P1 = ~buffer[i]; /* send complement[segment] */ pause(5); /* delay a while */ P1 = 0xff; /* off LED */ if ((P3 & 0x10) == 0) /* if key pressed P3.4 became low */ key = i; /* save key position to key variable */ digit>>=1; /* next digit */ } } void timeToBuffer() { buffer[0] = convert[min%10]; buffer[1] = convert[min/10]; buffer[2] = convert[hour%10]; buffer[3] = convert[hour/10]; } void blink() {if((flag1 & 0x04) != 0) /* check bit 2 if set decrement temp until zero */ {temp--; if (temp != 0) { buffer[1] |= 0x80; buffer[2] |= 0x80; } else( flag1 &= ~0x04); } } void keyexe() { if (key != -1) { if ((flag1 & 0x80) == 0) /* within 0.5 sec after 1st press the following execution is not allowed */ { flag1 |= 0x80; delay = 50; switch(key){ case (0): /* key position 0 */ manualOnOff(); /* service key 0 */ break; case (1): /* key position 1 */ savetimeOnOff1(); /* service key 1 */ break; case (2): /* key position 2 */ setmin(); /* service key 2 */ break; case (3): /* key position 3 */ sethour(); } } } } void sethour() { hour++; if ( hour== 24) hour = 0; } void setmin() { min++; sec = 0; if( min == 60 ) min = 0; } void savetimeOnOff1() { count1++; if (count1 == 1) { onHour1 = hour; onMin1 = min; buffer[0] = 0x00; buffer[1] = 0x68; buffer[2] = 0x78; buffer[3] = 0x71; showOnce(); } else { count1 = 0; savetimeOff1(); } } void savetimeOff1() { offHour1 = hour; offMin1 = min; buffer[0] = 0x63; buffer[1] = 0x63; buffer[2] = 0x78; buffer[3] = 0x71; showOnce(); } void manualOnOff() { opto= ~opto | 0x7f; /* complement bit 7 which in turn activates P3.7 */ if ((opto & 0x80) == 0) { buffer[0] = 0; buffer[1] = 0; buffer[2] = 0x68; buffer[3] = 0x78; showOnce(); } else { buffer[0] = 0; buffer[1] = 0x63; buffer[2] = 0x63; buffer[3] = 0x78; showOnce(); } } void showOnce() { int i; for(i=0;i<2000;i++) scanLED(); } void keydelay() { if ((flag1 & 0x80) !=0) { delay--; if(delay == 0) flag1 &= ~0x80; } }
void comparetime() { if((flag1 & 0x01) != 0 ) { flag1 &= ~0x01; if(hour == onHour1 && min == onMin1) opto = 0x7f; /* clear P3.7 turning opto on */ if(hour == offHour1 && min == offMin1) opto = 0xff; /* set bit P3.7 turning opto off */ } } void offmsd() { if (buffer[3] == 0x3f) /* if msd = '0' then put blank unstead */ buffer[3] = 0x00; } void pause(j) int j; { int i; for (i = 0; i < j; i++) ; } |