機電之家資源網(wǎng)
單片機首頁|單片機基礎|單片機應用|單片機開發(fā)|單片機文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開發(fā)
培訓信息
贊助商
[課程設計]可設置8個鬧鐘時間的智能時鐘(C)
[課程設計]可設置8個鬧鐘時間的智能時鐘(C)
 更新時間:2008-7-27 13:55:37  點擊數(shù):4
【字體: 字體顏色
可設置8個鬧鐘時間的智能時鐘
1.功能簡介
該時鐘以24小時制顯示時間,并可顯示2000年至2049年之間的任何日期及星期,日期與時間經(jīng)按鍵可相互切換,可輸入8個鬧鐘時間設置,每個鬧鐘設置包括響鈴的時間(小時與分鐘)、對工作日有效還是對周末有效的標志,以及本項設置是否啟用的標志等三部分。這8個鬧鐘設置均保存在EEPROM中,即使掉電也不用重新輸入。當然使用者可通過按鈕對任何一個設置作修改。數(shù)碼管可經(jīng)按鈕關閉顯示,避免夜間刺眼、影響睡眠。調節(jié)LM317輸出電壓,可改變數(shù)碼管亮度,但電壓不能低于后備電池的電壓,否則后備電池供電。用四節(jié)1.5V電池串聯(lián)作后備電源,保證市電停電時時鐘繼續(xù)走時。時鐘的精度取決于晶振頻率的精度。原理圖見下:


程序清單
本程序用C語言編寫,經(jīng)Keil C51編譯成二進制碼后寫入89C51內的EPROM內即可。
#i nclude "atmel\at89x51.h"
#i nclude "intrins.h"
unsigned char hour,min,sec,year,month,day,weekday
unsigned int  count_down
bit led_on
unsigned char display[8]
unsigned char attr
bit flash
unsigned char show_status
        // 0:設置鬧鐘數(shù)據(jù)
// 1:顯示當前日期及星期
                                                 // 2:顯示當前時間
// 3:設置當前日期
// 4:設置當前時間
bit km
bit kp
bit sound
bit alarm_stop
struct  { unsigned char h
        unsigned char m
       } alarm[8]
unsigned char alarm_en
unsigned char alarm_wk
unsigned char cur_alarm_set
unsigned char cur_alarm_active
bit new_alarm_info
sbit sound_output = P1^5
sbit SDA_PIN   = P1^6
sbit SCL_PIN   = P1^7
void I2cDelay()               //EEPROM操作時需要的延時函數(shù)
{ _nop_()
  _nop_()
}
void DelayX1ms(unsigned char count)        //延遲函數(shù),參數(shù)為毫秒數(shù)
{unsigned char i,j
  for(i=0
    for(j=0
}
void Start()                                        //I2C啟動,24C08使用I2C方式
{ SDA_PIN=1
  SCL_PIN=1
  SDA_PIN=0
  SCL_PIN=0
}
void Stop()                         //I2C停止
{ I2cDelay()
  I2cDelay()
  I2cDelay()
  I2cDelay()
}
bit SendByte(unsigned char value)               //發(fā)送1字節(jié)數(shù)據(jù)給EEPROM
{unsigned char i
 bit no_ack=0
  for(i=0
  { I2cDelay()
if(value&0x80)   SDA_PIN=1
else            SDA_PIN=0
    value=value<<1
       I2cDelay()
       I2cDelay()
       I2cDelay()
   }
  I2cDelay()
  I2cDelay()
  I2cDelay()
  if(SDA_PIN==1)   no_ack=1
  I2cDelay()
  return no_ack
}
void mywrite(unsigned char address,unsigned char value)         //向EEPROM寫1字節(jié)
{ Start()
  SendByte(value)
}
unsigned char ReadByte()                    //從EEPROM接收1字節(jié)
{unsigned char i,bval
  bval=0
  for(i=0
   { I2cDelay()
     SDA_PIN=1
     I2cDelay()
     I2cDelay()
     I2cDelay()
    }
       I2cDelay()
       I2cDelay()
       I2cDelay()
       I2cDelay()
    return(bval)
}
unsigned char myread(unsigned char address)            //從EEPROM讀入1字節(jié)數(shù)據(jù)
{unsigned char tmp
  Start()
  Start()
  Stop()
  return(tmp)
}
void Timer0ISR(void) interrupt 1 using 3     //定時器0中斷程序,用于走時,1/8000秒一次
{unsigned char tmp,tmp_days
  count_down--
  if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)
   { flash=~flash
     if(sound && flash) sound_output=0
     else             sound_output=1
        return
       }
  if(count_down==3000)
   { if(year==0)       weekday=5
    else { tmp=(year-1)/4+1
         weekday=(tmp+5)%7
        }
     tmp_days=0
     for(tmp=1
       if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)
          tmp_days=tmp_days+31
       else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)
             tmp_days=tmp_days+30
       else if(tmp==2)
             { if(year%4==0) tmp_days=tmp_days+29
            else         tmp_days=tmp_days+28
           }
     tmp_days=tmp_days+day-1
        return
       }
  if(count_down==5000)
  { if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) //觸發(fā)后1分鐘
      { alarm_stop=0
    if(sound==0 && alarm_stop==0)           //沒有已觸發(fā)的鬧鐘項
     for(tmp=0
         { if(((alarm_en>>tmp)&1)==0) continue
           if(((alarm_wk>>tmp)&1)==1)           //該鬧鐘項周末有效
                { if(weekday!=6 && weekday!=7) continue
              else
                { if(weekday==6 || weekday==7) continue
        if(alarm[tmp].h==hour && alarm[tmp].m==min)             //比較當前時間與該
          { sound=1
          }
    return
   }
  if(count_down==0)                              //過了一秒鐘
   { count_down=8000
     sec++
     if(sec==60)
      { sec=0
        min++
        if(min==60)
          { min=0
            hour++
            if(hour==24)
              { hour=0
                            switch(day)
                            { case 29: if(month==2 && year%4)    { day=1
                                       break
                              case 30: if(month==2 && year%4==0) { day=1
                                       break
                              case 31: if(month==4 || month==6 || month==9 || month==11)
                                       { day=1
                                          break
                              case 32: day=1
                                     if(month==13) { month=1
                             }
               }
           }
       }
     }
}
void Timer1ISR(void) interrupt 3 using 2            //定時器2中斷,用于按鍵掃描
{unsigned char keytmp
 char tmp
  TH1=0x15
  if(show_status==0)   //當前正在設置鬧鐘項
    { display[0]=cur_alarm_set
     display[2]=alarm[cur_alarm_set].h/10
        display[4]=alarm[cur_alarm_set].m/10
     display[6]=(alarm_wk>>cur_alarm_set)&1
     }
  if(show_status==1 || show_status==3)         //當前顯示或設置日期
    { display[0]=year/10
         display[3]=month%10
         display[6]=0xf
     }
  if(show_status==2 || show_status==4)         //當前顯示或設置時間
    { display[0]=hour/10
        display[3]=min%10
         display[6]=0xf
        }
  keytmp=~(P1) & 0x0f
  if(keytmp==0)  { km=0
  else
   { if(km==0)   km=1
        else
     { if(kp==0)
        { kp=1
                if(keytmp==1)                  //第一個按鈕
                 { if(sound) { alarm_stop=1
                   else if((show_status==1 || show_status==2) && led_on)  //正顯示日期或時間
                   { show_status=0
                      else if(show_status==0)                //如正在設置鬧鐘時間項
                      { show_status=2
                      return
                     }
                if(keytmp==2 && led_on)    //第二個按鈕,僅當數(shù)碼管打開時有效
                 { switch(attr)
                   { case 0xff: if(show_status==1) show_status=2
                                else if(show_status==2) show_status=1
                                      break
                        case 0x3f: if(show_status==0) cur_alarm_set=(cur_alarm_set+1)%8
                      else if(show_status==3)
                             year=(year+1)%50
                     else if(show_status==4)
                         hour=(hour+1)%24
                            break
          case 0xcf: if(show_status==0)                     //鬧鐘設置的“時”加1
  alarm[cur_alarm_set].h=(alarm[cur_alarm_set].h+1)%24
            else if(show_status==3)
   { month++
     if(month==13) month=1
                           else if(show_status==4)
                            min=(min+1)%60
                                 break
                case 0xf3: if(show_status==0)
                           alarm[cur_alarm_set].m=(alarm[cur_alarm_set].m+1)%60
                         else if(show_status==3)
                           {day++
                            if(day==32) day=1
                         else if(show_status==4)
                           {count_down=8000
                            sec=(sec+1)%60
                              break
            case 0xfd: if(show_status==0)
                                      alarm_wk^=0x1<<cur_alarm_set
                                            break
                         case 0xfe: if(show_status==0)
                                      alarm_en^=0x1<<cur_alarm_set
                       }       //end of switch(attr)
                      return
                     }         //end of if(keytmp==1)
 if(keytmp==4)              //第三個按鈕
                 { switch(attr)
                   { case 0xff: if(show_status==1 || show_status==2)
                                   led_on=~led_on
                                            break
                        case 0x3f: if(show_status==0)         //如果正在設置鬧鐘
                                             { if(cur_alarm_set==0)  cur_alarm_set=7
                             else cur_alarm_set--
                        else if(show_status==3)     //當前日期的“年”減1
                                    { if(year==0)  year=49
                                 else if(show_status==4)     //當前時間的“時”減1
                                             { tmp=hour-1
                                      break
                        case 0xcf: if(show_status==0)          //鬧鐘設置的“時”減1
                                             { tmp=alarm[cur_alarm_set].h-1
                                               if(tmp<0)    alarm[cur_alarm_set].h=23
                                                  else         alarm[cur_alarm_set].h=tmp
                                                 }
                          else if(show_status==3)
                                    { month--
                             if(month==0)  month=12
                                            else if(show_status==4)
                           { tmp=min-1
                            if(tmp<0) min=59
                                          break
                        case 0xf3: if(show_status==0)          //鬧鐘設置的“分鐘”減1
                                             { tmp=alarm[cur_alarm_set].m-1
                                               if(tmp<0)    alarm[cur_alarm_set].m=59
                                                  else         alarm[cur_alarm_set].m=tmp
                                                 }
                          else if(show_status==3)
                                    { day--
                             if(day==0)  day=31
                                            else if(show_status==4)
                           { tmp=sec-1
                             count_down=8000
                             if(tmp<0) sec=59
                                            break
                        case 0xfd: if(show_status==0)                       //切換周末標志
                                      alarm_wk^=0x1<<cur_alarm_set
                                            break
                        case 0xfe: if(show_status==0)                 //切換啟用標志
                                      alarm_en^=0x1<<cur_alarm_set
                       }       //end of switch(attr)
                      return
                     }         //end of if(keytmp==2)
                if(keytmp==8 & led_on)    //第四個按鈕,僅當數(shù)碼管打開時有效
                 { switch(attr)
                      { case 0xff: if(show_status==1)               //如果當前顯示日期
                         show_status=3
                               else if(show_status==2)    //如果當前顯示時間
                          show_status=4
                                     attr=0x3f
                        case 0x3f: attr=0xcf
                        case 0xcf: attr=0xf3
                        case 0xf3: if(show_status==0) attr=0xfd
                        else if(show_status==3)
                           { show_status=1
                                 else if(show_status==4)
                            { show_status=2
                                          break
                        case 0xfd: if(show_status==0) attr=0xfe
                                   break
                        case 0xfe: if(show_status==0) attr=0x3f
                      }
                     }   // end of if(keytmp==4)
               }      // end of if(kp==0)
        }         // end of if(km==0)
   }            // end of if(keytmp!=0)
}
main()
{unsigned char i
  hour=23
  count_down=8000
  flash=0
  km=0
  new_alarm_info=0
  for(i=0
    { alarm[i].h=myread(i*2)
      alarm_en=myread(i*2)
  IE=0
  TMOD=0x12
  TH0=6
  TH1=0x15
  TR0=1
  ET0=1
  while(1)
  { if(led_on)
      for(i=0
          { P2=0
         if(flash || attr&(0x80>>i))
                 { P0=display[i]
              }
    else  P2=0
    if(new_alarm_info)
     { P2=0
          new_alarm_info=0
       for(i=0
          mywrite(i*2,alarm_en)
         }
  }
}

  • 上一篇: 課程設計]AT89C2051驅動步進電機的電路和源碼
  • 下一篇: [課程設計]單片機控制的電動自行車驅動系統(tǒng)程序
  • 發(fā)表評論   告訴好友   打印此文  收藏此頁  關閉窗口  返回頂部
    熱點文章
     
    推薦文章
     
    相關文章
    網(wǎng)友評論:(只顯示最新5條。)
    關于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機電之家 | 會員助手 | 免費鏈接

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

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

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