📄 main_v2.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 + -