万年历代码.docx
《万年历代码.docx》由会员分享,可在线阅读,更多相关《万年历代码.docx(14页珍藏版)》请在冰点文库上搜索。
万年历代码
ATmega8单片机万年历C程序(内部RTC)
[日期:
2009-05-04][来源:
net作者:
佚名][字体:
大中小](投递新闻)
)调整时间和日期,
只设置了四个按键
a,复位按键;
b,调整模态选择按键,切换调整不同参数;
c,上调按键,调整模式下按此键被调整值上调;
d,下调按键,调整模式下按此键被调整值下调.
这是调整年份时的显示状态,LCD第二行末尾显示"yar".
依此类推,调整月份时显示"mth",调整日期时显示"day",小时时显示"hor",分钟时显示"min".
3)软件部分.
程序中包含一个头文件"LCD1620.h",此文件中包含有关LCD的一些显示函数.
下面是部分程序原代码---不知道怎么回事,今天网络速度比较慢,无法上传文件.如有需要可与我e-mail联系lhy_radio@.
/*******************************************************/
/*Project:
Calendar*/
/*Compiler:
ICCAVR6.31A*/
/*Date:
2008,5,31*/
/*Author:
lhy*/
/*Version:
v1.3*/
/*Rework:
lhy*/
/*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
#include
#defineDataPortPullupPORTD
#defineDataPortDirectionDDRD
#defineReadLCDPinPIND
#defineCtrlPortPullupPORTC
#defineCtrlPortDirectionDDRC
#defineRS_BitPC0
#defineRW_BitPC1
#defineE_BitPC2
#include"LCD1620.h"
#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<PORTC|=(1<}
voidTimer2Init(void)//timer2初始化
{
TCCR2=0x00;//stop
ASSR=0x08;//setasyncmode
TCNT2=ClkTcnt2;//setup
TCCR2=0x06;//start
}
voidTimer2Ovf(void)//timer2中断函数
{
TCNT2=ClkTcnt2;//reloadcountervalue
Sec+=1;
AskLeapYear();
SolarCount();
AskLeapYear();
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>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;
}
elseif(((Month==4)||(Month==6)||(Month==9)||(Month==11))&&(Day>30))
{
Month++;
Day=1;
}
elseif(Month==2)
{
if(LeapYearBit==1)//如果是闰年
{
if(Day>29)
{
Month++;
Day=1;
}
}
elseif(Day>28)//平年
{
Month++;
Day=1;
}
}
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并且农历转换成功时,显示农历
{
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,"Outofrange!
");
}
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]);
}
}
voidCountWeek(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;
}
}
voidKeyScan(void)
{if((PINC&(1<{
OldKeyNum=1;
}
elseif((PINC&(1<{
OldKeyNum=2;
}
elseif((PINC&(1<{
OldKeyNum=3;
}
if((PINC&(1<{
NewKeyNum=OldKeyNum;
OldKeyNum=0;
}
}
voidTimeChange(void)
{
switch(ModeSelect)
{
case0:
{
if(NewKeyNum==2)
{
ModeSelect+=1;
}
}break;
case1:
//更改年变量
{
switch(NewKeyNum)
{
case1:
Year--;break;
case2:
ModeSelect++;break;
case3:
Year++;break;
default:
break;
}
}break;
case2:
//更改月变量
{
switch(NewKeyNum)
{
case1:
Month--;break;
case2:
ModeSelect++;break;
case3:
Month++;break;
default:
break;
}
}break;
case3:
//更改日变量
{
switch(NewKeyNum)
{
case1:
Day--;break;
case2:
ModeSelect++;break;
case3:
Day++;break;
default:
break;
}
}break;
case4:
//更改小时变量
{
switch(NewKeyNum)
{
case1:
Hour--;break;
case2:
ModeSelect++;break;
case3:
Hour++;break;
default:
break;
}
}break;
case5:
{
switch(NewKeyNum)
{
case1:
Min--;break;
case2:
ModeSelect=0;break;
case3:
Min++;break;
default:
break;
}
}break;
default:
break;
}
}
/***********************
**********主函数********
***********************/
voidmain()
{
DeviceInit();
SEI();
for(;;)
{
if(ModeSelect!
=0)//判断现在是否处于更改时间日期状态
{
ChangeModeBit=1;
}
else
{
ChangeModeBit=0;
}
if(SecBit2%2==0)//如果秒末位是偶数,SecSymbol=0
{
SecOddBit=0;
}
else
{
SecOddBit=1;
}
KeyScan();
TimeChange();
if(ChangeModeBit==1)
{
CLI();
DispUpdate();
SEI();
}
}
}
此万年历程序不足,未尽完善之处:
1)未设置闹钟,只能显示阴历阳历和星期等信息.
2)后续应加入温度显示,以测定日气温
3)没有与计算机或其他设备通讯接口
4)液晶显示处于常亮状态,影响寿命.应当设置如果一定时间未操作,显示屏应关闭.待有按键操作时再打开.这样才能使LCD寿命更为长久.
5)程序和硬件中未加入对于LCD背光的控制模块,无光亮时无法看时间.
参考链接: