機電之家資源網(wǎng)
單片機首頁|單片機基礎|單片機應用|單片機開發(fā)|單片機文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開發(fā)
培訓信息
贊助商
ATmega8單片機萬年歷C程序(內(nèi)部RTC)
ATmega8單片機萬年歷C程序(內(nèi)部RTC)
 更新時間:2009-12-2 16:23:16  點擊數(shù):0
【字體: 字體顏色
正文
) 調(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控制模塊,無光亮時無法看時間.
  • 上一篇: ATMEGA8單片機驅(qū)動LCD1602液晶C程序
  • 下一篇: 沒有了
  • 發(fā)表評論   告訴好友   打印此文  收藏此頁  關(guān)閉窗口  返回頂部
    熱點文章
     
    推薦文章
     
    相關(guān)文章
    網(wǎng)友評論:(只顯示最新5條。)
    關(guān)于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機電之家 | 會員助手 | 免費鏈接

    點擊這里給我發(fā)消息66821730(技術(shù)支持)點擊這里給我發(fā)消息66821730(廣告投放) 點擊這里給我發(fā)消息41031197(編輯) 點擊這里給我發(fā)消息58733127(審核)
    本站提供的機電設備,機電供求等信息由機電企業(yè)自行提供,該企業(yè)負責信息內(nèi)容的真實性、準確性和合法性。
    機電之家對此不承擔任何保證責任,有侵犯您利益的地方請聯(lián)系機電之家,機電之家將及時作出處理。
    Copyright 2007 機電之家 Inc All Rights Reserved.機電之家-由機電一體化網(wǎng)更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術(shù)支持

    主辦:杭州市高新區(qū)(濱江)機電一體化學會
    中國行業(yè)電子商務100強網(wǎng)站

    網(wǎng)站經(jīng)營許可證:浙B2-20080178-1