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

📄 main_v2.c

📁 KEIL下编的SST89E58单片机万年历(定时器)程序
💻 C
字号:
/*
 *	Copyright (C) 2007, 华中科技大学电气与电子科技创新中心
 *	All Rights Reserved.
 *	
 *	文件名:		main.c
 *	文件描述:   万年历主程序
 *			
 *	当前版本:	1.0
 *	作者:		Zuowenping(fmku007@163.com)
 *	完成日期:	2008年10月24日
 *	
*/
#include "reg51.h"
#include "intrins.h"
#include "lcd1602.h"
#include "main.h"
#include <string.h>


#define MAIN_COUN 99            //中断计数值
#define MAX_NO_OP_TIME 10 		//最大无操作时间(从调整状态恢复到正常显示状态)
					
#define KEY1 0xfe				//四个按键键码
#define KEY2 0xfd
#define KEY3 0xfb
#define KEY4 0xf7

#define STOP  0x00				//秒表停止命令
#define START 0x01				//秒表启动命令
#define PAUSE 0x02				//秒表暂停命令(依然计数)
#define STPAU 0x03				//秒表暂停、不计数	

#define ADD    0x01				//时间调整命令:加
#define SUB	   0x02				//时间调整命令:减


u8 int_coun=0,sec=0,sec_pre=0;	//秒寄存器
u8 wink_mode=0;					//闪烁控制模式(时间调整用)
u8 key_temp=0;					//按键共享寄存器
u16 key_coun=0;					//按键计数寄存器(判断按键时长)
u8 key_speed=0;					//根据按键时长得到不同的调节速度
u8 max_speed=0;					//调节速度时长门限
u8 sys_mode=1;					//系统模式  0:时间调级 1:正常时间显示 2:计数模式3:农历模式
u8 sys_mode_pre=10;				//上一模式暂存
u8 stop_mode=0;  				//stopwatch工作模式 0:停止1:启动2:暂停仍计数3:暂停不计数
bit key_flag=0;					//按键标志		
bit adj_flag=0;					//时间调节标志
bit wink_ena=1;					//闪烁使能控制
bit stop_ena=0;					//秒表使能控制
bit disp_flag=0;				//正在显示标志,避免因为在显示过程中进中断调用显示程序,使LCD混乱

u8 no_op_time=0;				//无操作记时寄存器


u8 hour=2,min=7,month=10,day=26;
u16 m_day=365,year=2008;		//时间相关寄存器

u8 stop_hour=0,stop_min=0,stop_sec=0,stop_ms=0;
u8 stop_ms_pre=0;				//秒表时间相关寄存器


static u8 code non_leap_table[]={31,28,31,30,31,30,31,31,30,31,30,31,31,29,31,30,31,30,31,31,30,31,30,31};  //0-11:non_leap  12-23  leap year month table
								//平年、闰年每月天数表
	

void int_svr() interrupt 3		//定时器1中断服务程序
{	
	TH1=220;
	TL1=37;
//	P3=P3^0x01;
		if(int_coun<MAIN_COUN)
	 		int_coun+=1;
		else 
		{	int_coun=0;
			if(sec<59)
				sec+=1;
			else
				sec=0;
		}
		if(int_coun==MAIN_COUN/2&&wink_ena&&!disp_flag)
		{/*put_char(13,1,32);*/wink_set(wink_mode);}

		if(stop_mode==1||stop_mode==2)
			{
			calc_stop_watch();
			if(stop_ms<99)
				stop_ms+=1;
			else
				stop_ms=0;
					
			}
		else if(stop_mode==0)
			{
				stop_ms=0;
				stop_hour=0;
				stop_min=0;
				stop_sec=0;
			}
			
		if(stop_mode!=2&&stop_ena&&sys_mode==2&&!disp_flag)display();   //是暂停则不显示更新数据
}


void main()
{  
	Sys_Init();
	while(1)
	{
	if(sec_pre!=sec)
		{
			calc_time();
			if(sys_mode==1||sys_mode==0)
			display();
			sec_pre=sec;
		}

	key_scan();
	key_proc();
	}	
}

void Sys_Init()
{
	lcd_init();
	sys_config();
	TMOD=0x10;
	TH1=220;
	TL1=37;
	EA=1;
	ET1=1;
	TR1=1;
}

//时间计算函数
void calc_time()
{
	if(day>non_leap_table[month-1+(calc_day(year)?12:0)])
		day=non_leap_table[month-1+(calc_day(year)?12:0)];
	if(sec_pre==59)
		{
		if(min<59)
			min+=1;
		else 
			{
			min=0;
			if(hour<23)
				hour+=1;
			else
				{
				hour=0;
				if(day<non_leap_table[month-1+(calc_day(year)?12:0)])
					day+=1;
				else
					{
					day=1;
					if(month<12)
						month+=1;
					else
						{
						month=1;
						year+=1;
						}
					}
				}
			 }
		 }
}


void calc_stop_watch()
{
if(stop_ms==99)
	{
		if(stop_min<59)
			stop_min+=1;
		else 
			{
			stop_min=0;
			if(stop_hour<99)
				stop_hour+=1;
			else
				{
				stop_hour=0;
				}
			}
	}
}


//判断是否为闰年
unsigned char calc_day(u16 year)
{
	if((year%4==0&&year%100!=0)||year%400==0)
		return 1;
	else
		return 0;
}
//显示子程序
void display()
{
	disp_flag=1;
		if(sys_mode==0||sys_mode==1)
				{
				put_char(0,0,year/1000+48);
				put_char(1,0,(year%1000)/100+48);
				put_char(2,0,year%1000%100/10+48);
				put_char(3,0,year%1000%100%10+48);


				put_char(5,0,month/10+48);
				put_char(6,0,month%10+48);


				put_char(8,0,day/10+48);	
				put_char(9,0,day%10+48);

				put_char(8,1,hour/10+48);
				put_char(9,1,hour%10+48);

				put_char(11,1,min/10+48);
				put_char(12,1,min%10+48);

				put_char(14,1,sec/10+48);
				put_char(15,1,sec%10+48);
	
				put_char(4,0,'-');
				put_char(7,0,'-');
				put_char(10,1,':');	
				put_char(13,1,':');
				}
		 else if(sys_mode==2)
		 		{
				put_char(8,1,stop_hour/10+48);
				put_char(9,1,stop_hour%10+48);

				put_char(11,1,stop_min/10+48);
				put_char(12,1,stop_min%10+48);

				put_char(14,1,stop_sec/10+48);
				put_char(15,1,stop_sec%10+48);
				
				put_char(14,1,stop_ms/10+48);
				put_char(15,1,stop_ms%10+48);
				put_char(10,1,':');	
				put_char(13,1,':');
				switch(stop_mode)
				{
				case 0:
					put_str("STOP ",1);
					break;
				case 1:
				case 2:
					put_str("START",1);
					break;
				case 3:
					put_str("PAUSE",1);
					break;
				
				}
				}
	disp_flag=0;	 		
}

void delay(u16 timeinms)
{
	u16 i,j;
	for (i=timeinms;i>0;i--)
		for(j=0;j<1000;j++)
			_nop_();
}

void key_scan()
{
	P1=0xFF;
	if(P1!=0xFF)
		{
			key_temp=P1;
			delay(2);
			if(key_temp==P1&&key_coun<65535)
					key_coun+=1;
		}
	 else
		key_coun=0;
}

void key_proc()
{
//按键变速处理
	if(key_coun>200)
		max_speed=2;
	else if(key_coun>100)
		max_speed=15;
	else 
		max_speed=30;

//长按键处理
	if(key_coun>50)
		{
		  	if(key_temp==KEY1)
				{
					if(sys_mode==1)
						sys_mode=0;
					sys_config();
				}
		  	

			if(key_temp==KEY2)
				{
				if(key_speed>max_speed)
					{
					if(wink_mode==1)
						{year-=1;no_op_time=0;display();}
					else if(wink_mode==2)
					value_adj(&month,1,12,SUB);
					else if(wink_mode==3)
					value_adj(&day,1,non_leap_table[month-1+(calc_day(year)?12:0)],SUB);
					else if(wink_mode==4)
					value_adj(&hour,0,23,SUB);
					else if(wink_mode==5)
					value_adj(&min,0,59,SUB);
					else if(wink_mode==6)
					sec=0;
					else;

					key_speed=0;
					}
				key_speed+=1;
				
				}

		  	if(key_temp==KEY3)
				{
				if(key_speed>max_speed)
					{
					if(wink_mode==1)
						{year+=1;no_op_time=0;display();}
					else if(wink_mode==2)
					value_adj(&month,1,12,ADD);
					else if(wink_mode==3)
					value_adj(&day,1,non_leap_table[month-1+(calc_day(year)?12:0)],ADD);
					else if(wink_mode==4)
					value_adj(&hour,0,23,ADD);
					else if(wink_mode==5)
					value_adj(&min,0,59,ADD);
					else if(wink_mode==6)
					sec=0;
					else;
					//value_adj(&min,0,59,SUB);
					key_speed=0;
					}
				key_speed+=1;
				}


			return;
		}
	if(key_coun>3&&(P1!=key_temp))
	{
			switch(key_temp) {
				case KEY1:
					{
						if(wink_mode)
							{
								if(wink_mode<6)
									wink_mode+=1;
								else
									wink_mode=1;
								no_op_time=0;
							}
						else if(sys_mode<3)
							sys_mode+=1;
						else
							sys_mode=1;
						sys_config();
						break;
					}
				case KEY2:
					{
					if(wink_mode==1)
						{year-=1;no_op_time=0;display();}
					else if(wink_mode==2)
					value_adj(&month,1,12,SUB);
					else if(wink_mode==3)
					value_adj(&day,1,non_leap_table[month-1+(calc_day(year)?12:0)],SUB);
					else if(wink_mode==4)
					value_adj(&hour,0,23,SUB);
					else if(wink_mode==5)
					value_adj(&min,0,59,SUB);
					else if(wink_mode==6)
					sec=0;
					else if(sys_mode==2)
						{
						if(stop_mode==1)
							stop_mode=2;
						else if(stop_mode==2)
							stop_mode=1;
						else if(stop_mode==3)
							stop_mode=0;
						
						}
					else;
					break;
					}
				case KEY3:					
					{
					if(wink_mode==1)
						{year+=1;no_op_time=0;display();}
					else if(wink_mode==2)
					value_adj(&month,1,12,ADD);
					else if(wink_mode==3)
					value_adj(&day,1,non_leap_table[month-1+(calc_day(year)?12:0)],ADD);
					else if(wink_mode==4)
					value_adj(&hour,0,23,ADD);
					else if(wink_mode==5)
					value_adj(&min,0,59,ADD);
					else if(wink_mode==6)
					sec=0;
					else if(sys_mode==2)
						{
						if(stop_mode==0)
							stop_mode=1;
						else if(stop_mode==1)
							stop_mode=3;
						else if(stop_mode==3)
							stop_mode=1;
						}
					else;
					break;
					}
				case KEY4:
					{
						if(sys_mode==0)
						sys_mode=1;
						sys_config();
						break;
					}
				default: break;	
				}	
	}	
}
void value_adj(u8 *value,u8 min,u8 max,u8 cmd)
{
	wink_ena=0;
	no_op_time=0;
	if(cmd==ADD)
		{
		if(*value<max)
			*value+=1;
		else
			*value=min;
		display();
		}
	else if(cmd==SUB)
		{
		if(*value>min)
			*value-=1;
		else
			*value=max;
		display();
		}
	 else
	 	return;
	 wink_ena=1;
}


//时间调整闪屏
void wink_set(u8 wink)
{
	switch(wink)
	{
	case 0:
		break;
	case 1:
		{ 		
			put_char(0,0,' ');
			put_char(1,0,' ');
			put_char(2,0,' ');
			put_char(3,0,' ');
			break;
		}
	case 2:
		{
			put_char(5,0,' ');
			put_char(6,0,' ');
			break;
		}
	case 3:
		{
			put_char(8,0,' ');
			put_char(9,0,' ');
			break;
		}
	case 4:
		{
			put_char(8,1,' ');
			put_char(9,1,' ');
			break;
		}
	case 5:
		{
			put_char(11,1,' ');
			put_char(12,1,' ');
			break;
		}
	case 6:
		{
			put_char(14,1,' ');
			put_char(15,1,' ');
			break;
		}
	default: break;
	}
	no_op_time+=1;
	if(no_op_time>MAX_NO_OP_TIME)
		{
		sys_mode=1;
		sys_config();
		no_op_time=0;
		}
}

void sys_config()
{
	if(sys_mode==sys_mode_pre)
		return;
	if(sys_mode==0)
		{
		wink_ena=1;
		wink_mode=1;
		no_op_time=0;
		put_str("TIMEADJ",1);
		display();
		}
	else if(sys_mode==1)
		{
		wink_mode=0;
		put_str("                ",0);
		put_str("TIME            ",1);
		display();
		}
	
	else if(sys_mode==2)
		{
		wink_ena=0;
		put_str("   STOPWATCH    ",0);
		put_str("                ",1);
		display();
		stop_ena=1;
		}
	else if(sys_mode==3)
		{
		wink_ena=0;
		put_str("                ",1);
		put_str("    Calander    ",0);
		lon_calander();
		stop_ena=0;
		}
		
	sys_mode_pre=sys_mode;
}
void lon_calander()
{
	u16 dayto11=0;
	u16 daytochun=0;
	u16 temp_day=0;
	bit same_year_flag;
	u8 lon_year_table[13];
	u16 lon_year;
	u8 lon_month=0,lon_day=0;
	u8 max_month;
	u8 leap;
	u8 i;

	if(year>2100||year<1901)
		{
		put_str(" OUT OF RANGE!  ",1);
		return;
		}

	for(i=0;i<month-1;i++)
		dayto11+=non_leap_table[i+(calc_day(year)?12:0)];
/*		put_char(2,0,dayto11/100+48);
		put_char(3,0,dayto11%100/10+48);
		put_char(4,0,dayto11%100%10+48);*/

		dayto11+=day;
    for(i=1;i<((calender_tab[year-1901][2]&0x60)>>5);i++)
		daytochun+=non_leap_table[i+(calc_day(year)?12:0)-1];
		daytochun+=(calender_tab[year-1901][2]&0x1f);


	if(dayto11>=daytochun)
		{
		same_year_flag=1;
		daytochun=dayto11-daytochun+1;
		lon_year=year;
		}
	else
		{
		same_year_flag=0;
		daytochun=daytochun-dayto11;
		lon_year=year-1;
		}

	for(i=0;i<13;i++)
		{
		if(i<4)
			lon_year_table[3-i]=((calender_tab[lon_year-1901][0]>>i)&0x01)?30:29;
		else if(i>=4&&i<12)
			lon_year_table[i]=((calender_tab[lon_year-1901][1]<<(i-4))&0x80)?30:29;
		else
			lon_year_table[12]=(calender_tab[lon_year-1901][2]&0x80)?30:29;
		}

		leap=((calender_tab[lon_year-1901][0]&0xf0)>>4);

	 if(leap==0)
	 	max_month=12;
	 else
	 	{
		max_month=13;
		put_char(15,0,0xff);
		}

		if(same_year_flag)
			{
				for(lon_month=0;lon_month<max_month;lon_month++)	
				{
				temp_day+=lon_year_table[lon_month];	
				if(temp_day>=daytochun)
						{
						lon_day=daytochun+lon_year_table[lon_month]-temp_day;
						lon_month+=1;
						break;
						}
				}
			}
		else
			{
				for(lon_month=max_month-1;lon_month>=0;lon_month--)
				{
					temp_day+=lon_year_table[lon_month];	
					if(temp_day>=daytochun)
						{
						lon_day=temp_day-daytochun+1;
						lon_month+=1;
						break;
						}
					
				}					
				
			}

		  		put_char(3,1,lon_year/1000+48);
				put_char(4,1,(lon_year%1000)/100+48);
				put_char(5,1,lon_year%1000%100/10+48);
				put_char(6,1,lon_year%1000%100%10+48);
				if(leap)
				{
				if(lon_month==(leap+1))
					put_str("LM",1);
				if(lon_month>leap)
					lon_month-=1;
				}
				put_char(8,1,lon_month/10+48);
				put_char(9,1,lon_month%10+48);


				put_char(11,1,lon_day/10+48);	
				put_char(12,1,lon_day%10+48);
				put_char(7,1,'-');
				put_char(10,1,'-');
}

⌨️ 快捷键说明

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