⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clock.c

📁 基于AT89C51的电子钟源程序和Protel电路图
💻 C
字号:
/*	定时器,可以设置小时和分钟;	可以设置开始时间,和结束时间,在P3.7口输出变化情况(opto=0xFF P3.7=1, opto=0x7F P3.7=0)*/#include <reg52.h>     #include <stdio.h>      unsigned  char sec100,sec,min,hour,day,month,flag1,temp,opto;unsigned char digit,buffer[4],onHour1,onMin1,offHour1,offMin1;char cputick,key,delay,count1;char keyflag, showdelay;unsigned char showsave;//char convert[10] = {0x3F,0x0c,0x76,0x5e,0x4d,0x5b,0x7b,0x0e,0x7f,0x5f};// 数码管的编码,需要取反输出0-9char convert[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};// 各个月的天数char days[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};void pause(int); void scanLED();void manualOnOff();void savetimeOnOff1(); void setmin();void sethour();void setonHour();void setonMin();void setoffHour();void setoffMin();void setday();void setmonth();void showOnce();void savetimeOff1();void blinkset();void time();void timeToBuffer();void dateToBuffer();void blink();void offmsd();void keyexe();void keydelay();void comparetime();/*---------------------------------------------------------------------------*//* 定时器零的中断服务程序 *//*---------------------------------------------------------------------------*/void timer0int (void)  interrupt 1  using 1  {	TL0 = 0;	TH0 |= 0xB8;						// reload timer 0 with 0B800H 22.1184MHZ	cputick++;	time();								// update realtime clock          }/*---------------------------------------------------------------------------*//* 主函数 *//*---------------------------------------------------------------------------*/void main(){	EA = 1;								// 允许所有中断	ET0 = 1;							// 允许定时器0中断 	TMOD |= 0x01;						// timer 0 run 16 bit counter 	TR0 = 1;							// run timer 0 	opto = 0xff;						// 控制P3.7的输出 	cputick = 0;						// 每10ms加1	month = 1;							// 月的初始值	day = 1;							// 日的初始值 	hour = 18;							// 小时的初始值  	min = 0;							// 分钟的初始值  	sec = 0;							// 秒的初始值  	key = -1;							// 首次按键	keyflag = 0;						// 设置键没有按下  	flag1 = 0;	showsave = 0;						// 记录闪烁多少次没有按键自动恢复时间显示  	onHour1 = 18;						// 18:01 turn lamp on  	onMin1 = 01;  	offHour1 = 18;						// 18:02 turn lamp off  	offMin1 = 02;  	count1 = 0;	buffer[0] = 0x00;  	buffer[1] = 0x00;  	buffer[2] = 0x00;  	buffer[3] = 0x00;  	while(1)  	{		while ( cputick < 1)			// 如果定时器中断没有执行,则显一直	  		scanLED();				    // 扫描显示,否则获取时间值,再显示		cputick = 0;		/*----------以下每10ms执行一次---------------------------------------*/    	timeToBuffer();					// 将时间值的7段码输入buffer中    	offmsd();						// 关闭最高位的零显示    	blink();						// 处理秒点的闪烁, 亮50*10ms		blinkset();					    // 处理设置时的闪烁    	keyexe();						// 判断键盘按键,执行相应动作    	keydelay();					    // 延时50*10ms后清除不可按键标志flag1 &= ~0x80    	comparetime();				    // 判断是否到了开始或结束时间		/*-------------------------------------------------------------------*/  	}}/*---------------------------------------------------------------------------*//* 由中断服务程序调用,主要是设置秒分时的变量值 *//*---------------------------------------------------------------------------*/void time (){   	sec100++;	if (sec100 >= 30)		opto |= 0x20;					// set P3.5 to beep off		if (sec100==50||sec100==100)		// 设置时的闪烁间隔	{		showdelay = 25;		flag1 |= 0x08;	}   	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++;				opto &= 0xDF;               // clear bit P3.5 to beep     			if (hour >= 24)     			{					hour = 0;					day++;					if (day > days[month-1])					{						day = 1;						month++;						if (month > 12)							month = 1;					}			    }			} 		}	}}/*----------------------------------------------------------------------------*//* 扫描4个数码管和4个按键, if key pressed key = 0-3 else key = -1 *//*----------------------------------------------------------------------------*/void scanLED(){	int i;	        digit = 0x08;    key = -1;    for( i = 0; i < 4; i++)				// 4-DIGIT scanning    {		P1 = ~buffer[i];				// send complement[segment]			     	P3 = ~digit & opto;				// send complement[digit]	    pause(160);						// 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(){	if (keyflag < 3)		// 如果设置键按下的次数小于3,则显示时间	{		buffer[0] = convert[min%10];	    buffer[1] = convert[min/10];	    buffer[2] = convert[hour%10];	    buffer[3] = convert[hour/10];	}	else if (keyflag < 5)	// 否则显示日期	{		buffer[0] = convert[day%10];	    buffer[1] = convert[day/10];		buffer[2] = convert[month%10];		buffer[3] = convert[month/10];		// 屏蔽0,不显示	    if (buffer[3] == convert[0])				    buffer[3] = 0x00;	    if (buffer[1] == convert[0])				    buffer[1] = 0x00;	}	else if (keyflag < 7)	{		buffer[0] = convert[onMin1%10];		buffer[1] = convert[onMin1/10];		buffer[2] = convert[onHour1%10];		buffer[3] = convert[onHour1/10];		}	else	{		buffer[0] = convert[offMin1%10];		buffer[1] = convert[offMin1/10];		buffer[2] = convert[offHour1%10];		buffer[3] = convert[offHour1/10];	}}/*----------------------------------------------------------------------------*//* 点亮秒针 *//*----------------------------------------------------------------------------*/void blink(){	if((flag1 & 0x04) != 0)				// check bit 2 if set decrement 										// temp until zero    {		temp--;									if (temp != 0)        {  			// 显示日期时不显示秒闪烁			if (keyflag < 3)			{ 				buffer[0] |= 0x80;    	    	buffer[1] |= 0x80;			}        }        else		   	flag1 &= ~0x04;	}}/*----------------------------------------------------------------------------*//* 闪烁设置位*//*----------------------------------------------------------------------------*/void blinkset(){	if((flag1 & 0x08) != 0 && key!=3) // 如果闪烁间隔到且前后两次按键不一样,就闪烁    {		showdelay--;									if (showdelay != 0)        {   			if (keyflag != 0)			{				// 如果是在小时和月份状态				switch (keyflag)				{				case 1:				case 3:				case 5:				case 7:					buffer[3] = 0x00;			// 关闭显示,实现闪烁					buffer[2] = 0x00;					break;								case 2:					buffer[0] = 0x80;			// 关闭显示,实现闪烁					buffer[1] = 0x80;					break;				case 4:				case 6:				case 8:					buffer[0] = 0x00;			// 关闭显示,实现闪烁					buffer[1] = 0x00;					break;					}			}        }        else		{		   	flag1 &= ~0x08;			if (showsave++ > 20)			   // 如果闪烁20次都没有按键,自动恢复时间显示			{				keyflag = 0;				showsave = 0;			}		}	}}/*----------------------------------------------------------------------------*//* 执行键盘命令 *//*----------------------------------------------------------------------------*/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 = 25;					      		switch(key)			{        	case (0):					// key position 0        		manualOnOff();			// service key 0				keyflag=0;        		break;        	case (1):					// key position 1        		savetimeOnOff1();		// service key 1				keyflag=0;        		break;        	case (2):					// key position 2				keyflag++;				// keyflag 1: set hour				if (keyflag>8)			//		   2: set min					keyflag=0;			//		   3: set month											//		   4: set day        		break;        	case (3):					// key position 3				showsave = 0;        		switch(keyflag)				{				case (0):					dateToBuffer();			// show date					break;				case (1):	        		sethour();							break;				case (2):					setmin();					break;				case (3):					setmonth();					break;				case (4):					setday();					break;				case (5):					setonHour();					break;				case (6):					setonMin();					break;				case (7):					setoffHour();					break;				case (8):					setoffMin();					break;				}			}		}    }}/*----------------------------------------------------------------------------*//* 显示日期 *//*----------------------------------------------------------------------------*/void dateToBuffer(){	buffer[0] = convert[day%10];    buffer[1] = convert[day/10];	buffer[2] = convert[month%10];	buffer[3] = convert[month/10];    if (buffer[3] == convert[0])			    buffer[3] = 0x00;    if (buffer[1] == convert[0])			    buffer[1] = 0x00;	showOnce();}/*----------------------------------------------------------------------------*//* 设置小时 *//*----------------------------------------------------------------------------*/void sethour(){	hour++;    if ( hour== 24)    	hour = 0;}void setonHour(){	onHour1++;	if (onHour1 == 24)		onHour1 = 0;}void setoffHour(){	offHour1++;	if (offHour1 == 24)		offHour1 = 0;}/*----------------------------------------------------------------------------*//* 设置分钟 *//*----------------------------------------------------------------------------*/void setmin(){    min++;    sec = 0;    if( min == 60 )    	min = 0;}void setonMin(){	onMin1++;	if (onMin1 == 60)		onMin1 = 0;}void setoffMin(){	offMin1++;	if (offMin1 == 60)		offMin1 = 0;}/*----------------------------------------------------------------------------*//* 设置日 *//*----------------------------------------------------------------------------*/void setday(){	day++;	if (day > days[month-1])		day = 1;}/*----------------------------------------------------------------------------*//* 设置月 *//*----------------------------------------------------------------------------*/void setmonth(){	month++;	if (month > 12)		month = 1;}/*----------------------------------------------------------------------------*//* 设置开始和结束时间 *//*----------------------------------------------------------------------------*/void savetimeOnOff1(){    count1++;    if (count1 == 1)    {    	onHour1 = hour;    	onMin1 = min;    	buffer[0] = 0x00;    	buffer[1] = 0x54;    	buffer[2] = 0x5C;    	buffer[3] = 0x78;				// show "on" at led    	showOnce();    }    else    {        count1 = 0;        savetimeOff1();    }}/*----------------------------------------------------------------------------*//* 保存结束时间 *//*----------------------------------------------------------------------------*/void savetimeOff1(){    offHour1 = hour;    offMin1 = min;    buffer[0] = 0x71;    buffer[1] = 0x71;    buffer[2] = 0x5C;    buffer[3] = 0x78;					// show "off" at led    showOnce();	}/*----------------------------------------------------------------------------*//* 手工点亮 on 或者 off *//*----------------------------------------------------------------------------*/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] = 0x54;        buffer[3] = 0x5C;				// show "on"        showOnce();    }    else    {        buffer[0] = 0;        buffer[1] = 0x71;        buffer[2] = 0x71;        buffer[3] = 0x5C;				// show "off"        showOnce();    }}/*----------------------------------------------------------------------------*//* 显示数码值 *//*----------------------------------------------------------------------------*/void showOnce(){    int i;    for(i=0;i<400;i++)    	scanLED();}/*----------------------------------------------------------------------------*//* 键盘延迟 *//*----------------------------------------------------------------------------*/void keydelay(){    if ((flag1 & 0x80) !=0)    {    	delay--;        if(delay == 0)            flag1 &= ~0x80;    }}/*----------------------------------------------------------------------------*//* 比较是否到了设定的开始或结束时间, 设定opto *//*----------------------------------------------------------------------------*/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] == convert[0])		// if msd = '0' then put blank instead	    buffer[3] = 0x00;}/*----------------------------------------------------------------------------*//* 延迟 *//*----------------------------------------------------------------------------*/void pause(int j){	int i;   	for (i = 0; i < j; i++);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -