led电子钟控制程序.c

来自「一款LED电子钟控制程序 本产品能根据用户设定的时间」· C语言 代码 · 共 545 行

C
545
字号
/*
	定时器,可以设置小时和分钟;
	可以设置开始时间,和结束时间,在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-9
char 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 + =
减小字号Ctrl + -
显示快捷键?