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

📄 日历.txt

📁 这个是用MedWin配合proteus仿真的单片机程序
💻 TXT
字号:
#include<AT89S5X.H>
#define 	SAVEKEY			P32						//显示器件电源开关,自锁开关,低电平有效,按下去有效
#define 	SECLED			P00						//秒计数LED灯;
#define		SEG20			P33						//数码管显示20控制位
#define		BUZZ			P01						//蜂鸣器控制位,高电平有效
#define		K1_SURE 	 	P25
#define		K2_MIN  		P24
#define		K3_HOUR  		P23
#define		K4_DAY_COUNT  	P22
#define		K5_MON_ALARM  	P21
#define		K6_YEAR_TIME 	P20
#define 	uchar unsigned char
/*移位寄存器引脚输入定义*/
#define 	CP_1	P26
#define 	CP_2	P36
#define		B_1		P27
#define		B_2		P37  
/*	十二个数码管选通端口定义*/
sbit WEI1	=	P1^0;
sbit WEI2	=	P1^1;
sbit WEI3	=	P1^2;
sbit WEI4	=	P1^3;
sbit WEI5	=	P1^4;
sbit WEI6	=	P1^5;
sbit WEI7	=	P1^6;
sbit WEI8	=	P1^7;
sbit WEI9	=	P3^0;
sbit WEI10	=	P3^1;
sbit WEI11	=	P3^4;
sbit WEI12	=	P3^5;
uchar SEG[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; /*共阳数码管0-9   16进制代码*/
uchar DC=0,SEC =0,MIN = 59, HOUR = 23,DAY = 19,MON = 4,YEAR=8;	//存放十毫秒、1秒、1分钟、1小时、1天、1月、1年变量
uchar RUNNIAN = 1;DAXIAOYUE = 0;								//  闰年标志,大小月标志,仅用于中断;
uchar TIME_=40;													/*		扫描次数变量			*/
/***************************************************************************************************/
/*延时程序*/
/***************************************************************************************************/
void DELAY(uchar TIME)
{
	uchar P;
	for(;TIME != 0;TIME--)
	{
		for(P=0;P<112;P++);
	}
	
}

/*************************************************************
*******定时器0和1初始化*****************************************
**************************************************************/
void ET0_ET1()
{
	TMOD=0X11;				//T0模式1,T1模式1	相当于00010001B
	ET0=1;					//T0开中断
	ET1=1;					//T1开中断
	PT0=0;					//T0为低优先级
	PT1=1;					//T1为高优先级
	EA=1;					//中断总开关打开
	TH0=0Xd8;				//T0装入初值,实现10ms定时
	TL0=0Xf0;
	
	TH1=0Xfe;				//T1装入初值,实现50ms定时			
	TL1=0X0c;
//	TR0=1;					//开启T0
	TR1=1;					//开启T1
}

/*************************************************************************************************/
/*8位数据从74HC164_1的串行输入端输入,从输出端并行输出*/
/*************************************************************************************************/
void HC164_1(unsigned char DATA_1)
{        
	uchar X;
	for (X = 0;X < 8;X ++) 				//移位8次
	{
		B_1 = (bit)(DATA_1 & 0x01);		//按位输出
		CP_1 = 1;  CP_1 = 0;			//移位寄存器CP脉冲
	 	DATA_1 = DATA_1 >> 1;			  
	}				         
}


/*************************************************************************************************/
/*8位数据从74HC164_2的串行输入端输入,从输出端并行输出*/
/*************************************************************************************************/
void HC164_2(unsigned char DATA_2)
{        
	uchar Y;
	for (Y = 0;Y < 8;Y ++) 			//移位8次
	{
		B_2 = (bit)(DATA_2 & 0x01);	//按位输出
		CP_2 = 1;  CP_2 = 0;			//移位寄存器CP脉冲
	 	DATA_2 = DATA_2 >> 1;			  
	}				         
}


/****************************************************************************************************/
/*动态扫描显示程序*/
/****************************************************************************************************/
void DISPALYSEG()           
{
	uchar DISPLY[13];							//存放显示变量
	/***************************************************
	*******转换显示数据*********************************
	***************************************************/
		/*下面的低六位由164_1输出*/
	DISPLY[1] 	= 	SEC		%	10;
	DISPLY[2] 	= 	SEC		/	10;
	DISPLY[3]	=	MIN		%	10;
	DISPLY[4]	=	MIN		/	10;
	DISPLY[5]	=	HOUR	%	10;
	DISPLY[6]  	=	HOUR	/	10;
	/*下面高六位由164_2输出*/
	DISPLY[7]  	=	DAY		%	10;
	DISPLY[8]  	=	DAY		/	10;
	DISPLY[9]  	=	MON		%	10;
	DISPLY[10]  =	MON		/	10;
	DISPLY[11]  =	YEAR	%	10;
	DISPLY[12]  =	YEAR	/	10;

	/********************************
	转换完毕,开始显示
	**********************************/
	//低六位显示秒,分钟,小时
	HC164_1(SEG[DISPLY[1]]);
	WEI1 = 1;
	DELAY(1);
	WEI1 = 0;

	HC164_1(SEG[DISPLY[2]]);
	WEI2 = 1;
	DELAY(1);
	WEI2 = 0;

	HC164_1(SEG[DISPLY[3]]);
	WEI3 = 1;
	DELAY(1);
	WEI3 = 0;

	HC164_1(SEG[DISPLY[4]]);
	WEI4 = 1;
	DELAY(1);
	WEI4 = 0;

	HC164_1(SEG[DISPLY[5]]);
	WEI5 = 1;
	DELAY(1);
	WEI5 = 0;

	HC164_1(SEG[DISPLY[6]]);
	WEI6 = 1;
	DELAY(1);
	WEI6 = 0;
	//高六位显示天,月,年
	HC164_2(SEG[DISPLY[7]]);
	WEI7 = 1;
	DELAY(1);
	WEI7 = 0;

	HC164_2(SEG[DISPLY[8]]);
	WEI8 = 1;
	DELAY(1);
	WEI8 = 0;

	HC164_2(SEG[DISPLY[9]]);
	WEI9 = 1;
	DELAY(1);
	WEI9 = 0;

	HC164_2(SEG[DISPLY[10]]);
	WEI10 = 1;
	DELAY(1);
	WEI10 = 0;

	HC164_2(SEG[DISPLY[11]]);
	WEI11 = 1;
	DELAY(1);
	WEI11 = 0;

	HC164_2(SEG[DISPLY[12]]);
	WEI12 = 1;
	DELAY(1);
	WEI12 = 0;		
}


/***************************************************************************************************/
/* 定时计数器0的中断服务子程序 */
/***************************************************************************************************/
/*void ET_0()	interrupt 1  using 1
{
	TH1 = 0Xd8;				//T0重新装入初值,继续10ms定时			
	TL1 = 0Xf0;
}
*/
/***************************************************************************************************/
/* 定时计数器1的中断服务子程序 ,控制数码管时间变量,判断闰年,大小月*/
/***************************************************************************************************/
void ET_1()	interrupt 3  using 2
{
	TH1 = 0Xfe;			//T1重新装入初值,继续50ms定时			
	TL1 = 0X0c;
	DC=DC + 1;				//50毫秒计数
	if(DC == 20)			//满1秒?
	{
		SEC= SEC + 1;		//秒计数加1
		if(SAVEKEY == 0)	//显示器件开关是否打开?打开了
		{
			SECLED = 0;		//LED亮
		}
		if(SAVEKEY == 1)	//没打开
		{
			SECLED = 1;		//LED灭
		}
	}
	if(DC == 40)			//满2秒?
	{
		DC = 0;				//清零十毫秒计数
		SEC= SEC + 1;		//秒计数加1
		if(SAVEKEY == 0)	//显示器件开关是否打开?打开了。
		{
			SECLED = 1;		//LED灭
		}
		if(SAVEKEY == 1)	//没有打开
		{
			SECLED = 1;		//LED灭
		}
	}
	if(SEC == 60)			//满一分钟?
	{
		SEC = 0;			//清零秒计数
		MIN = MIN + 1;		//分钟计数加1
	}
	if(MIN == 60)			//满一小时?
	{
		MIN = 0;			//清零分计数
		HOUR = HOUR+1;		//小时计数加1
	}
	if(HOUR == 24)			//满1天?
	{
		HOUR = 0;			//清0小时计数
		DAY = DAY +1;		//天计数加1
	}
/*闰年判断,大小月判断,*/
	RUNNIAN = YEAR % 4;
	if(RUNNIAN == 0)				//是闰年?
	{
		if(MON == 2)				//二月到了?
		{
			if (DAY > 28)			//超过28天了?
			{
				DAY = 1;			//天初始化
				MON = 3;			//月+1
			}
		}
	}
	if(RUNNIAN != 0 )				//不是闰年
	{	
		if(MON == 2)				//2月到了?	
		{
			if (DAY > 29)			//超过29天了?
			{
				MON = 3;			//月+1
				DAY = 1;			//天初始化
			}			
		}
	}
		
	switch(MON)
	{
		case 1:		DAXIAOYUE = 1;		
		case 3:		DAXIAOYUE = 1;
		case 4:		DAXIAOYUE = 0;	
		case 5:		DAXIAOYUE = 1;
		case 6:		DAXIAOYUE = 0;	
		case 7:		DAXIAOYUE = 1;
		case 8:		DAXIAOYUE = 1;
		case 9:		DAXIAOYUE = 0;
		case 10:	DAXIAOYUE = 1;	
		case 11:	DAXIAOYUE = 0;
		case 12:	DAXIAOYUE = 1;
	
	}
	if (DAXIAOYUE == 1)			//大月
	{
		if(DAY > 31)			//超过31天了
		{
			MON = MON + 1;		//月+1
			DAY = 1;
		}
	}
	if(DAXIAOYUE == 0)			//小月
	{
		if(DAY > 30)			//超过30天了?
		{
			MON = MON+1;		//月+1
			DAY = 1;
		}
	}
	if (MON > 12)				//超过1年了
	{
		YEAR = YEAR + 1;
		MON  = 1;
	}
	if (YEAR > 28)				//超过2028年?溢出
	{
		YEAR = 8;				//初始化
	}
}
/****************************************************************************************************
/***************************************蜂鸣器嘟嘟两声程序******************************************/
/****************************************************************************************************/
void BUZZ_TWO()
{
	uchar ii;	
	BUZZ = 1;					//蜂鸣器发声
	for(ii = 0;ii < 50;ii++)	//通过扫描数码管延时一段时间,实现延时
	{
		DISPALYSEG();
	}
	BUZZ = 0;					//蜂鸣器关闭
	for(ii = 0;ii < 50;ii++)	//通过扫描数码管延时一段时间,实现延时
	{
		DISPALYSEG();
	}
	BUZZ = 1;					//蜂鸣器发声
	for(ii = 0;ii < 50;ii++)	//通过扫描数码管延时一段时间,实现延时
	{
		DISPALYSEG();
	}
	BUZZ = 0;					//蜂鸣器关闭
}

/***************************************************************************************************/
/* 键盘设置 */
/***************************************************************************************************/
void KEY_()
{	
	uchar jj,RUNNIANBIAOZHI,	DAXIAOYUE_,		END = 0;
	ET1 = 0;TR1 = 0;						//首先关闭定时器1中断,和定时开关
	for (;END == 0;)
	{
		/* 判断K6是否按下*/					
		if (K6_YEAR_TIME == 0)					//K6按下?
		{
			YEAR = YEAR +1;
			if (YEAR > 28)						//年溢出2028?
			{
				YEAR = 8;						//超过出则初始化
			}
			RUNNIANBIAOZHI = YEAR % 4;			//此标志与定时器1中断的标志位有区别
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();
			}
		}
		/* 判断K5是否按下*/
		if(K5_MON_ALARM == 0)					//k5按下?
		{
			MON = MON + 1;						//月加1
			if (MON == 13)						//超过1年了?
			{
				MON = 1;						//超过出则初始化
			}
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();	
			}
		}
		/* 判断K4是否按下*/
		if(K4_DAY_COUNT == 0)					//k4按下?
		{
			DAY = DAY + 1;						//天+1
			if (RUNNIANBIAOZHI == 0)			//是闰年?
			{
				if (MON == 2)					//是二月?	
				{
					if (DAY >28)				//超过28天了?
					{
						DAY = 1;				//超过出则初始化
					}		
				}
			}	
			if (RUNNIANBIAOZHI == 1)			//不是闰年?
			{
				if (MON == 2)					//是二月?	
				{
					if (DAY >29)				//超过29天了?
					{
						DAY = 1;				//超过出则初始化
					}
				}
			}	
			switch(MON)
			{
				case 1:		DAXIAOYUE_ = 1;		
				case 3:		DAXIAOYUE_ = 1;
				case 4:		DAXIAOYUE_ = 0;	
				case 5:		DAXIAOYUE_ = 1;
				case 6:		DAXIAOYUE_ = 0;	
				case 7:		DAXIAOYUE_ = 1;
				case 8:		DAXIAOYUE_ = 1;
				case 9:		DAXIAOYUE_ = 0;
				case 10:	DAXIAOYUE_ = 1;	
				case 11:	DAXIAOYUE_ = 0;
				case 12:	DAXIAOYUE_ = 1;
			}	
			if (DAXIAOYUE_ == 1)				//大月
			{
				if(DAY > 31)					//超过31天了
				{
					DAY = 1;
				}
			}
			if(DAXIAOYUE_ == 0)					//小月
			{
				if(DAY > 30)					//超过30天了?
				{
					DAY = 1;
				}
			}			
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时	
			{
				DISPALYSEG();
			}
		}
		/* 判断K3是否按下*/
		if (K3_HOUR == 0)						//k3按下?
		{
			HOUR = HOUR + 1;					//小时加1
			if (HOUR == 24)						//超过24小时了?
			{
				HOUR = 0;						//小时初始化
			}
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();
			}
		}
		/* 判断K2是否按下*/
		if(K2_MIN == 0)						//k2按下?
		{
			MIN = MIN + 1;						//小时加1
			if (MIN == 60)						//超过60分钟了?
			{
				MIN = 0;						//分钟初始化
			}
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();
			}
		}
		/* 判断K1是否按下*/
		if (K1_SURE == 0)						//k1按下?
		{
			BUZZ_TWO();							//蜂鸣器嘟嘟两声
			ET1 = 1;TR1 = 1;					//开启定时器1中断,和定时开关
			for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();
			}
			END = 1;
		}
		/*没有按键按下,则只扫描显示*/
		for(jj = 0;jj < TIME_;jj++)			//通过扫描数码管延时一段时间,实现延时
			{
				DISPALYSEG();
			}
	}
}
/***************************************************************************************************/
/* 按键设置时间程序 */
/***************************************************************************************************/
void TIME_SHEZHI()
{
	uchar jj;
/****************************时间设置开关K6是否按下*************************************************/
	if(K6_YEAR_TIME == 0)						//K6按下?开始设置时间
	{
		for(jj = 0;jj < TIME_;jj++)				//通过扫描数码管延时一段时间,实现延时
		{
			DISPALYSEG();
		}
		KEY_();									//开始进行设置
	}												
}

/***************************************************************************************************/
/* 按键设置闹钟程序 */
/***************************************************************************************************/
void ALARM_SHEZHI()
{
	uchar jj;
/****************************时间设置开关K6是否按下*************************************************/
	if(K5_MON_ALARM == 0)						//K5按下?开始设置闹钟
	{
		for(jj = 0;jj < TIME_;jj++)				//通过扫描数码管延时一段时间,实现延时
		{
			DISPALYSEG();
		}
		KEY_();									//开始进行设置	
	}												
}

/***************************************************************************************************/
/*主程序*/
/***************************************************************************************************/
void main()                     
{
	SAVEKEY = 1;				//初始化节电开关SAVEKEY,
	SEG20   = 0;				//关闭数码管"20"位
	P2 = 0XFF;				//初始化P2,P2的0~5引脚作为输入
	ET0_ET1();				//初始化定时器0、1
	while(1)     			//无穷循环
	{ 
		if (SAVEKEY == 1)	//进入省电模式?
		{
			SEG20 = 0;		//20显示开关关闭
		}
		if (SAVEKEY == 0)	//显示器件打开?
		{
			SEG20 = 1;		//20显示开关打开
			DISPALYSEG();
			TIME_SHEZHI();
			ALARM_SHEZHI();
		}
		
/*		WDTRST = 0X1E;		//开启WDT,循环执行,不断喂狗
		WDTRST = 0XE1;*/
	}		        
}
























⌨️ 快捷键说明

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