万年历代码文档格式.docx
《万年历代码文档格式.docx》由会员分享,可在线阅读,更多相关《万年历代码文档格式.docx(14页珍藏版)》请在冰点文库上搜索。
/*Date:
2008,5,31*/
/*Author:
lhy*/
/*Version:
v1.3*/
/*Rework:
/*ReworkDate:
2008.6.26*/
/**/
/*Comments:
*/
/*1,使用Atmega8内部RTC(实时时钟,32.768KHz)*/
/*2,显示使用LCD1620*/
/*3,在Timer2中断中刷新显示,精度提高1S@5H*/
/*4,加入星期显示*/
/*5,加入农历换算*/
/*6,秒末位大于等于5时,显示公历:
Solar年月日*/
/*7,SolarYear>
2099或SolarYear<
1900,*/
/*显示"
Outofrange!
"
/*8,加入手动调整日期和时间*/
#include<
iom8v.h>
macros.h>
#defineDataPortPullupPORTD
#defineDataPortDirectionDDRD
#defineReadLCDPinPIND
#defineCtrlPortPullupPORTC
#defineCtrlPortDirectionDDRC
#defineRS_BitPC0
#defineRW_BitPC1
#defineE_BitPC2
#include"
#defineClkTcnt20x80
/****************变量声明********************/
unsignedintYear=2008;
//年变量
unsignedcharMonth=6;
//月变量
unsignedcharDay=1;
unsignedcharHour=12;
//小时
unsignedcharMin=0;
//分钟
unsignedcharSec=0;
//秒
unsignedcharYearBit1,YearBit2,YearBit3,YearBit4;
unsignedcharMonthBit1,MonthBit2;
unsignedcharDayBit1,DayBit2;
unsignedcharHourBit1,HourBit2;
unsignedcharMinBit1,MinBit2;
unsignedcharSecBit1,SecBit2;
unsignedcharWeek[][4]=
{"
Mon"
"
Tue"
Wed"
Thu"
Fri"
Sat"
Sun"
};
unsignedcharChangeSymbol[][5]={"
-Yar"
-Mth"
-Day"
-Hor"
-Min"
unsignedcharLeapYearWeekTable[]={3,6,0,3,5,1,3,6,2,4,0,2};
//闰年星期偏差表
unsignedcharUnLeapWeekTable[]={4,0,0,3,5,1,3,6,2,4,0,2};
unsignedcharTodayWeek=0;
unsignedcharLeapYearBit=0;
//为0时,平年
unsignedcharLunarData[]={0,0,0,0};
unsignedcharLunarYear1,LunarYear2,LunarYear3,LunarYear4,LunarMonth1,LunARMonth2,LunarDay1,LunarDay2;
unsignedcharLunarConvertBit;
//0,农历转换成功
unsignedcharCalendarStopBit;
//1,时钟暂停
unsignedcharOldKeyNum=0;
unsignedcharNewKeyNum=0;
unsignedcharModeSelect=0;
unsignedcharChangeModeBit=0;
//ModeSelect!
=0时,为1,标志现在处于更改时间状态
unsignedcharSecOddBit=0;
//秒为偶数时,此为0,否则为1
staticunsignedcharconstLunarDayCode1[9]=
{0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3};
staticunsignedshortconstLunarDayCode2[3]={0x111,0x130,0x14e};
/**************************
***********子函数**********
*************************/
voidPortInit(void)//端口初始化
{
DDRC&
=~((1<
<
PC3)|(1<
PC4)|(1<
PC5));
PORTC|=(1<
PC5);
}
voidTimer2Init(void)//timer2初始化
TCCR2=0x00;
//stop
ASSR=0x08;
//setasyncmode
TCNT2=ClkTcnt2;
//setup
TCCR2=0x06;
//start
voidTimer2Ovf(void)//timer2中断函数
//reloadcountervalue
Sec+=1;
AskLeapYear();
SolarCount();
CountWeek();
LunarCount();
//先判断是否转换成功,然后再计算各位显示数值
if(ModeSelect==0)
{
LCDispClear();
DispUpdate();
}
voidAskLeapYear(void)
if(((Year%4==0)&
&
(Year%100!
=0))||Year%400==0)//判断是否为闰年
LeapYearBit=1;
else
LeapYearBit=0;
voidSolarCount(void)//计算各位显示值
if(Sec>
59)
Sec=0;
Min++;
if(Min>
Min=0;
Hour++;
if(Hour>
23)
Hour=0;
Day++;
if(((Month==1)||(Month==3)||(Month==5)||(Month==7)||(Month==8)||(Month==10)||(Month==12))&
(Day>
31))
Month++;
Day=1;
elseif(((Month==4)||(Month==6)||(Month==9)||(Month==11))&
30))
elseif(Month==2)
if(LeapYearBit==1)//如果是闰年
if(Day>
29)
elseif(Day>
28)//平年
if(Month>
12)
Month=1;
Year++;
//计算各位的值
YearBit1=Year/1000;
YearBit2=Year%1000/100;
YearBit3=Year%100/10;
YearBit4=Year%10;
MonthBit1=Month/10;
MonthBit2=Month%10;
DayBit1=Day/10;
DayBit2=Day%10;
HourBit1=Hour/10;
HourBit2=Hour%10;
MinBit1=Min/10;
MinBit2=Min%10;
SecBit1=Sec/10;
SecBit2=Sec%10;
}
voidDeviceInit(void)//MCU初始化
CLI();
PortInit();
Timer2Init();
MCUCR=0x00;
GICR=0x00;
TIMSK=0x40;
LCD_Init();
SEI();
//更新显示
voidDispUpdate(void)
if((SecBit2>
=5)||(ModeSelect!
=0))//秒末位大于5时,显示公历
PutStringLCD(0,0,"
Solar"
);
PutNumberLCD(0,6,YearBit1);
PutNumberLCD(0,7,YearBit2);
PutNumberLCD(0,8,YearBit3);
PutNumberLCD(0,9,YearBit4);
PutNumberLCD(0,11,MonthBit1);
PutNumberLCD(0,12,MonthBit2);
PutNumberLCD(0,14,DayBit1);
PutNumberLCD(0,15,DayBit2);
elseif(LunarConvertBit==1)//秒末位小于5并且农历转换成功时,显示农历
Lunar"
PutNumberLCD(0,6,LunarYear1);
PutNumberLCD(0,7,LunarYear2);
PutNumberLCD(0,8,LunarYear3);
PutNumberLCD(0,9,LunarYear4);
PutNumberLCD(0,11,LunARMonth1);
PutNumberLCD(0,12,LunARMonth2);
PutNumberLCD(0,14,LunarDay1);
PutNumberLCD(0,15,LunarDay2);
PutNumberLCD(1,0,HourBit1);
PutNumberLCD(1,1,HourBit2);
if(SecOddBit)
PutOneCharLCD(1,2,"
:
PutNumberLCD(1,3,MinBit1);
PutNumberLCD(1,4,MinBit2);
PutOneCharLCD(1,5,"
PutNumberLCD(1,6,SecBit1);
PutNumberLCD(1,7,SecBit2);
PutStringLCD(1,9,Week[TodayWeek]);
if(ChangeModeBit&
SecOddBit)
PutStringLCD(1,12,ChangeSymbol[ModeSelect-1]);
voidCountWeek(void)
if(LeapYearBit==1)
TodayWeek=((Year/100%4*5)+(Year%100/4*5)+(Year%4)+1+Day+LeapYearWeekTable[Month-1])%7;
TodayWeek=((Year/100%4*5)+(Year%100/4*5)+(Year%4)+1+Day+UnLeapWeekTable[Month-1])%7;
voidKeyScan(void)
{if((PINC&
(1<
PC5))==0)
OldKeyNum=1;
elseif((PINC&
PC4))==0)
OldKeyNum=2;
PC3))==0)
OldKeyNum=3;
}
if((PINC&
(1<
PC5))&
(PINC&
PC4))&
PC3)))//判断是否有按键按下
NewKeyNum=OldKeyNum;
OldKeyNum=0;
voidTimeChange(void)
switch(ModeSelect)
case0:
if(NewKeyNum==2)
ModeSelect+=1;
}break;
case1:
//更改年变量
switch(NewKeyNum)
Year--;
break;
case2:
ModeSelect++;
case3:
default:
break;
//更改月变量
Month--;
//更改日变量
Day--;
case4:
//更改小时变量
Hour--;
case5:
Min--;
ModeSelect=0;
default:
/***********************
**********主函数********
***********************/
voidmain()
DeviceInit();
for(;
;
)
if(ModeSelect!
=0)//判断现在是否处于更改时间日期状态
ChangeModeBit=1;
ChangeModeBit=0;
if(SecBit2%2==0)//如果秒末位是偶数,SecSymbol=0
SecOddBit=0;
SecOddBit=1;
KeyScan();
TimeChange();
if(ChangeModeBit==1)
此万年历程序不足,未尽完善之处:
1)未设置闹钟,只能显示阴历阳历和星期等信息.
2)后续应加入温度显示,以测定日气温
3)没有与计算机或其他设备通讯接口
4)液晶显示处于常亮状态,影响寿命.应当设置如果一定时间未操作,显示屏应关闭.待有按键操作时再打开.这样才能使LCD寿命更为长久.
5)程序和硬件中未加入对于LCD背光的控制模块,无光亮时无法看时间.
参考链接: