找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 4011|回復(fù): 1
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)數(shù)碼管鬧鐘顯示多個(gè)模式 掉電鬧鐘時(shí)間不丟失

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
數(shù)碼管顯示多個(gè)模式
實(shí)際使用的單片機(jī)為STC89C52,可實(shí)現(xiàn)掉電鬧鐘時(shí)間不丟失,開關(guān)狀態(tài)不丟失的功能
由于Proteus中沒有STC,所以用AT的51代替,因此該功能在仿真中不能實(shí)現(xiàn)(AT51沒有內(nèi)部EEPROM),實(shí)際電路是可行的
PS:鬧鐘鈴聲為本校校歌-------《一方沃土》

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機(jī)源程序如下:
  1. #include<reg52.h>
  2. #include<intrins.h>
  3. #include"buzzer.h"
  4. #include"delay.h"       
  5. #include"stc_eeprom.h"
  6. #include"ds1302.h"
  7. #include"display.h"
  8. #include"keyscan.h"

  9. #define uchar unsigned char
  10. #define uint unsigned int

  11. char alarm_hour=0,alarm_minute=23;//鬧鐘時(shí)間設(shè)置        有符號
  12. uchar alarm_temp[8];
  13. uchar num1,alarm_en,alarm_switch=1;

  14. uchar tms=0,sec=0,temp_tms=0,temp_sec=0,dq_sec,dq_tms,k=3;//秒表        k為顯示的位數(shù)0-k,按下分圈計(jì)時(shí)則顯示8位
  15. bit miaobiao_flag=0,fenquan_flag=0;
  16. uchar num;         //用來做定時(shí)器動(dòng)態(tài)掃描的基數(shù)
  17. uchar mb_temp[8];//用來儲存轉(zhuǎn)換成數(shù)碼管各位顯示的數(shù)據(jù)

  18. /*******************************************************************/
  19. /**************************鬧鐘判斷函數(shù)***************************/
  20. /*******************************************************************/
  21. void alarm_judge()
  22. {
  23.         if(alarm_hour==time[4]&&alarm_minute==time[5]&&alarm_en&&alarm_switch)
  24.         {       
  25.                 key0_count=4;//強(qiáng)制切換到鬧鐘顯示狀態(tài),防止兩種顯示互相干擾(表現(xiàn)為秒顯示有殘影)
  26.                 tune=music[i]+music[i+1]*7-1;
  27.                 pai=music[i+2];
  28.                 TH1=tuneH[tune];
  29.                 TL1=tuneL[tune];
  30.                 TR1=1;
  31.                 delay_jiepai(pai);
  32.                 i+=3;
  33.                 if(i>138)          //循環(huán)播放
  34.                         i=0;       
  35.         }
  36.         else
  37.         {
  38.                 buzzer=1;
  39.                 i=0;
  40.         }       
  41. }
  42. /*******************************************************************/
  43. /************************分圈計(jì)時(shí)的計(jì)算函數(shù)*************************/
  44. /*******************************************************************/
  45. void fenquanjishi()
  46. {
  47.         temp_tms+=dq_tms;
  48.         temp_sec+=dq_sec;                //前n-1圈時(shí)間之和
  49.         if(temp_tms>99)                  //若10毫秒數(shù)達(dá)到100則進(jìn)位到秒
  50.         {
  51.                 temp_tms-=100;
  52.                 temp_sec++;
  53.         }
  54.         if(tms<temp_tms)                //若總時(shí)間的10毫秒數(shù)小于前n-1圈和的10毫秒數(shù),則從秒借位
  55.         {       
  56.                 dq_tms=tms+100-temp_tms;
  57.                    dq_sec=sec-temp_sec-1;
  58.         }
  59.         else                                                                                 //第n圈單圈時(shí)間=總時(shí)間-前n-1圈時(shí)間之和
  60.         {
  61.                 dq_tms=tms-temp_tms;
  62.                 dq_sec=sec-temp_sec;
  63.         }       
  64. }
  65. /*******************************************************************/
  66. /**************************主函數(shù)部分***************************/
  67. /*******************************************************************/
  68. void main()
  69. {
  70.         //ds1302_init();
  71.         alarm_hour=stc_eeprom_read(rom1);
  72.         alarm_minute=stc_eeprom_read(rom2);//開機(jī)將存在單片機(jī)內(nèi)部eeprom的鬧鐘時(shí)間和開關(guān)讀出
  73.         alarm_switch=stc_eeprom_read(rom3);
  74.         alarm_en=0;//鬧鐘使能默認(rèn)為0,用來復(fù)位關(guān)鬧鈴
  75.         EA=1;
  76.         IP=0x02;  //設(shè)置定時(shí)器0中斷優(yōu)先,保證秒表走時(shí)的準(zhǔn)確
  77.         TMOD=0x11;                //設(shè)置定時(shí)器工作方式
  78.         ET1=1;
  79.         ET0=1;         //定時(shí)器0和1中斷
  80.         while(1)
  81.         {
  82.                 static uchar keyscan_count;//按鍵掃描計(jì)數(shù),減少按鍵掃描頻率
  83.                 keyscan_count++;
  84.                 if(keyscan_count==10)          //每隔10次進(jìn)行按鍵掃描
  85.                 {
  86.                         keyscan_count=0;
  87.                         keyscan();
  88.                 }
  89.                    read_time();                   //從ds1302中讀出數(shù)據(jù)
  90.                 if(time[6]==0)                   //走過新的一分鐘后才重新打開鬧鐘使能,用來配合復(fù)位關(guān)鬧鈴
  91.                         alarm_en=1;                                                             //(此時(shí)鬧鐘的分鐘與實(shí)際時(shí)間已不等)
  92.                 alarm_judge();         //鬧鐘判斷
  93. /*******************************************************************/
  94. /**************************時(shí)分秒顯示部分***************************/
  95. /*******************************************************************/
  96.                 if(key0_count==0)                          
  97.                 {
  98.                         display_time(time[4],time[5],time[6]);
  99.                         if(key1_count==1&&(key2_flag||key3_flag))
  100.                         {
  101.                                 if(key2_flag)          //判斷加還是減
  102.                                 {       
  103.                                         time[4]++;
  104.                                         key2_flag=0;
  105.                                         if(time[4]>23)
  106.                                                 time[4]=0;
  107.                                 }
  108.                                 else if(key3_flag)
  109.                                 {       
  110.                                         time[4]--;
  111.                                         key3_flag=0;
  112.                                         if(time[4]<0)
  113.                                                 time[4]=23;
  114.                                 }
  115.                                 ds1302_set_time(write_add[4],time[4]);            
  116.                         }
  117.                         else if(key1_count==2&&(key2_flag||key3_flag))
  118.                         {
  119.                                 if(key2_flag)                 
  120.                                 {       
  121.                                         time[5]++;
  122.                                         key2_flag=0;
  123.                                         if(time[5]>59)
  124.                                                 time[5]=0;
  125.                                 }
  126.                                 else if(key3_flag)
  127.                                 {
  128.                                         time[5]--;
  129.                                         if(time[5]<0)
  130.                                                 time[5]=59;                                    
  131.                                         key3_flag=0;
  132.                                 }
  133.                                 ds1302_set_time(write_add[5],time[5]);                            
  134.                         }
  135.                         else if(key1_count==3&&(key2_flag||key3_flag))
  136.                         {
  137.                                 if(key2_flag)
  138.                                 {       
  139.                                         time[6]++;
  140.                                         key2_flag=0;
  141.                                         if(time[6]>59)
  142.                                                 time[6]=0;
  143.                                 }
  144.                                 else if(key3_flag)
  145.                                 {       
  146.                                         time[6]--;                                       
  147.                                         if(time[6]<0)
  148.                                                 time[6]=59;                                    
  149.                                         key3_flag=0;
  150.                                 }
  151.                                 ds1302_set_time(write_add[6],time[6]);                            
  152.                         }
  153.                 }
  154. /*******************************************************************/
  155. /**************************年月日顯示部分***************************/
  156. /*******************************************************************/
  157.                 else if(key0_count==1)
  158.                 {
  159.                         display_time(time[0],time[2],time[3]);
  160.                         static uchar Max_Day;
  161.                         switch(time[2])
  162.                         {
  163.                                 case 4:
  164.                                 case 6:
  165.                                 case 9:
  166.                                 case 11:Max_Day=30;break;
  167.                                 case 2:
  168.                                                 if(time[0]%4==0) Max_Day=29;
  169.                                                 else Max_Day=28;
  170.                                                 break;
  171.                                 default:Max_Day=31;                   //判斷各月的天數(shù)
  172.                         }
  173.                         if(key1_count==1&&(key2_flag||key3_flag))
  174.                         {
  175.                                 if(key2_flag)
  176.                                 {
  177.                                         time[0]++;
  178.                                         key2_flag=0;
  179.                                         if(time[0]>99)
  180.                                                 time[0]=0;
  181.                                 }
  182.                                 else if(key3_flag)
  183.                                 {
  184.                                         time[0]--;                                       
  185.                                         if(time[0]<0)
  186.                                                 time[0]=99;
  187.                                         key3_flag=0;
  188.                                 }
  189.                                 ds1302_set_time(write_add[0],time[0]);            
  190.                         }
  191.                         else if(key1_count==2&&(key2_flag||key3_flag))
  192.                         {
  193.                                 if(key2_flag)
  194.                                 {       
  195.                                         time[2]++;
  196.                                           if(time[2]>12)
  197.                                                 time[2]=1;
  198.                                         key2_flag=0;
  199.                                 }
  200.                                 else if(key3_flag)
  201.                                 {
  202.                                         time[2]--;
  203.                                         if(time[2]<1)
  204.                                                 time[2]=12;
  205.                                         key3_flag=0;
  206.                                 }
  207.                                 ds1302_set_time(write_add[2],time[2]);                            
  208.                         }
  209.                         else if(key1_count==3&&(key2_flag||key3_flag))
  210.                         {
  211.                                 if(key2_flag)
  212.                                 {
  213.                                         time[3]++;
  214.                                         key2_flag=0;
  215.                                         if(time[3]>Max_Day)
  216.                                                 time[3]=1;
  217.                                 }
  218.                                 else if(key3_flag)
  219.                                 {
  220.                                         time[3]--;
  221.                                         if(time[3]<1)
  222.                                                 time[3]=Max_Day;
  223.                                         key3_flag=0;
  224.                                 }
  225.                                 ds1302_set_time(write_add[3],time[3]);                            
  226.                         }
  227.                 }
  228. /*******************************************************************/
  229. /**************************秒表顯示部分***************************/         
  230. /*******************************************************************/
  231.                 else if(key0_count==2)           //如果模式選擇鍵按下2次,進(jìn)入秒表模式
  232.                 {
  233.                         miaobiao_flag=1;//秒表模式的標(biāo)志
  234.                         TH0=(65536-50000)/256;
  235.                         TL0=(65536-50000)%256;
  236.                         TH1=(65536-5000)/256;
  237.                         TL1=(65536-5000)%256;
  238.                         TR1=1;
  239.                         do
  240.                         {
  241.                                 keyscan();                           //程序在此循環(huán)時(shí)不漏掉按鍵掃描
  242.                                 if(key1_count)
  243.                                 {
  244.                                         TR0=1;
  245.                                 }
  246.                                 else
  247.                                 {
  248.                                         TR0=0;                          
  249.                                         if(fenquan_flag)        //進(jìn)入分圈計(jì)后,即使按下停止鍵也能記出最后一圈的時(shí)間
  250.                                         {
  251.                                                  fenquanjishi();
  252.                                                  fenquan_flag=0;
  253.                                         }
  254.                                 }
  255.                                 if(key3_flag)
  256.                                 {
  257.                                         tms=0;
  258.                                         sec=0;
  259.                                         dq_sec=0;
  260.                                         dq_tms=0;
  261.                                         temp_sec=0;
  262.                                         temp_tms=0;
  263.                                         fenquan_flag=0;
  264.                                         key3_flag=0;
  265.                                         k=3;                        //按下清零鍵所有數(shù)據(jù)清零,只顯示數(shù)碼管0-3位正常秒表
  266.                                 }
  267.                                 else if(key2_flag&&TR0)//加TR0是為了在定時(shí)器未啟動(dòng)時(shí)分圈計(jì)時(shí)鍵無效
  268.                                 {
  269.                                         key2_flag=0;
  270.                                         k=7;                          //顯示8位數(shù)碼管,后四位為單圈時(shí)間
  271.                                         fenquanjishi();
  272.                                 }
  273.                         }while(key0_count==2);        //防止重復(fù)設(shè)置定時(shí)器
  274.                 }
  275. /*******************************************************************/
  276. /**************************星期顯示部分***************************/
  277. /*******************************************************************/
  278.                 else if(key0_count==3)                        //如果模式選擇鍵按下3次,進(jìn)入星期顯示模式
  279.                 {
  280.                          uchar b=0;
  281.                          static uchar dis_count=0;
  282.                          dis_count++;
  283.                          if(dis_count>51)
  284.                                  dis_count=1;
  285.                          if(key1_count)
  286.                                  b=50;
  287.                          if(dis_count>b)         //若key1按下則閃動(dòng),表示進(jìn)入調(diào)時(shí)模式
  288.                          {
  289.                                  P2=table2[7];
  290.                                  P0=table1[time[1]%16];
  291.                                  delay(10);
  292.                                 P2=0xff;
  293.                                 delay(10);
  294.                          }
  295.                          if(key1_count&&(key2_flag||key3_flag))
  296.                          {
  297.                                 if(key2_flag)
  298.                                 {       
  299.                                         time[1]++;
  300.                                         if(time[1]>7)
  301.                                                 time[1]=1;
  302.                                         key2_flag=0;
  303.                                 }
  304.                                 else if(key3_flag)
  305.                                 {
  306.                                         time[1]--;
  307.                                         if(time[1]<1)
  308.                                                 time[1]=7;                               
  309.                                         key3_flag=0;
  310.                                 }
  311.                                 ds1302_set_time(write_add[1],time[1]);            
  312.                         }
  313.                 }
  314. /*******************************************************************/
  315. /**************************鬧鐘顯示部分***************************/
  316. /*******************************************************************/
  317.                 else if(key0_count==4)                 //如果模式選擇鍵按下4次,進(jìn)入鬧鐘顯示模式
  318.                 {
  319.                          uchar v1;
  320.                          if(alarm_switch)
  321.                          {
  322.                                  display_time(alarm_hour,alarm_minute,0);
  323.                          }
  324.                          else
  325.                          {
  326.                                  P2=0xff;
  327.                                 P0=0x40;
  328.                                 P2=table2[v1];
  329.                                 delay(3);
  330.                                 v1++;
  331.                                 if(v1==8)
  332.                                         v1=0;
  333.                          }
  334.                          if(key1_count==0&&(key2_flag||key3_flag))
  335.                          {
  336.                                  if(key2_flag)
  337.                                 {
  338.                                         key2_flag=0;
  339.                                         alarm_switch=1;
  340.                                         stc_eeprom_erase(rom3);                         //擦除扇區(qū)
  341.                                         stc_eeprom_write(rom3,alarm_switch);          //寫入扇區(qū)
  342.                                  }
  343.                                  else if(key3_flag)
  344.                                  {
  345.                                          key3_flag=0;
  346.                                         alarm_switch=0;
  347.                                         stc_eeprom_erase(rom3);                       
  348.                                         stc_eeprom_write(rom3,alarm_switch);       
  349.                                  }
  350.                          }
  351.                          else if(key1_count==1&&(key2_flag||key3_flag))
  352.                          {
  353.                                  if(key2_flag)
  354.                                 {       
  355.                                         alarm_hour++;
  356.                                            key2_flag=0;
  357.                                         if(alarm_hour>23)
  358.                                                 alarm_hour=0;
  359.                                 }
  360.                                 else if(key3_flag)
  361.                                 {
  362.                                         alarm_hour--;
  363.                                         if(alarm_hour<0)
  364.                                                 alarm_hour=23;
  365.                                         key3_flag=0;
  366.                                 }
  367.                                 stc_eeprom_erase(rom1);                         
  368.                                 stc_eeprom_write(rom1,alarm_hour);         
  369.                          }
  370.                          else if(key1_count==2&&(key2_flag||key3_flag))
  371.                          {
  372.                                  if(key2_flag)
  373.                                 {       
  374.                                         alarm_minute++;
  375.                                         key2_flag=0;
  376.                                         if(alarm_minute>59)
  377.                                                 alarm_minute=0;
  378.                                 }
  379.                                 else if(key3_flag)
  380.                                 {
  381.                                         alarm_minute--;                               
  382.                                         if(alarm_minute<0)
  383.                                                 alarm_minute=59;                       
  384.                                         key3_flag=0;
  385.                                 }
  386.                                 stc_eeprom_erase(rom2);
  387.                                 stc_eeprom_write(rom2,alarm_minute);
  388.                          }
  389.                          alarm_temp[0]=table1[alarm_hour/10];
  390.                           alarm_temp[1]=table1[alarm_hour%10];
  391.                             alarm_temp[2]=0x40;
  392.                           alarm_temp[3]=table1[alarm_minute/10];
  393.                            alarm_temp[4]=table1[alarm_minute%10];
  394.                            alarm_temp[5]=0x40;
  395.                           alarm_temp[6]=table1[0];
  396.                           alarm_temp[7]=table1[0];                 //轉(zhuǎn)化成位顯示,方便進(jìn)入定時(shí)器時(shí)動(dòng)態(tài)掃描
  397.                 }
  398.         }
  399. }
  400. /*******************************************************************/
  401. /**************************定時(shí)器0和1中斷函數(shù)***************************/
  402. /*******************************************************************/
  403. ……………………

  404. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
929861698Clock.zip (111.03 KB, 下載次數(shù): 37)


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:641580 發(fā)表于 2019-12-4 19:41 | 只看該作者
eeprom的程序沒有嘛
回復(fù)

使用道具 舉報(bào)

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表