找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1601|回复: 2
收起左侧

一款实用的单片机电子钟制作 附程序原理图

[复制链接]
ID:1044703 发表于 2022-9-14 10:57 | 显示全部楼层 |阅读模式
一、电路图
二、使用说明:
功能按键说明:S1为功能选择按键和移位的作用,S2为确认作用,S3为数值加一作用。
功能调节说明:
1、时钟功能:
    如果是芯片内部定时器的时钟,上电后显示00:00:00(掉电后时间不行走不保存,重新上电时间就归0);
    如果是外部时钟DS1302的套件,上电后则显示芯片的内部时间(这个时间掉电后可以保持行走,从新上电显示当前的时间);
2、校时功能:按一次S1,数码管显示SET1(设置时间),这时按一次S2就进入修改时间,数码管显示00:00(秒位不可调)小时的十位闪烁状态,再次按S1可以移动闪烁的位置,按一次移动一位,按S3时,对应闪烁位置的数据会加1,设置后后再按S2就保存并退出;
3、闹钟功能:按两次S1,数码管显示SET2(设置闹钟),这时按一次S2就进入修改闹钟,数码管显示00:00 0(秒位不可调,后面的0代表闹钟的状态,0代表闹钟关闭,1表示闹钟开启)小时的十位闪烁状态,再次按S1可以移动闪烁的位置,按一次移动一位,按S3时,对应闪烁位置的数据会加1,设置后后再按S2就保存并退出;
4、倒计时功能:按三次次S1,数码管显示SET3(设置倒计时),这时按一次S2就进入修改倒计时,数码管显示00:00:00,小时的十位闪烁状态,再次按S1可以移动闪烁的位置,按一次移动一位,按S3时,对应闪烁位置的数据会加1,设置后后再按S2后,系统就开始倒计时;
5、秒表功能:按四次S1,数码管显示SET4(秒表功能),这时按一次S2就秒表功能,此时S2用来开启或关闭秒表,S3退出秒表功能;
6、计数器功能:按五次S1,数码管显示SET5(计数器功能),这时按一次S2就进入计数器,按S3计数器的值加1,再次按S2退出计数器,系统恢复;

电路原理图如下:
001.png

单片机源程序如下:
  1. /*====================================================================
  2.   调试要求:
  3.   1.MCU:AT89S52芯片或AT89C52
  4.   2.晶振:12MHz
  5.   功能:启动芯片内部计时
  6. ====================================================================*/
  7. #include <reg52.h>
  8. #include <intrins.h>

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

  11. sbit    dis_bit1=P2^7;//定义数码管控制口
  12. sbit    dis_bit2=P2^6;//定义数码管控制口
  13. sbit    dis_bit3=P2^4;//定义数码管控制口
  14. sbit    dis_bit4=P2^3;//定义数码管控制口
  15. sbit    dis_bit5=P2^1;//定义数码管控制口
  16. sbit    dis_bit6=P2^0;//定义数码管控制口
  17. sbit    led1_bit=P2^2;//定时LED的控制口
  18. sbit    led2_bit=P2^5;//定时LED的控制口
  19. sbit    s1_bit=P1^0;  //定义S1控制口
  20. sbit    s2_bit=P1^1;  //定义S2控制口
  21. sbit    s3_bit=P1^2;  //定义S3控制口
  22. sbit    speak=P3^7;   //定义蜂鸣器控制口
  23. #define smg_data    P0//定义数码管数据口


  24. void  delay_50us(uint t);//延时50*T微妙函数的声明
  25. void  display1(uchar dis_data);//数码管1显示子程序
  26. void  display2(uchar dis_data);//数码管2显示子程序
  27. void  display3(uchar dis_data);//数码管3显示子程序
  28. void  display4(uchar dis_data);//数码管4显示子程序
  29. void  display5(uchar dis_data);//数码管5显示子程序
  30. void  display6(uchar dis_data);//数码管6显示子程序
  31. void  init_t0();//定时器0初始化函数
  32. void  dis_led();//LED处理函数
  33. void  judge_s1();//S1按键处理函数
  34. void  judge_s2();//S2按键处理函数
  35. void  judge_s3();//S3按键处理函数
  36. void  dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1);//显示子程序
  37. void  dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san);//闪烁显示子程序
  38. void  judge_dis();//显示处理函数
  39. void  judge_clock();//显示处理函数
  40. //共阳数码管断码表
  41. const unsigned char tabl1[17]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
  42.                                // 0  1    2    3    4    5
  43.                                0x82,0xf8,0x80,0x90,0x86,0x87,0xFF,
  44.                               //6   7     8    9     E    T   B
  45.                                     0xc6,0xa1,0x8e,0xb6};
  46.                               //    C     D    F    三

  47. uchar t0_crycle;
  48. uchar hour_count,minute_count,second_count,msecond_count;
  49. uchar clock_hour,clock_minute;
  50. uchar clock_en;//闹钟关闭和开启的标志,1开启,0关闭
  51. uchar flag1,zancun1,zancun2,zancun3;//,flag2;
  52. uchar clock_flag;
  53. uint  speak_count;
  54. //主程序
  55. void main()
  56. {
  57.     P3=0x00;
  58.     flag1=0;   
  59.     zancun3=0;
  60.     speak=1;//关闭蜂鸣器
  61.     speak_count=0;
  62.     clock_hour=0;
  63.     clock_minute=0;
  64.     clock_flag=0;
  65.    
  66.     clock_en=0;//开机时默认关闭闹钟
  67.     init_t0();
  68.     TR0=1;//
  69.    //接下来开始编写让数码管显示的程序
  70.     while(1)
  71.     {
  72.       judge_dis();//显示处理
  73.       judge_s1();
  74.       judge_s2();
  75.       judge_s3();
  76.       judge_clock();//闹钟处理程序
  77.     }
  78. }
  79. void timer0() interrupt 1
  80. {
  81.         TH0=(65536-50000)/256;
  82.         TL0=(65536-50000)%256;
  83.         t0_crycle++;
  84.         if(t0_crycle==2)// 0.1秒
  85.         {
  86.           t0_crycle=0;
  87.           msecond_count++;
  88.       if(msecond_count==10)//1秒
  89.       {
  90.         msecond_count=0;
  91.         second_count++;
  92.         if(second_count==60)
  93.         {
  94.           second_count=0;
  95.           minute_count++;
  96.           if(minute_count==60)
  97.           {
  98.             minute_count=0;
  99.             hour_count++;
  100.             if(hour_count==24)
  101.             {
  102.               hour_count=0;
  103.             }
  104.           }
  105.         }
  106.       }   
  107.         }
  108. }
  109. //**************************************************
  110. //显示处理函数
  111. void  judge_dis()
  112. {     
  113.     if(flag1==0)
  114.     {
  115.       dis(hour_count/10,hour_count%10,minute_count/10,minute_count%10,second_count/10,second_count%10);
  116.       dis_led();
  117.     }
  118.     if(flag1!=0)
  119.     {
  120.        switch(flag1)
  121.        {
  122.            case 1:
  123.                 dis(5,10,11,1,12,12);//显示SET1
  124.                 led1_bit=1;
  125.                 led2_bit=1;
  126.                 break;
  127.            case 2:
  128.                 dis(5,10,11,2,12,12);//显示SET2
  129.                 break;
  130.            case 3:
  131.                 dis(5,10,11,3,12,12);//显示SET3
  132.                 break;
  133.            case 4:
  134.                 dis(5,10,11,4,12,12);//显示SET4
  135.                 break;
  136.            case 5:
  137.                 dis(5,10,11,5,12,12);//显示SET5
  138.                 break;
  139.            case 6:
  140.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,1);
  141.                 break;
  142.            case 7:
  143.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,2);
  144.                 break;
  145.            case 8:
  146.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,3);
  147.                 break;
  148.            case 9://进入修改时间,时间分位个位闪烁
  149.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,12,4);
  150.                 break;
  151.            case 10://进入修改闹钟,闹钟小时十位闪烁
  152.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,1);
  153.                 break;
  154.            case 11://进入修改闹钟,闹钟小时个位闪烁
  155.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,2);
  156.                 break;
  157.            case 12://进入修改闹钟,闹钟小时十位闪烁
  158.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,3);
  159.                 break;
  160.            case 13://进入修改闹钟,闹钟小时个位闪烁
  161.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,4);
  162.                 break;
  163.            case 14://进入修改闹钟的开关
  164.                 dis_san(zancun1/10,zancun1%10,zancun2/10,zancun2%10,12,zancun3,6);
  165.                 break;
  166.            default:
  167.                 break;
  168.         }
  169.     }
  170. }
  171. //**************************************************
  172. //S1按键处理函数
  173. void  judge_s1()
  174. {
  175.     s1_bit=1;//置IO为1,准备读入收据
  176.     if(s1_bit==0)//判断是否有按键按下
  177.     {
  178.         delay_50us(1);// 延时,去除机械抖动
  179.         if(s1_bit==0)
  180.         {
  181.            switch(flag1)
  182.            {
  183.                case 0:
  184.                     flag1=1;
  185.                     break;
  186.                case 1:
  187.                     flag1=2;
  188.                     break;
  189.                case 2:
  190.                     flag1=3;
  191.                     break;
  192.                case 3:
  193.                     flag1=4;
  194.                     break;
  195.                case 4:
  196.                     flag1=5;
  197.                     break;
  198.                case 5:
  199.                     flag1=0;
  200.                     break;
  201.                case 6://在修改时间小时十位下按S1键
  202.                     flag1=7;
  203.                     break;
  204.                case 7:
  205.                     flag1=8;
  206.                     break;
  207.                case 8:
  208.                     flag1=9;
  209.                     break;
  210.                case 9:
  211.                     flag1=6;
  212.                     break;
  213.                case 10:
  214.                     flag1=11;
  215.                     break;
  216.                case 11:
  217.                     flag1=12;
  218.                     break;
  219.                case 12:
  220.                     flag1=13;
  221.                     break;
  222.                case 13:
  223.                     flag1=14;
  224.                     break;
  225.                case 14:
  226.                     flag1=10;
  227.                     break;
  228.                default:
  229.                     break;
  230.            }           
  231.            while(s1_bit==0)
  232.            {
  233.               judge_dis();
  234.            }//等待按键释放
  235.         }
  236.     }
  237. }
  238. //**************************************************
  239. //S2按键处理函数
  240. void  judge_s2()
  241. {
  242.     s2_bit=1;//置IO为1,准备读入收据
  243.     if(s2_bit==0)//判断是否有按键按下
  244.     {
  245.         delay_50us(1);// 延时,去除机械抖动
  246.         if(s2_bit==0)
  247.         {
  248.            switch (flag1)
  249.            {
  250.               case 1: //在显示SET1状态下按S2件,进入修改时间
  251.                  flag1=6;
  252.                  zancun1=hour_count;
  253.                  zancun2=minute_count;
  254.                  break;
  255.               case 2://在显示SET2状态下按S2,进入设置闹钟
  256.                  zancun1=clock_hour;
  257.                  zancun2=clock_minute;
  258.                  flag1=10;
  259.                  break;
  260.               case 6://修改时钟小时十位状态下按S2件
  261.                  hour_count=zancun1;
  262.                  minute_count=zancun2;
  263.                  second_count=0;
  264.                  flag1=0;
  265.                  break;
  266.               case 7://修改时钟小时个位状态下按S2件
  267.                  hour_count=zancun1;
  268.                  minute_count=zancun2;
  269.                  second_count=0;
  270.                  flag1=0;
  271.                  break;
  272.               case 8://修改时钟分钟十位状态下按S2件
  273.                  hour_count=zancun1;
  274.                  minute_count=zancun2;
  275.                  second_count=0;
  276.                  flag1=0;
  277.                  break;
  278.               case 9://修改时钟分钟个位状态下按S2件
  279.                  hour_count=zancun1;
  280.                  minute_count=zancun2;
  281.                  second_count=0;
  282.                  flag1=0;
  283.                  break;
  284.               case 10:
  285.                  clock_hour=zancun1;
  286.                  clock_minute=zancun2;
  287.                  clock_en=zancun3;
  288.                  flag1=0;
  289.                  break;
  290.               case 11:
  291.                  clock_hour=zancun1;
  292.                  clock_minute=zancun2;
  293.                  clock_en=zancun3;
  294.                  flag1=0;
  295.                  break;
  296.               case 12:
  297.                  clock_hour=zancun1;
  298.                  clock_minute=zancun2;
  299.                  clock_en=zancun3;
  300.                  flag1=0;
  301.                  break;
  302.               case 13:
  303.                  clock_hour=zancun1;
  304.                  clock_minute=zancun2;
  305.                  clock_en=zancun3;
  306.                  flag1=0;
  307.                  break;
  308.               case 14:
  309.                  clock_hour=zancun1;
  310.                  clock_minute=zancun2;
  311.                  clock_en=zancun3;
  312.                  flag1=0;
  313.                  break;
  314.               default:
  315.                  break;
  316.                  
  317.            }   
  318.            while(s2_bit==0)
  319.            {
  320.               judge_dis();
  321.            }//等待按键释放
  322.         }
  323.     }
  324. }
  325. //**************************************************
  326. //S3按键处理函数
  327. void  judge_s3()
  328. {
  329.     s3_bit=1;//置IO为1,准备读入收据
  330.     if(s3_bit==0)//判断是否有按键按下
  331.     {
  332.         delay_50us(1);// 延时,去除机械抖动
  333.         if(s3_bit==0)
  334.         {
  335.            switch (flag1)
  336.            {
  337.             
  338.               case 6://修改时间小时的十位数
  339.                  zancun1+=10;
  340.                  if(zancun1>=24)zancun1=zancun1%10;
  341.                  break;
  342.               case 7://修改时间小时的个位数
  343.                  zancun1=zancun1/10*10+(zancun1%10+1)%10;
  344.                  if(zancun1>=24)zancun1=20;
  345.                  break;
  346.               case 8://修改时间分钟的十位数
  347.                  zancun2+=10;
  348.                  if(zancun2>=60)zancun2-=60;
  349.                  break;
  350.               case 9://修改时间分钟的个位数
  351.                  zancun2=zancun2/10*10+(zancun2%10+1)%10;
  352.                  break;
  353.               case 10://修改闹钟小时的十位数
  354.                  zancun1+=10;
  355.                  if(zancun1>=24)zancun1=zancun1%10;
  356.                  break;
  357.               case 11://修改闹钟小时的个位数
  358.                  zancun1=zancun1/10*10+(zancun1%10+1)%10;
  359.                  if(zancun1>=24)zancun1=20;
  360.                  break;
  361.               case 12://修改闹钟分钟的十位数
  362.                  zancun2+=10;
  363.                  if(zancun2>=60)zancun2-=60;
  364.                  break;
  365.               case 13://修改闹钟分钟的个位数
  366.                  zancun2=zancun2/10*10+(zancun2%10+1)%10;
  367.                  break;
  368.               case 14:
  369.                  zancun3^=1;
  370.                  break;
  371.               default:
  372.                  break;
  373.                  
  374.            }   
  375.            while(s3_bit==0)
  376.            {
  377.               judge_dis();
  378.            }//等待按键释放
  379.         }
  380.     }
  381. }
  382. //****************************************
  383. //显示处理函数
  384. void  judge_clock()
  385. {
  386.     if(clock_hour==hour_count && clock_minute==minute_count)
  387.     {
  388.          if(clock_en==1 && clock_flag==0)
  389.          {         
  390.               speak_count=0;//开启蜂鸣器
  391.               clock_flag=1;
  392.               speak_count=0;
  393.          }
  394.     }
  395.     else
  396.     {
  397.      clock_flag=0;
  398.     }
  399.     if(clock_flag==1 && speak_count<400)
  400.     {
  401.       
  402.         if(msecond_count<=5)
  403.         {
  404.            speak=0;
  405.            speak_count++;
  406.         }
  407.         else
  408.         {
  409.           speak=1;
  410.    
  411.         }
  412.     }
  413.     else
  414.     {
  415.         speak=1;
  416.     }
  417. }
  418. //****************************************
  419. ////闪烁显示子程序
  420. void  dis_san(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1,uchar san)
  421. {   
  422.      if(san==1)
  423.      {
  424.         if(msecond_count<5)
  425.         {
  426.            display1(s6);
  427.         }
  428.      }
  429.      else
  430.      {
  431.          display1(s6);
  432.      }
  433.      if(san==2)
  434.      {
  435.         if(msecond_count<5)
  436.         {
  437.            display2(s5);
  438.         }
  439.      }
  440.      else
  441.      {
  442.          display2(s5);
  443.      }
  444.      if(san==3)
  445.      {
  446.         if(msecond_count<5)
  447.         {
  448.            display3(s4);
  449.         }
  450.      }
  451.      else
  452.      {
  453.          display3(s4);
  454.      }
  455.      if(san==4)
  456.      {
  457.         if(msecond_count<5)
  458.         {
  459.            display4(s3);
  460.         }
  461.      }
  462.      else
  463.      {
  464.          display4(s3);
  465.      }
  466.      if(san==6)
  467.      {
  468.         if(msecond_count<5)
  469.         {
  470.            display6(s1);
  471.         }
  472.      }
  473.      else
  474.      {
  475.          display6(s1);
  476.      }
  477.      display5(s2);
  478.     // display6(s1);
  479. }
  480. //****************************************
  481. //时钟显示程序
  482. void  dis(uchar s6,uchar s5,uchar s4,uchar s3,uchar s2,uchar s1)
  483. {
  484.      display1(s6);
  485.      display2(s5);
  486.      display3(s4);
  487.      display4(s3);
  488.      display5(s2);
  489.      display6(s1);
  490. }
  491. //********************************************************************************************
  492. void init_t0()
  493. {
  494.            TMOD=0x01;//设定定时器工作方式1,定时器定时50毫秒
  495.         TH0=(65536-50000)/256;
  496.         TL0=(65536-50000)%256;
  497.         EA=1;//开总中断
  498.         ET0=1;//允许定时器0中断
  499.         t0_crycle=0;//定时器中断次数计数单元
  500. }
  501. //**************************************************
  502. //LED处理函数
  503. void  dis_led()
  504. {
  505.      if(msecond_count<5)
  506.      {
  507.          led1_bit=1;
  508.          led2_bit=1;
  509.      }
  510.      else
  511.      {
  512.          led1_bit=0;
  513.          led2_bit=0;
  514.      }
  515. }
  516. //***************************************************************
  517. //功能:把数据1显示在数码管1上
  518. void display6(uchar dis_data)
  519. {  
  520.    smg_data=tabl1[dis_data];//送显示断码
  521.    dis_bit6=0;//锁存数据
  522.    delay_50us(40);
  523.    dis_bit6=1;
  524. }
  525. //***************************************************************
  526. //功能:把数据1显示在数码管1上
  527. void display5(uchar dis_data)
  528. {  
  529.    smg_data=tabl1[dis_data];//送显示断码
  530.    dis_bit5=0;//锁存数据
  531.    delay_50us(40);
  532.    dis_bit5=1;
  533. }
  534. //***************************************************************
  535. //功能:把数据1显示在数码管1上
  536. void display4(uchar dis_data)
  537. {  
  538.    smg_data=tabl1[dis_data];//送显示断码
  539.    dis_bit4=0;//锁存数据
  540.    delay_50us(40);
  541.    dis_bit4=1;
  542. }//***************************************************************
  543. //功能:把数据1显示在数码管1上
  544. void display3(uchar dis_data)
  545. {  
  546.    smg_data=tabl1[dis_data];//送显示断码
  547.    dis_bit3=0;//锁存数据
  548.    delay_50us(40);
  549.    dis_bit3=1;
  550. }
  551. //***************************************************************
  552. //功能:把数据1显示在数码管1上
  553. void display1(uchar dis_data)
  554. {  
  555.    smg_data=tabl1[dis_data];//送显示断码
  556.    dis_bit1=0;//锁存数据
  557.    delay_50us(40);
  558.    dis_bit1=1;
  559. }
  560. //***************************************************************
  561. //功能:把数据1显示在数码管1上
  562. void display2(uchar dis_data)
  563. {  
  564.    smg_data=tabl1[dis_data];//送显示断码
  565.    dis_bit2=0;//锁存数据
  566.    delay_50us(40);
  567.    dis_bit2=1;
  568. }
  569. //**************************************************************************************************
  570. //函数名称:void delay_50US(unsigned int t)
  571. //功能: 延时50*t(us)
  572. void delay_50us(uint t)
  573. {
  574.   unsigned char j;
  575.   for(;t>0;t--)
  576.   {
  577.     for(j=19;j>0;j--);
  578.   }
  579. }
复制代码

评分

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

查看全部评分

回复

使用道具 举报

ID:638376 发表于 2022-9-15 16:19 | 显示全部楼层
实用参考下程序写法
回复

使用道具 举报

ID:253767 发表于 2022-9-16 07:41 | 显示全部楼层
这单片机是什么类型
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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