久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

標題: 可設置8個鬧鐘時間的單片機智能時鐘 [打印本頁]

作者: 51黑科技    時間: 2016-2-2 04:38
標題: 可設置8個鬧鐘時間的單片機智能時鐘
                        普通的家用時鐘一般只能設置一個鬧鐘時間,但很多人均需為工作日、周末、早晨、午休等不同時段設置不同的鬧鐘時間。如果是使用普通的鬧鐘,只好每次休息前重新設置,很不方便,有時甚至會出現(xiàn)忘記更改鬧鐘設置而睡過頭的情況。
        
        
        針對這種情況,本人利用89C51單片機設計了一款有8種鬧鐘設置的時鐘,通過一段時間的使用,情況良好。
        
        
        1、                          元件清單
        
        共陰極數(shù)碼管                                              8個                                              4511七段譯碼芯片                                        1片
        
        ATMEL89C51單片機                                          1片                                              24C08EEPROM                     1片
        
        24M晶振                                                   1個                                              9V變壓器(3VA)                                         1個
        
        LM317輸出可調(diào)穩(wěn)壓IC                                       1個                                                      整流橋堆                                                1個
        
        470uF電容                                                 1個                                              100uF電容                                               1個
        
        10uF電容                                                  1個                                              0.1uF電容                                               1個
        
        33pF電容                                                  2個                                                      蜂鳴器                                                  1個
        
        9014(或其它NPN管)                                       8個                                              ksp92(或其它PNP管)            1個
        
        二極管                                                    2個                                              1K歐電阻                                                16個
        
        470歐電阻                                                 1個                                              10K歐可調(diào)電阻                                           1個
        
        10K歐電阻                                                 4個                                                      按鈕開關                                                4個        
        
        可裝四節(jié)電池的電池盒                                      1個                                                      萬能板(約12CM*17CM)           1塊
        
        所有元件按以下的電路圖焊接在一塊萬能板上。注意LM317的輸出應由低調(diào)高,以免燒IC。
        
        
        1、                          電路圖
        
        
        
        
        1、                          功能簡介
        
        該時鐘以24小時制顯示時間,并可顯示2000年至2049年之間的任何日期及星期,日期與時間經(jīng)按鍵可相互切換,可輸入8個鬧鐘時間設置,每個鬧鐘設置包括響鈴的時間(小時與分鐘)、對工作日有效還是對周末有效的標志,以及本項設置是否啟用的標志等三部分。這8個鬧鐘設置均保存在EEPROM中,即使掉電也不用重新輸入。當然使用者可通過按鈕對任何一個設置作修改。數(shù)碼管可經(jīng)按鈕關閉顯示,避免夜間刺眼、影響睡眠。調(diào)節(jié)LM317輸出電壓,可改變數(shù)碼管亮度,但電壓不能低于后備電池的電壓,否則后備電池供電。用四節(jié)1.5V電池串聯(lián)作后備電源,保證市電停電時時鐘繼續(xù)走時。時鐘的精度取決于晶振頻率的精度。
        
        
        2、                          程序清單
        
        本程序用C語言編寫,經(jīng)Keil                         C51編譯成二進制碼后寫入89C51內(nèi)的EPROM內(nèi)即可。
  1. #include "atmelat89x51.h"

  2. #include "intrins.h"



  3. unsigned char hour,min,sec,year,month,day,weekday;   //當前時間、日期、星期

  4. unsigned int  count_down;      //1秒鐘計時用



  5. bit led_on;                    //數(shù)碼管是否點亮的標志

  6. unsigned char display[8];         //8位數(shù)碼管要顯示的數(shù)據(jù)

  7. unsigned char attr;              //八個數(shù)碼管的閃爍控制字節(jié),當為0時,對應數(shù)碼管閃

  8. bit flash;                            //LED 閃爍開關,與attr共同決定數(shù)碼管是否閃爍

  9. unsigned char show_status;     //LED 顯示狀態(tài)標志

  10.         // 0:設置鬧鐘數(shù)據(jù)

  11. // 1:顯示當前日期及星期

  12.                                                  // 2:顯示當前時間

  13. // 3:設置當前日期

  14. // 4:設置當前時間



  15. bit km;                      //按鍵已去抖動標志

  16. bit kp;                       //按鍵已處理標志



  17. bit sound;                    //蜂鳴器響標志

  18. bit alarm_stop;                //蜂鳴器響后用戶手工按停標志

  19. struct  { unsigned char h;           //小時

  20.         unsigned char m;           //分鐘

  21.        } alarm[8];                            //8個鬧鐘項

  22. unsigned char alarm_en;        //鬧鐘項啟用標志

  23. unsigned char alarm_wk;        //鬧鐘項周末啟用標志

  24. unsigned char cur_alarm_set;     //當前設置的鬧鐘項

  25. unsigned char cur_alarm_active;   //當前到點的鬧鐘項

  26. bit new_alarm_info;            //鬧鐘項內(nèi)容已修改標志



  27. sbit sound_output = P1^5;      //蜂鳴器驅(qū)動端口,輸出0時蜂鳴器響

  28. sbit SDA_PIN   = P1^6;          //EEPROM數(shù)據(jù)線端口

  29. sbit SCL_PIN   = P1^7;          //EEPROM時鐘線端口



  30. void I2cDelay()               //EEPROM操作時需要的延時函數(shù)

  31. { _nop_();  _nop_();  _nop_();

  32.   _nop_();  _nop_();  _nop_();

  33. }

  34. void DelayX1ms(unsigned char count)        //延遲函數(shù),參數(shù)為毫秒數(shù)

  35. {unsigned char i,j;

  36.   for(i=0;i<count;i++)

  37.     for(j=0;j<240;j++)    ;

  38. }

  39. void Start()                                        //I2C啟動,24C08使用I2C方式

  40. { SDA_PIN=1;   I2cDelay();

  41.   SCL_PIN=1;   I2cDelay();

  42.   SDA_PIN=0;   I2cDelay();

  43.   SCL_PIN=0;   

  44. }

  45. void Stop()                         //I2C停止

  46. { I2cDelay();  SDA_PIN=0;

  47.   I2cDelay();  SCL_PIN=1;

  48.   I2cDelay();  SDA_PIN=1;

  49.   I2cDelay();

  50. }

  51. bit SendByte(unsigned char value)               //發(fā)送1字節(jié)數(shù)據(jù)給EEPROM

  52. {unsigned char i;

  53. bit no_ack=0;

  54.   for(i=0;i<8;i++)                     //發(fā)送8位數(shù)據(jù)

  55.   { I2cDelay();   

  56. if(value&0x80)   SDA_PIN=1;

  57. else            SDA_PIN=0;

  58.     value=value<<1;        

  59.        I2cDelay();      SCL_PIN=1;         

  60.        I2cDelay();

  61.        I2cDelay();      SCL_PIN=0;

  62.    }

  63.   I2cDelay();        SDA_PIN=1;     //確認脈沖周期,等待EEPROM的確認

  64.   I2cDelay();        SCL_PIN=1;      

  65.   I2cDelay();      

  66.   if(SDA_PIN==1)   no_ack=1;

  67.   I2cDelay();        SCL_PIN=0;

  68.   return no_ack;

  69. }

  70. void mywrite(unsigned char address,unsigned char value)         //向EEPROM寫1字節(jié)

  71. { Start();          SendByte(0xa0);     SendByte(address);   

  72.   SendByte(value);  Stop();             DelayX1ms(10);

  73. }

  74. unsigned char ReadByte()                    //從EEPROM接收1字節(jié)

  75. {unsigned char i,bval;

  76.   bval=0;

  77.   for(i=0;i<8;i++)                              //接收8位數(shù)據(jù)

  78.    { I2cDelay();

  79.      SDA_PIN=1;                          //從P1輸入數(shù)據(jù)時,先往P1輸入“1”

  80.      I2cDelay();    SCL_PIN=1;



  81.      I2cDelay();    bval=bval<<1;     if(SDA_PIN)    bval=bval|0x01;

  82.      I2cDelay();    SCL_PIN=0;

  83.     }

  84.        I2cDelay();     SDA_PIN=1;    //確認脈沖周期,不送出確認

  85.        I2cDelay();     SCL_PIN=1;   

  86.        I2cDelay();     

  87.        I2cDelay();



  88.     return(bval);

  89. }

  90. unsigned char myread(unsigned char address)            //從EEPROM讀入1字節(jié)數(shù)據(jù)

  91. {unsigned char tmp;

  92.   Start();        SendByte(0xa0);     SendByte(address);   

  93.   Start();        SendByte(0xa1);     tmp=ReadByte();

  94.   Stop();         DelayX1ms(2);

  95.   return(tmp);

  96. }

  97. void Timer0ISR(void) interrupt 1 using 3     //定時器0中斷程序,用于走時,1/8000秒一次

  98. {unsigned char tmp,tmp_days;

  99.   count_down--;

  100.   if(count_down==1 || count_down==2001 || count_down==4001 || count_down==6001)

  101.    { flash=~flash;                                   //數(shù)碼管閃爍的開關量

  102.      if(sound && flash) sound_output=0;         //驅(qū)動蜂鳴器

  103.      else             sound_output=1;         //關閉蜂鳴器

  104.         return;

  105.        }

  106.                      /*** 計算當前日期為星期幾***/

  107.   if(count_down==3000)

  108.    { if(year==0)       weekday=5;           //2000年1月1日為星期六

  109.     else { tmp=(year-1)/4+1;   tmp=(year-tmp)+tmp*2;

  110.          weekday=(tmp+5)%7;           //計算出當前年的1月1日為星期幾

  111.         }

  112.      tmp_days=0;

  113.      for(tmp=1;tmp<month;tmp++)

  114.        if(tmp==1 || tmp==3 || tmp==5 || tmp==7 || tmp==8 || tmp==10)

  115.           tmp_days=tmp_days+31;

  116.        else if(tmp==4 || tmp==6 || tmp==9 || tmp==11)

  117.              tmp_days=tmp_days+30;

  118.        else if(tmp==2)

  119.              { if(year%4==0) tmp_days=tmp_days+29;

  120.             else         tmp_days=tmp_days+28;

  121.            }

  122.      tmp_days=tmp_days+day-1;    weekday=(weekday+tmp_days%7)%7+1;

  123.         return;

  124.        }

  125.                   /***  查詢是否有鬧鐘時間項符合觸發(fā)條件 ***/

  126.   if(count_down==5000)

  127.   { if((alarm_stop || sound) && alarm[cur_alarm_active].m!=min) //觸發(fā)后1分鐘

  128.       { alarm_stop=0; sound=0; }                                                //自動關蜂鳴器



  129.     if(sound==0 && alarm_stop==0)           //沒有已觸發(fā)的鬧鐘項

  130.      for(tmp=0;tmp<8;tmp++)                           //則查詢8個鬧鐘項內(nèi)是否有符合條件的

  131.          { if(((alarm_en>>tmp)&1)==0) continue;    //該鬧鐘項不啟用

  132.            if(((alarm_wk>>tmp)&1)==1)           //該鬧鐘項周末有效

  133.                 { if(weekday!=6 && weekday!=7) continue;  }     //當前不是星期六或星期天

  134.               else

  135.                 { if(weekday==6 || weekday==7) continue;  }



  136.         if(alarm[tmp].h==hour && alarm[tmp].m==min)             //比較當前時間與該

  137.           { sound=1;  cur_alarm_active=tmp; break; }         //鬧鐘項的時間

  138.           }

  139.     return;

  140.    }



  141.   if(count_down==0)                              //過了一秒鐘

  142.    { count_down=8000;

  143.      sec++;

  144.      if(sec==60)

  145.       { sec=0;

  146.         min++;

  147.         if(min==60)

  148.           { min=0;

  149.             hour++;

  150.             if(hour==24)

  151.               { hour=0;   day++;

  152.                             switch(day)

  153.                             { case 29: if(month==2 && year%4)    { day=1; month=3; }

  154.                                        break;

  155.                               case 30: if(month==2 && year%4==0) { day=1; month=3; }

  156.                                        break;

  157.                               case 31: if(month==4 || month==6 || month==9 || month==11)

  158.                                        { day=1; month++; }

  159.                                           break;

  160.                               case 32: day=1;          month++;

  161.                                      if(month==13) { month=1; year++; }

  162.                              }

  163.                }

  164.            }

  165.        }

  166.      }

  167. }



  168. void Timer1ISR(void) interrupt 3 using 2            //定時器2中斷,用于按鍵掃描

  169. {unsigned char keytmp;

  170. char tmp;



  171.   TH1=0x15; TL1=0xa0;      // 每30ms中斷一次



  172.                  /***  當前顯示的內(nèi)容 ***/

  173.   if(show_status==0)   //當前正在設置鬧鐘項

  174.     { display[0]=cur_alarm_set;               display[1]=0xf;

  175.      display[2]=alarm[cur_alarm_set].h/10;      display[3]=alarm[cur_alarm_set].h%10;

  176.         display[4]=alarm[cur_alarm_set].m/10;      display[5]=alarm[cur_alarm_set].m%10;

  177.      display[6]=(alarm_wk>>cur_alarm_set)&1;  display[7]=(alarm_en>>cur_alarm_set)&1;

  178.      }



  179.   if(show_status==1 || show_status==3)         //當前顯示或設置日期

  180.     { display[0]=year/10;       display[1]=year%10;    display[2]=month/10;  

  181.          display[3]=month%10;    display[4]=day/10;   display[5]=day%10;

  182.          display[6]=0xf;         display[7]=weekday;

  183.      }



  184.   if(show_status==2 || show_status==4)         //當前顯示或設置時間

  185.     { display[0]=hour/10;      display[1]=hour%10;    display[2]=min/10;

  186.         display[3]=min%10;     display[4]=sec/10;       display[5]=sec%10;

  187.          display[6]=0xf;         display[7]=0xf;   //最后兩后無顯示

  188.         }



  189.                     /***  按鍵掃描及處理  ***/

  190.   keytmp=~(P1) & 0x0f;

  191.   if(keytmp==0)  { km=0;  kp=0; }  

  192.   else

  193.    { if(km==0)   km=1;  

  194.         else

  195.      { if(kp==0)

  196.         { kp=1;

  197.                 if(keytmp==1)                  //第一個按鈕

  198.                  { if(sound) { alarm_stop=1; sound=0; }      //如果鬧鐘正響,按此鍵停止

  199.                    else if((show_status==1 || show_status==2) && led_on)  //正顯示日期或時間

  200.                    { show_status=0;  cur_alarm_set=0;  attr=0x3f; }  //進入鬧鐘設置

  201.                       else if(show_status==0)                //如正在設置鬧鐘時間項

  202.                       { show_status=2;  new_alarm_info=1; attr=0xff; }  //返回當前時間顯示

  203.                       return;

  204.                      }

  205.                   

  206.                 if(keytmp==2 && led_on)    //第二個按鈕,僅當數(shù)碼管打開時有效

  207.                  { switch(attr)

  208.                    { case 0xff: if(show_status==1) show_status=2;   //在顯示時間與日期間切換

  209.                                 else if(show_status==2) show_status=1;

  210.                                       break;

  211.                         case 0x3f: if(show_status==0) cur_alarm_set=(cur_alarm_set+1)%8;

  212.                       else if(show_status==3)

  213.                              year=(year+1)%50;       //當前日期的“年”加1

  214.                      else if(show_status==4)

  215.                          hour=(hour+1)%24;       //當前時間的“時”加1

  216.                             break;   

  217.           case 0xcf: if(show_status==0)                     //鬧鐘設置的“時”加1

  218.   alarm[cur_alarm_set].h=(alarm[cur_alarm_set].h+1)%24;

  219.             else if(show_status==3)

  220.    { month++;                //當前日期的“月”加1

  221.      if(month==13) month=1; }

  222.                            else if(show_status==4)

  223.                             min=(min+1)%60;         //當前時間的“分”加1

  224.                                  break;

  225.                 case 0xf3: if(show_status==0)

  226.                            alarm[cur_alarm_set].m=(alarm[cur_alarm_set].m+1)%60;

  227.                          else if(show_status==3)

  228.                            {day++;                  //當前日期的“日”加1

  229.                             if(day==32) day=1; }

  230.                          else if(show_status==4)

  231.                            {count_down=8000;

  232.                             sec=(sec+1)%60; }        //當前時間的“秒”加1

  233.                               break;               

  234.             case 0xfd: if(show_status==0)

  235.                                       alarm_wk^=0x1<<cur_alarm_set; 周末標志位切換

  236.                                             break;

  237.                          case 0xfe: if(show_status==0)

  238.                                       alarm_en^=0x1<<cur_alarm_set; 啟用標志位切換

  239.                        }       //end of switch(attr)

  240.                       return;

  241.                      }         //end of if(keytmp==1)



  242.                 if(keytmp==4)           //第三個按鈕

  243.                  { switch(attr)

  244.                    { case 0xff: if(show_status==1 || show_status==2)

  245.                                    led_on=~led_on;        //打開或關閉數(shù)碼管顯示

  246.                                             break;

  247.                         case 0x3f: if(show_status==0)         //如果正在設置鬧鐘

  248.                                              { if(cur_alarm_set==0)  cur_alarm_set=7;

  249.                              else cur_alarm_set--;}

  250.                         else if(show_status==3)     //當前日期的“年”減1

  251.                                     { if(year==0)  year=49;  else year--; }

  252.                                  else if(show_status==4)     //當前時間的“時”減1

  253.                                              { tmp=hour-1;  if(tmp<0) hour=23;  else  hour=tmp;  }

  254.                                       break;

  255.                         case 0xcf: if(show_status==0)          //鬧鐘設置的“時”減1

  256.                                              { tmp=alarm[cur_alarm_set].h-1;

  257.                                                if(tmp<0)    alarm[cur_alarm_set].h=23;

  258.                                                   else         alarm[cur_alarm_set].h=tmp;

  259.                                                  }

  260.                           else if(show_status==3)         

  261.                                     { month--;             //當前日期的“月”減1

  262.                              if(month==0)  month=12; }

  263.                                             else if(show_status==4)         

  264.                            { tmp=min-1;           //當前時間的“分”減1

  265.                             if(tmp<0) min=59;   else  min=tmp;   }

  266.                                           break;

  267.                         case 0xf3: if(show_status==0)          //鬧鐘設置的“分鐘”減1

  268.                                              { tmp=alarm[cur_alarm_set].m-1;

  269.                                                if(tmp<0)    alarm[cur_alarm_set].m=59;

  270.                                                   else         alarm[cur_alarm_set].m=tmp;

  271.                                                  }

  272.                           else if(show_status==3)     

  273.                                     { day--;                 //當前日期的“日”減1

  274.                              if(day==0)  day=31; }

  275.                                             else if(show_status==4)        

  276.                            { tmp=sec-1;             //當前時間的“秒”減1

  277.                              count_down=8000;

  278.                              if(tmp<0) sec=59;   else  sec=tmp; }

  279.                                             break;

  280.                         case 0xfd: if(show_status==0)                       //切換周末標志

  281.                                       alarm_wk^=0x1<<cur_alarm_set;

  282.                                             break;

  283.                         case 0xfe: if(show_status==0)                 //切換啟用標志

  284.                                       alarm_en^=0x1<<cur_alarm_set;

  285.                        }       //end of switch(attr)

  286.                       return;

  287.                      }         //end of if(keytmp==2)



  288.                 if(keytmp==8 & led_on)    //第四個按鈕,僅當數(shù)碼管打開時有效

  289.                  { switch(attr)

  290.                       { case 0xff: if(show_status==1)               //如果當前顯示日期

  291.                          show_status=3;       //切換到調(diào)準日期狀態(tài)

  292.                                else if(show_status==2)    //如果當前顯示時間

  293.                           show_status=4;      //切換到調(diào)準時間狀態(tài)

  294.                                      attr=0x3f; break;               //第一、二個數(shù)碼管閃爍

  295.                         case 0x3f: attr=0xcf; break;           //第三、四個數(shù)碼管閃爍

  296.                         case 0xcf: attr=0xf3; break;           //第五、六個數(shù)碼管閃爍

  297.                         case 0xf3: if(show_status==0) attr=0xfd;   //第七個數(shù)碼管閃爍

  298.                         else if(show_status==3)

  299.                            { show_status=1; attr=0xff; }  //恢復正常顯示日期

  300.                                  else if(show_status==4)

  301.                             { show_status=2; attr=0xff; }  //恢復正常顯示時間

  302.                                           break;

  303.                         case 0xfd: if(show_status==0) attr=0xfe;     //第八個數(shù)碼管閃爍

  304.                                    break;

  305.                         case 0xfe: if(show_status==0) attr=0x3f;     //第一、二個數(shù)碼管閃爍

  306.                       }

  307.                      }   // end of if(keytmp==4)

  308.                }      // end of if(kp==0)

  309.         }         // end of if(km==0)

  310.    }            // end of if(keytmp!=0)

  311. }



  312. main()

  313. {unsigned char i;



  314.   hour=23;  min=58;  sec=30;  year=2;  month=4;  day=25;

  315.   count_down=8000;



  316.   flash=0;    attr=0xff;      led_on=1;

  317.   km=0;     kp=0;          show_status=2;     //加電后顯示當前時間



  318.   new_alarm_info=0;  sound=0;   alarm_stop=0;  



  319.   for(i=0;i<8;i++)           //從EEPROM中讀入8個鬧鐘設置

  320.     { alarm[i].h=myread(i*2);  alarm[i].m=myread(i*2+1); }

  321.       alarm_en=myread(i*2);        alarm_wk=myread(i*2+1);



  322.   IE=0;  IP=0;             //disable all interrupt and lower priority

  323.   TMOD=0x12;             //timer 0 is set to mode 2,auto_reloading,timer1,mode 1

  324.   TH0=6;    TL0=6;        //timer0 parameters for 0.125ms

  325.   TH1=0x15; TL1=0xa0;      //timer1 parameters for 30ms

  326.   TR0=1;    TR1=1;        //timer0 interrupt most important

  327.   ET0=1;    ET1=1;    EA=1;     //enable interrupt function



  328.   while(1)

  329.   { if(led_on)

  330.       for(i=0;i<8;i++)

  331.           { P2=0;

  332.          if(flash || attr&(0x80>>i))

  333.                  { P0=display[i];  P2=0x80>>i; DelayX1ms(1); }

  334.               }

  335.     else  P2=0;  



  336.     if(new_alarm_info)

  337.      { P2=0;                  //暫時關閉數(shù)碼管

  338.           new_alarm_info=0;      //寫入EEPROM

  339.        for(i=0;i<8;i++)  { mywrite(i*2,alarm[i].h);  mywrite(i*2+1,alarm[i].m); }

  340.           mywrite(i*2,alarm_en);   mywrite(i*2+1,alarm_wk);

  341.          }

  342.   }  

  343. }

  344.  
復制代碼



</cur_alarm_set;
</cur_alarm_set;
</month;tmp++)
</count;i++)

作者: mengyudi1    時間: 2016-2-19 15:15
嘿嘿嘿嘿呵呵嘿嘿




歡迎光臨 (http://www.zg4o1577.cn/bbs/) Powered by Discuz! X3.1
主站蜘蛛池模板: 日韩中文字幕一区二区 | 久久久久久久久久久蜜桃 | 亚洲午夜av | 成人精品视频在线观看 | 国产精品久久久久久久久久久久 | 懂色中文一区二区三区在线视频 | 国产yw851.c免费观看网站 | 久久久99国产精品免费 | 精品综合 | 欧美成人h版在线观看 | 一区二区三区电影网 | 99精品欧美一区二区蜜桃免费 | 日韩在线视频免费观看 | 黄一区二区三区 | 九色av | 久久国产香蕉 | 国产成人精品999在线观看 | 夜夜爽99久久国产综合精品女不卡 | 免费成人毛片 | 午夜精品一区二区三区在线视频 | 亚洲精品第一 | 欧美激情在线一区二区三区 | 国产japanhdxxxx麻豆 | 欧美日韩国产在线观看 | 久久久久亚洲视频 | 三级特黄特色视频 | 青青草视频免费观看 | 日本特黄a级高清免费大片 国产精品久久性 | 二区三区av | 日干夜操 | 国产96在线 | 国产精品日韩一区二区 | 久久久国产精品视频 | 国产精品视频在线观看 | 中文字幕视频在线免费 | 日韩欧美一区二区三区在线播放 | 干干天天 | 日本人做爰大片免费观看一老师 | 欧美一区二区视频 | 国内自拍视频在线观看 | 97精品超碰一区二区三区 |