正文:
) 調(diào)整時間和日期, 只設置了四個按鍵 a, 復位按鍵; b, 調(diào)整模態(tài)選擇按鍵,切換調(diào)整不同參數(shù); c, 上調(diào)按鍵,調(diào)整模式下按此鍵被調(diào)整值上調(diào); d, 下調(diào)按鍵,調(diào)整模式下按此鍵被調(diào)整值下調(diào). 這shi調(diào)整年份時de顯示狀態(tài),LCD第二行末尾顯示"yar". 依此類推,調(diào)整月份時顯示"mth",調(diào)整日期時顯示"day",小時時顯示"hor",分鐘時顯示"min".
3) 軟件部分. 程序中包含一個頭文件"LCD1620.h",此文件中包含有關(guān)LCDde一些顯示函數(shù). 下面shi部分程序原代碼---不知道怎么回事,今天網(wǎng)絡速度比較慢,無法上傳文件.如有需要可與我e-mail聯(lián)系lhy_radio@yeah.net. /*******************************************************/ /* Project :Calendar */ /* Compiler :ICCAVR 6.31A */ /* Date :2008,5,31 */ /* Author :lhy */ /* Version :v1.3 */ /* Rework :lhy */ /* Rework Date :2008.6.26 */ /* */ /* Comments : */ /* 1,使用Atmega8內(nèi)部RTC(實時時鐘,32.768KHz) */ /* 2,顯示使用LCD1620 */ /* 3,在Timer2中斷中刷新顯示,精度提高1S@5H */ /* 4,加入星期顯示 */ /* 5,加入農(nóng)歷換算 */ /* 6,秒末位大于等于5時,顯示公歷:Solar 年月日 */ /* 7,SolarYear>2099或SolarYear<1900, */ /* 顯示"Out of range!" */ /* 8,加入手動調(diào)整日期和時間 */ /*******************************************************/
#i nclude <iom8v.h> #i nclude <macros.h>
#define DataPortPullup PORTD #define DataPortDirection DDRD #define ReadLCDPin PIND #define CtrlPortPullup PORTC #define CtrlPortDirection DDRC #define RS_Bit PC0 #define RW_Bit PC1 #define E_Bit PC2
#i nclude "LCD1620.h"
#define ClkTcnt2 0x80
/****************變量聲明********************/ unsigned int Year = 2008;//年變量 unsigned char Month = 6;//月變量 unsigned char Day = 1; unsigned char Hour = 12;//小時 unsigned char Min = 0;//分鐘 unsigned char Sec = 0;//秒 unsigned char YearBit1,YearBit2,YearBit3,YearBit4; unsigned char MonthBit1,MonthBit2; unsigned char DayBit1,DayBit2; unsigned char HourBit1,HourBit2; unsigned char MinBit1,MinBit2; unsigned char SecBit1,SecBit2; unsigned char Week[][4] = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun"}; unsigned char ChangeSymbol[][5] = {"-Yar","-Mth","-Day","-Hor","-Min"}; unsigned char LeapYearWeekTable[] = {3,6,0,3,5,1,3,6,2,4,0,2};//閏年星期偏差表 unsigned char UnLeapWeekTable[] = {4,0,0,3,5,1,3,6,2,4,0,2}; unsigned char TodayWeek = 0; unsigned char LeapYearBit = 0;//為0時,平年 unsigned char LunarData[] = {0,0,0,0}; unsigned char LunarYear1,LunarYear2,LunarYear3,LunarYear4,LunarMonth1,LunARMonth2,LunarDay1,LunarDay2; unsigned char LunarConvertBit;//0,農(nóng)歷轉(zhuǎn)換成功 unsigned char CalendarStopBit;//1,時鐘暫停 unsigned char OldKeyNum = 0; unsigned char NewKeyNum = 0; unsigned char ModeSelect = 0; unsigned char ChangeModeBit = 0;//ModeSelect != 0時,為1,標志現(xiàn)在處于更改時間狀態(tài) unsigned char SecOddBit = 0;//秒為偶數(shù)時,此為0,否則為1 static unsigned char const LunarDayCode1[9]= {0x0,0x1f,0x3b,0x5a,0x78,0x97,0xb5,0xd4,0xf3}; static unsigned short const LunarDayCode2[3]={0x111,0x130,0x14e};
/************************** ***********子函數(shù)********** *************************/
void PortInit(void) //端口初始化 { DDRC &= ~((1<<PC3)|(1<<PC4)|(1<<PC5)); PORTC |= (1<<PC3)|(1<<PC4)|(1<<PC5); }
void Timer2Init(void) //timer2初始化 { TCCR2 = 0x00; //stop ASSR = 0x08; //set async mode TCNT2 = ClkTcnt2; //setup TCCR2 = 0x06; //start }
void Timer2Ovf(void)//timer2中斷函數(shù) { TCNT2 = ClkTcnt2;//reload counter value Sec += 1; AskLeapYear(); SolarCount(); AskLeapYear(); CountWeek(); LunarCount();//先判斷shi否轉(zhuǎn)換成功,然后再計算各位顯示數(shù)值 if(ModeSelect == 0) { LCDispClear(); DispUpdate(); } }
void AskLeapYear(void) { if ( ( (Year%4 == 0) && (Year % 100!=0) ) || Year%400 == 0)//判斷shi否為閏年 { LeapYearBit = 1; } else { LeapYearBit = 0; } }
void SolarCount(void)//計算各位顯示值 { if (Sec>59) { Sec = 0; Min ++; } if (Min>59) { 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; } else if ( ( (Month==4) || (Month==6) || (Month==9) || (Month==11) ) && (Day>30) ) { Month ++; Day = 1; } else if (Month==2) { if (LeapYearBit == 1)//如果shi閏年 { if (Day>29) { Month ++; Day = 1; } } else if (Day > 28)//平年 { Month ++; Day = 1; } } if (Month > 12) { Month = 1; Year ++; } //計算各位de值 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; }
void DeviceInit(void)//MCU初始化 { CLI(); PortInit(); Timer2Init();
MCUCR = 0x00; GICR = 0x00; TIMSK = 0x40; LCD_Init(); SEI(); }
//更新顯示 void DispUpdate(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); } else if(LunarConvertBit == 1)//秒末位小于5并且農(nóng)歷轉(zhuǎn)換成功時,顯示農(nóng)歷 { PutStringLCD(0,0,"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); } else { PutStringLCD(0,0,"Out of range!"); } PutNumberLCD(1,0,HourBit1); PutNumberLCD(1,1,HourBit2); if(SecOddBit) { PutOneCharLCD(1,2,":"); } PutNumberLCD(1,3,MinBit1); PutNumberLCD(1,4,MinBit2); if(SecOddBit) { 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]); } }
void CountWeek(void) { if(LeapYearBit == 1) { TodayWeek = ((Year/100%4*5) + (Year%100/4*5) + (Year%4) + 1 + Day + LeapYearWeekTable[Month - 1])%7; } else { TodayWeek = ((Year/100%4*5) + (Year%100/4*5) + (Year%4) + 1 + Day + UnLeapWeekTable[Month - 1])%7; } } void KeyScan(void) {if((PINC&(1<<PC5)) == 0) { OldKeyNum = 1; } else if((PINC&(1<<PC4)) == 0) { OldKeyNum = 2; } else if((PINC&(1<<PC3)) == 0) { OldKeyNum = 3; } if((PINC & (1<<PC5)) && (PINC & (1<<PC4)) && (PINC & (1<<PC3)))//判斷shi否有按鍵按下 { NewKeyNum = OldKeyNum; OldKeyNum = 0; } }
void TimeChange(void) { switch(ModeSelect) { case 0: { if(NewKeyNum == 2) { ModeSelect += 1; } }break; case 1://更改年變量 { switch (NewKeyNum) { case 1: Year --; break; case 2: ModeSelect ++; break; case 3: Year ++; break; default:break; } }break; case 2://更改月變量 { switch (NewKeyNum) { case 1: Month --; break; case 2: ModeSelect ++; break; case 3: Month ++; break; default:break; } }break; case 3://更改日變量 { switch (NewKeyNum) { case 1: Day --; break; case 2: ModeSelect ++; break; case 3: Day ++; break; default:break; } }break; case 4://更改小時變量 { switch (NewKeyNum) { case 1: Hour --; break; case 2: ModeSelect ++; break; case 3: Hour ++; break; default:break; } }break; case 5: { switch (NewKeyNum) { case 1: Min --; break; case 2: ModeSelect = 0; break; case 3: Min ++; break; default:break; } }break; default : break; } }
/*********************** **********主函數(shù)******** ***********************/ void main() { DeviceInit(); SEI(); for (;;) { if(ModeSelect != 0)//判斷現(xiàn)在shi否處于更改時間日期狀態(tài) { ChangeModeBit = 1; } else { ChangeModeBit = 0; } if(SecBit2 % 2 == 0)//如果秒末位shi偶數(shù),SecSymbol=0 { SecOddBit = 0; } else { SecOddBit = 1; } KeyScan(); TimeChange(); if(ChangeModeBit == 1) { CLI(); DispUpdate(); SEI(); } } }
此萬年歷程序不足,未盡完善之處: 1) 未設置鬧鐘,只能顯示陰歷陽歷和星期等信息. 2) 后續(xù)應加入溫度顯示,以測定日氣溫 3) 沒有與計算機或其他設備通訊接口 4) 液晶顯示處于常亮狀態(tài),影響壽命.應當設置如果一定時間未操作,顯示屏應關(guān)閉.待有按鍵操作時再打開.這樣才能使LCD壽命更為長久. 5) 程序和硬件中未加入對于LCD背光de控制模塊,無光亮時無法看時間.
|
|