找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2734|回复: 1
打印 上一主题 下一主题
收起左侧

单片机数码管闹钟显示多个模式 掉电闹钟时间不丢失

[复制链接]
跳转到指定楼层
楼主
数码管显示多个模式
实际使用的单片机为STC89C52,可实现掉电闹钟时间不丢失,开关状态不丢失的功能
由于Proteus中没有STC,所以用AT的51代替,因此该功能在仿真中不能实现(AT51没有内部EEPROM),实际电路是可行的
PS:闹钟铃声为本校校歌-------《一方沃土》

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


单片机源程序如下:
  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;//闹钟时间设置        有符号
  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为显示的位数0-k,按下分圈计时则显示8位
  15. bit miaobiao_flag=0,fenquan_flag=0;
  16. uchar num;         //用来做定时器动态扫描的基数
  17. uchar mb_temp[8];//用来储存转换成数码管各位显示的数据

  18. /*******************************************************************/
  19. /**************************闹钟判断函数***************************/
  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;//强制切换到闹钟显示状态,防止两种显示互相干扰(表现为秒显示有残影)
  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)          //循环播放
  34.                         i=0;       
  35.         }
  36.         else
  37.         {
  38.                 buzzer=1;
  39.                 i=0;
  40.         }       
  41. }
  42. /*******************************************************************/
  43. /************************分圈计时的计算函数*************************/
  44. /*******************************************************************/
  45. void fenquanjishi()
  46. {
  47.         temp_tms+=dq_tms;
  48.         temp_sec+=dq_sec;                //前n-1圈时间之和
  49.         if(temp_tms>99)                  //若10毫秒数达到100则进位到秒
  50.         {
  51.                 temp_tms-=100;
  52.                 temp_sec++;
  53.         }
  54.         if(tms<temp_tms)                //若总时间的10毫秒数小于前n-1圈和的10毫秒数,则从秒借位
  55.         {       
  56.                 dq_tms=tms+100-temp_tms;
  57.                    dq_sec=sec-temp_sec-1;
  58.         }
  59.         else                                                                                 //第n圈单圈时间=总时间-前n-1圈时间之和
  60.         {
  61.                 dq_tms=tms-temp_tms;
  62.                 dq_sec=sec-temp_sec;
  63.         }       
  64. }
  65. /*******************************************************************/
  66. /**************************主函数部分***************************/
  67. /*******************************************************************/
  68. void main()
  69. {
  70.         //ds1302_init();
  71.         alarm_hour=stc_eeprom_read(rom1);
  72.         alarm_minute=stc_eeprom_read(rom2);//开机将存在单片机内部eeprom的闹钟时间和开关读出
  73.         alarm_switch=stc_eeprom_read(rom3);
  74.         alarm_en=0;//闹钟使能默认为0,用来复位关闹铃
  75.         EA=1;
  76.         IP=0x02;  //设置定时器0中断优先,保证秒表走时的准确
  77.         TMOD=0x11;                //设置定时器工作方式
  78.         ET1=1;
  79.         ET0=1;         //定时器0和1中断
  80.         while(1)
  81.         {
  82.                 static uchar keyscan_count;//按键扫描计数,减少按键扫描频率
  83.                 keyscan_count++;
  84.                 if(keyscan_count==10)          //每隔10次进行按键扫描
  85.                 {
  86.                         keyscan_count=0;
  87.                         keyscan();
  88.                 }
  89.                    read_time();                   //从ds1302中读出数据
  90.                 if(time[6]==0)                   //走过新的一分钟后才重新打开闹钟使能,用来配合复位关闹铃
  91.                         alarm_en=1;                                                             //(此时闹钟的分钟与实际时间已不等)
  92.                 alarm_judge();         //闹钟判断
  93. /*******************************************************************/
  94. /**************************时分秒显示部分***************************/
  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;                   //判断各月的天数
  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次,进入秒表模式
  232.                 {
  233.                         miaobiao_flag=1;//秒表模式的标志
  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();                           //程序在此循环时不漏掉按键扫描
  242.                                 if(key1_count)
  243.                                 {
  244.                                         TR0=1;
  245.                                 }
  246.                                 else
  247.                                 {
  248.                                         TR0=0;                          
  249.                                         if(fenquan_flag)        //进入分圈计后,即使按下停止键也能记出最后一圈的时间
  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;                        //按下清零键所有数据清零,只显示数码管0-3位正常秒表
  266.                                 }
  267.                                 else if(key2_flag&&TR0)//加TR0是为了在定时器未启动时分圈计时键无效
  268.                                 {
  269.                                         key2_flag=0;
  270.                                         k=7;                          //显示8位数码管,后四位为单圈时间
  271.                                         fenquanjishi();
  272.                                 }
  273.                         }while(key0_count==2);        //防止重复设置定时器
  274.                 }
  275. /*******************************************************************/
  276. /**************************星期显示部分***************************/
  277. /*******************************************************************/
  278.                 else if(key0_count==3)                        //如果模式选择键按下3次,进入星期显示模式
  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按下则闪动,表示进入调时模式
  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次,进入闹钟显示模式
  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);                         //擦除扇区
  341.                                         stc_eeprom_write(rom3,alarm_switch);          //写入扇区
  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];                 //转化成位显示,方便进入定时器时动态扫描
  397.                 }
  398.         }
  399. }
  400. /*******************************************************************/
  401. /**************************定时器0和1中断函数***************************/
  402. /*******************************************************************/
  403. ……………………

  404. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
929861698Clock.zip (111.03 KB, 下载次数: 36)


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:641580 发表于 2019-12-4 19:41 | 只看该作者
eeprom的程序没有嘛
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表