找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机C51电子时钟按键式程序及仿真

[复制链接]
跳转到指定楼层
楼主
电子时钟仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)


单片机源程序如下:
  1. #include "reg52.H"
  2. #include "stdio.h"
  3. #include "intrins.h"
  4. sbit K1 = P3^4;//设置键
  5. sbit K2 = P3^5;//加键
  6. sbit K3 = P3^6;//减键
  7. sbit K4 = P3^7;//日期时间切换键
  8. unsigned char  pre_key = 0x0f;//记录按键状态
  9. unsigned char  key_value;//获取到按键的值
  10. #define  DIG_SEG   P0         //段选
  11. #define  DIG_PLA   P2   //位选
  12. unsigned char code dig_tab[18] =//共阴数码管码表
  13. {
  14.                 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0、1、2、3、4、5、6、7、
  15.                 0x7f,0x6f,0x77,0x00,0x39,0x5e,0x79,0x71,//8、9、A、B、C、D、E、F、
  16.                 0x40,0x00//-
  17. };
  18. unsigned char dig_show_fir;//数码管第一位显示值
  19. unsigned char dig_show_two;//数码管第二位显示值
  20. unsigned char dig_show_thr;//数码管第三位显示值
  21. unsigned char dig_show_fou;//数码管第四位显示值
  22. unsigned char dig_show_fiv;//数码管第五位显示值
  23. unsigned char dig_show_six;//数码管第六位显示值
  24. unsigned char dig_show_sev;//数码管第七位显示值
  25. unsigned char dig_show_eig;//数码管第八位显示值
  26. unsigned char dig_show_tmp = 0;//显示临时变量
  27. unsigned char now_window;//当前显示窗口
  28. unsigned char now_win_sta;//当前显示状态
  29. unsigned char win_sta_tmp;//显示状态临时变量
  30. unsigned char tim_flg;//倒计时标志1S一次
  31. unsigned char nian,yue,ri,shi,fen,miao;//定义时分秒年月日
  32. signed char tim_temp[3] = {0};//时分秒设置临时变量
  33. #define  FLIOPE   200//数码管闪烁时间常量
  34. #define  FLICLO   400//数码管闪烁时间常量
  35. unsigned char   part;//数码管闪烁标志设置的时候
  36. unsigned int    sci_count;//数码管闪烁时间
  37. unsigned char   curr_menu;

  38. unsigned char alm_tim_cnt;//报警时间计数
  39. unsigned char alm_flag;//报警标志
  40. unsigned char dist_yel_alm;//东西南北黄灯闪烁区分变量
  41. void init_all_hardware(void);//初始化硬件
  42. void delay_ms(unsigned int cnt);//延时函数
  43. void time_init(void);//定时器初始化
  44. void key_scan(void);//按键扫描
  45. void key_service(void);//按键处理函数
  46. void dis_dri(void);//动态数码管扫描
  47. void display_service(void);//数码显示处理
  48. void timing_service(void);//倒计时函数
  49. void main(void)
  50. {
  51.         init_all_hardware();//初始化硬件,IO和定时器
  52.                 while(1)
  53.                 {
  54.                         key_scan();//按键扫描
  55.                         key_service();//按键服务处理函数
  56.                         display_service();//数码显示处理
  57.                         timing_service();//倒计时函数
  58.                 }
  59. }
  60. /******************************************************
  61. ** 函数名:init_all_hardware
  62. ** 描述  :初始化所有硬件,及其变量参数。
  63. ** 输入  :无
  64. ** 输出  :无
  65. ** 调用  :主程序
  66. ******************************************************/
  67. void init_all_hardware(void)
  68. {
  69.                    delay_ms(100);
  70.                 time_init();//定时器初始化
  71.                 key_value = 0;
  72.                 dig_show_fir = 17;//开机不显示
  73.                 dig_show_two = 17;//开机不显示
  74.                 dig_show_thr = 17;//开机不显示
  75.                 dig_show_fou = 17;//开机不显示
  76.                 dig_show_fiv = 17;//开机不显示
  77.         dig_show_six = 17;//开机不显示
  78.         dig_show_sev = 17;//开机不显示
  79.         dig_show_eig = 17;//开机不显示
  80.                 shi = 8; //初始化时分秒
  81.                 fen = 12;
  82.                 miao = 35;
  83.                 nian = 16;//初始化年月日
  84.                 yue  = 1;
  85.                 ri   = 4;
  86.                 part = 0;
  87.                 sci_count = 0;
  88.                 curr_menu = 0;
  89.                 now_window = 1;
  90.                 now_win_sta = 1;
  91.         EA=1;
  92.                 delay_ms(1000);//延时1S
  93. }
  94. /*******************************************************************************
  95. * 函 数 名         : delay_ms
  96. * 函数功能                   : 延时函数,延时1ms
  97. * 输    入         : cnt
  98. * 输    出         : 无
  99. * 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
  100. *******************************************************************************/
  101. void delay_ms(unsigned int cnt)   //
  102. {
  103.         unsigned int x;
  104.         for( ; cnt>0; cnt--)
  105.         {
  106.                 for(x=110; x>0; x--);//软件延时为1MS
  107.         }
  108. }
  109. /******************************************************
  110. ** 函数名:time_init
  111. ** 描述  :定时器初始化
  112. ** 输入  :无
  113. ** 输出  :无
  114. ******************************************************/
  115. void time_init(void)
  116. {
  117.           TMOD |= 0x01;//time0 工作方式为1
  118.           TH0 = 0xf8;//装载初值
  119.           TL0 = 0x2f;//装载初值,为2ms(65535-63535)
  120.       TR0 = 1;//开启定时器
  121.           ET0 = 1;//打开中断
  122.           ES = 1;
  123. }
  124. /******************************************************
  125. ** 函数名:key_scan
  126. ** 描述  :按键扫描
  127. ** 输入  :无
  128. ** 输出  :无
  129. ******************************************************/
  130. void key_scan(void)
  131. {
  132.           P3 |=0xf0;//P3高四位置高
  133.           if (pre_key==(P3&0xf0))return;//按键状态未改变时继续
  134.           pre_key = P3&0xf0;//保存当前最新按键状态
  135.           if (!K1)//特殊模式按键
  136.           {
  137.                   delay_ms(10);//延时10ms
  138.                   if(!K1)//还判断为按下
  139.                   {
  140.                             key_value = 1;//触发按键值
  141.                   }
  142.           }
  143.           if (!K2)//特殊模式按键
  144.           {
  145.                   delay_ms(10);//延时10ms
  146.                   if(!K2)//还判断为按下
  147.                   {
  148.                             key_value = 2;//触发按键值
  149.                   }
  150.           }
  151.           if (!K3)//特殊模式按键
  152.           {
  153.                   delay_ms(10);//延时10ms
  154.                   if(!K3)//还判断为按下
  155.                   {
  156.                             key_value = 3;//触发按键值
  157.                   }
  158.           }
  159.           if (!K4)//特殊模式按键
  160.           {
  161.                   delay_ms(10);//延时10ms
  162.                   if(!K4)//还判断为按下
  163.                   {
  164.                             key_value = 4;//触发按键值
  165.                   }
  166.           }

  167. }
  168. /******************************************************
  169. ** 函数名:key_service
  170. ** 描述  :按键服务函数
  171. ** 输入  :无
  172. ** 输出  :无
  173. ** 调用  :主程序
  174. ******************************************************/
  175. void key_service(void)
  176. {
  177.                 switch(now_window)//选择不同窗口
  178.                 {
  179.                         case 1:
  180.                         {
  181.                                 switch(key_value)
  182.                                 {
  183.                                         case 1://切换到设置日期
  184.                                         {
  185.                                                 now_window = 3;
  186.                                                 now_win_sta = 31;
  187.                                                 tim_temp[0] = shi;
  188.                                                 tim_temp[1] = fen;
  189.                                                 tim_temp[2] = miao;
  190.                                                 part = 1;
  191.                                                 curr_menu = 1;
  192.                                         }
  193.                                         key_value = 0;
  194.                                         break;
  195.                                         case 4://切换到显示日期
  196.                                         {
  197.                                                 now_window = 2;
  198.                                                 now_win_sta = 2;
  199.                                         }
  200.                                         key_value = 0;
  201.                                         break;
  202.                                 }
  203.                         }
  204.                         break;
  205.                         case 2:
  206.                         {
  207.                                 switch(key_value)
  208.                                 {
  209.                                         case 4://切换到显示时间
  210.                                         {
  211.                                                 now_window = 1;
  212.                                                 now_win_sta = 1;
  213.                                         }
  214.                                         key_value = 0;
  215.                                         break;
  216.                                 }
  217.                         }
  218.                         break;
  219.                         case 3:
  220.                         {
  221.                                 switch(key_value)
  222.                                 {
  223.                                         case 1://设置日期
  224.                                         {
  225.                                                 if (curr_menu<4)
  226.                                                         curr_menu++;
  227.                                                 if (curr_menu == 2)
  228.                                                 {
  229.                                                         part = 2;
  230.                                                         now_win_sta = 31;
  231.                                                 }
  232.                                                 else if(curr_menu == 3)
  233.                                                 {

  234.                                                         part = 3;
  235.                                                         now_win_sta = 31;
  236.                                                 }
  237.                                                 else if (curr_menu == 4)
  238.                                                 {
  239.                                                         curr_menu = 0;
  240.                                                         now_window = 1;
  241.                                                         now_win_sta = 1;
  242.                                                 }
  243.                                         }
  244.                                         key_value = 0;
  245.                                         break;
  246.                                         case 2://日期加
  247.                                         {
  248.                                                 if(curr_menu == 1)
  249.                                                 {
  250.                                                         if (++tim_temp[2]>59)
  251.                                                         {
  252.                                                                 tim_temp[2] = 0;
  253.                                                         }
  254.                                                         miao = tim_temp[2];
  255.                                                 }
  256.                                                 else if (curr_menu == 2)
  257.                                                 {
  258.                                                         if (++tim_temp[1]>59)
  259.                                                         {
  260.                                                                 tim_temp[1] = 0;
  261.                                                         }
  262.                                                         fen = tim_temp[1];
  263.                                                 }
  264.                                                 else if (curr_menu == 3)
  265.                                                 {
  266.                                                         if (++tim_temp[0]>23)
  267.                                                         {
  268.                                                                 tim_temp[0] = 0;
  269.                                                         }
  270.                                                         shi = tim_temp[0];
  271.                                                 }
  272.                                         }
  273.                                         key_value = 0;
  274.                                         break;
  275.                                         case 3://日期减
  276.                                         {
  277.                                                 if(curr_menu == 1)
  278.                                                 {
  279.                                                         if (--tim_temp[2]<0)
  280.                                                         {
  281.                                                                 tim_temp[2] = 59;
  282.                                                         }
  283.                                                         miao = tim_temp[2];
  284.                                                 }
  285.                                                 else if (curr_menu == 2)
  286.                                                 {
  287.                                                         if (--tim_temp[1]<0)
  288.                                                         {
  289.                                                                 tim_temp[1] = 59;
  290.                                                         }
  291.                                                         fen = tim_temp[1];
  292.                                                 }
  293.                                                 else if (curr_menu == 3)
  294.                                                 {
  295.                                                         if (--tim_temp[0]<0)
  296.                                                         {
  297.                                                                 tim_temp[0] = 23;
  298.                                                         }
  299.                                                         shi = tim_temp[0];
  300.                                                 }
  301.                                         }
  302.                                         key_value = 0;
  303.                                         break;
  304.                                 }
  305.                         }
  306.                         break;
  307.                 }
  308. }
  309. /*******************************************************************************
  310. * 函 数 名         : dis_dri
  311. * 函数功能                   : 数码管扫描函数
  312. * 输    入         : 无
  313. * 输    出         : 无
  314. *******************************************************************************/
  315. void dis_dri(void)
  316. {
  317.                            static unsigned char dis_step = 1;
  318.                            DIG_SEG = 0x00;
  319.                            switch(dis_step)
  320.                            {
  321.                                   case 1:  //显示第1位
  322.                                   {
  323.                                            dig_show_tmp=dig_tab[dig_show_fir];

  324.                                                    DIG_SEG = dig_show_tmp;
  325.                                                    DIG_PLA = 0xfe;
  326.                                   }
  327.                                   break;
  328.                                   case 2:  //显示第2位
  329.                                   {
  330.                                            dig_show_tmp=dig_tab[dig_show_two];

  331.                                                    DIG_SEG = dig_show_tmp;
  332.                                                    DIG_PLA = 0xfd;
  333.                                   }
  334.                                   break;
  335.                   case 3:  //显示第3位
  336.                                   {
  337.                                            dig_show_tmp=dig_tab[dig_show_thr];

  338.                                                    DIG_SEG = dig_show_tmp;
  339.                                                    DIG_PLA = 0xfb;
  340.                                   }
  341.                                   break;
  342.                   case 4:  //显示第4位
  343.                                   {
  344.                                            dig_show_tmp=dig_tab[dig_show_fou];

  345.                                                    DIG_SEG = dig_show_tmp;
  346.                                                    DIG_PLA = 0xf7;
  347.                                   }
  348.                                   break;
  349.                   case 5:  //显示第5位
  350.                                   {
  351.                                            dig_show_tmp=dig_tab[dig_show_fiv];

  352.                                                    DIG_SEG = dig_show_tmp;
  353.                                                    DIG_PLA = 0xef;
  354.                                   }
  355.                                   break;
  356.                   case 6:  //显示第6位
  357.                                   {
  358.                                            dig_show_tmp=dig_tab[dig_show_six];

  359.                                                    DIG_SEG = dig_show_tmp;
  360.                                                    DIG_PLA = 0xdf;
  361.                                   }
  362.                                   break;
  363.                   case 7:  //显示第7位
  364.                                   {
  365.                                            dig_show_tmp=dig_tab[dig_show_sev];

  366.                                                    DIG_SEG = dig_show_tmp;
  367.                                                    DIG_PLA = 0xbf;
  368.                                   }
  369.                                   break;
  370.                   case 8:  //显示第8位
  371.                                   {
  372.                                            dig_show_tmp=dig_tab[dig_show_eig];

  373.                                                    DIG_SEG = dig_show_tmp;
  374.                                                    DIG_PLA = 0x7f;
  375.                                   }
  376.                                   break;

  377.                            }
  378.                            dis_step++;
  379.                            if(dis_step>8)        //扫描完4个数码管后,重新从第一个开始扫描
  380.                            {
  381.                                   dis_step=1;
  382.                            }
  383. }
  384. /*******************************************************************************
  385. * 函 数 名       : display_service()
  386. * 函数功能                 : 显示服务函数
  387. * 输    入       : 无
  388. * 输    出       : 无
  389. *******************************************************************************/
  390. void display_service(void)
  391. {
  392.                         switch(now_window)
  393.                         {
  394.                                  case 1://显示时间
  395.                                  {
  396.                                         if (now_win_sta == 1)//刷新显示
  397.                                         {
  398.                                                 now_win_sta = 0;
  399.                                                 dig_show_fir = miao/10;//显示秒
  400.                                                 dig_show_two = miao%10;//显示秒
  401.                                                 dig_show_fou = 16;//显示-
  402.                                                 dig_show_six = fen/10;//显示分
  403.                                                 dig_show_thr = fen%10;//显示分
  404.                                                 dig_show_fiv = 16;//显示-
  405.                                                 dig_show_sev = shi/10;//显示时
  406.                                                 dig_show_eig = shi%10;//显示时
  407.                                         }
  408.                                  }
  409.                                  break;
  410.                                  case 2://显示日期
  411.                                  {
  412.                                         if (now_win_sta == 2)//刷新显示
  413.                                         {
  414.                                                 now_win_sta = 0;
  415.                                                 dig_show_fir = ri/10;//显示秒
  416.                                                 dig_show_two = ri%10;//显示秒
  417.                                                 dig_show_fou = 16;//显示-
  418.                                                 dig_show_six = yue/10;//显示分
  419.                                                 dig_show_thr = yue%10;//显示分
  420.                                                 dig_show_fiv = 16;//显示-
  421.                                                 dig_show_sev = nian/10;//显示时
  422.                                                 dig_show_eig = nian%10;//显示时
  423.                                         }
  424.                                  }
  425.                                  break;
  426.                                  case 3:
  427.                                  {

  428.                                                 if(now_win_sta ==31)
  429.                                                 {
  430.                                                         now_win_sta = 0;
  431.                                                         dig_show_fir = tim_temp[2]/10;//显示秒
  432.                                                         dig_show_two = tim_temp[2]%10;//显示秒
  433.                                                         dig_show_fou = 16;//显示-
  434.                                                         dig_show_six = tim_temp[1]/10;//显示分
  435.                                                         dig_show_thr = tim_temp[1]%10;//显示分
  436.                                                         dig_show_fiv = 16;//显示-
  437.                                                         dig_show_sev = tim_temp[0]/10;//显示时
  438.                                                         dig_show_eig = tim_temp[0]%10;//显示时
  439.                                                 }
  440.                                                 switch (part)//设置时候闪烁
  441.                                                 {
  442.                                                         case 1://秒闪烁
  443.                                                         {
  444.                                                                 if (sci_count == FLIOPE)
  445.                                                                 {
  446.                                                                         dig_show_fir = tim_temp[2] / 10;
  447.                                                                         dig_show_two = tim_temp[2] % 10;
  448.                                                                 }
  449.                                                                 else if (sci_count > FLICLO)
  450.                                                                 {
  451.                                                                         sci_count = 0;
  452.                                                                         dig_show_fir = 17;
  453.                                                                         dig_show_two = 17;
  454.                                                                 }
  455.                                                         }
  456.                                                         break;
  457.                                                         case 2://分闪烁
  458.                                                         {
  459.                                                                 if (sci_count == FLIOPE)
  460.                                                                 {
  461.                                                                         dig_show_six = tim_temp[1] / 10;
  462.                                                                         dig_show_thr = tim_temp[1] % 10;
  463.                                                                 }
  464.                                                                 else if (sci_count > FLICLO)
  465.                                                                 {
  466.                                                                         sci_count = 0;
  467.                                                                         dig_show_six = 17;
  468.                                                                         dig_show_thr = 17;
  469.                                                                 }
  470.                                                         }
  471.                                                         break;
  472.                                                         case 3://时闪烁
  473.                                                         {
  474.                                                                 if (sci_count == FLIOPE)
  475.                                                                 {
  476.                                                                         dig_show_sev = tim_temp[0] / 10;
  477.                                                                         dig_show_eig = tim_temp[0] % 10;
  478.                                                                 }
  479.                                                                 else if (sci_count > FLICLO)
  480.                                                                 {
  481.                                                                         sci_count = 0;
  482.                                                                         dig_show_sev = 17;
  483.                                                                         dig_show_eig = 17;
  484.                                                                 }
  485.                                                         }
  486.                                                         break;
  487.                                                 }
  488.                                  }
  489.                                  break;
  490.                         }
  491. }
  492. /******************************************************
  493. ** 函数名:timing_service
  494. ** 描述  :定时1秒函数
  495. ** 输入  : 无
  496. ** 输出  :无
  497. ** 调用  :中断调用
  498. ******************************************************/
  499. void timing_service(void)//倒计时函数
  500. {
  501.                          if (tim_flg == 1)
  502.                          {
  503.                 tim_flg = 0;
  504.                                 now_win_sta = 1;
  505.                                 miao++;
  506.                                 if(miao==60)//六十秒到了吗
  507.                     {
  508.                                          fen++;//分加加
  509.                             miao=0;
  510.                             if(fen==60)//六十分到了吗
  511.                         {
  512.                                            shi++;
  513.                            fen=0;
  514.                            if(shi==24)//24小时到了吗
  515.                            {
  516.                                                   shi=0;    //时清零
  517.                          fen=0;
  518.                          miao=0;
  519.                                                  ri++;
  520.                                                  if (ri==30)
  521.                                                  {
  522.                                                          ri = 1;
  523.                                                  }
  524.                            }
  525.                         }
  526.                     }
  527.             }
  528. }
  529. /******************************************************
  530. ** 函数名:time0_interrupt
  531. ** 描述  :按键扫描函数
  532. ** 输入  :无
  533. ** 输出  :无
  534. ******************************************************/
  535. void time0_interrupt() interrupt 1
  536. {
  537.        static unsigned int base_2ms_buff;
  538.            static unsigned int samping_cnt = 0;//1//1S钟计时
  539.            TF0 = 0;//清除标志
  540.            TR0 = 0;
  541.            dis_dri();//动态扫描数码管
  542.            if (++samping_cnt  > 500)
  543.            {
  544.                         samping_cnt = 0;
  545.                         if (now_window!=3)
  546.                         {
  547.                                 tim_flg = 1;
  548.                         }
  549.            }
  550.            if (++base_2ms_buff==50)
  551.            {
  552.                         base_2ms_buff = 0;
  553.                         if (alm_tim_cnt)
  554.             alm_tim_cnt--;
  555.            }
  556.        if (++sci_count > 2000)
  557.        {
  558.                         sci_count = 0;
  559.        }
  560.            TR0 = 1;
  561.            TH0 = 0xf8;
  562.            TL0 = 0x2f;//装载初值2ms(65535-63535)
  563. }
复制代码

所有资料51hei提供下载:
电子钟程序程序及电路.zip (63.26 KB, 下载次数: 54)


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

沙发
ID:928002 发表于 2021-6-18 15:54 | 只看该作者
谢了,下载就能用。就是程序说明有点少。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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