找回密码
 立即注册

QQ登录

只需一步,快速开始

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

STC89c52rc单片机4位数码时钟,4个按键是怎么设置时间的? 求帮助

[复制链接]
楼主
ID:213173 发表于 2019-4-2 11:22 | 显示全部楼层
按照你的硬件电路给你改写的程序,仿真走时不一定准确,实物比较准,也可以软件调整精确度。

  1. //K1键调整选择,K2键+,长按连+,K3键-,长按连-,K4键闹钟设置
  2. //定时器初始化程序根据晶振频率选择
  3. #include <reg51.h>
  4. #define uint unsigned int
  5. #define uchar unsigned char
  6. //#define key_S 300                                        //宏定义短按(约20ms)实物
  7. //#define key_L 6000                                        //宏定义长按(约2/3s)
  8. //#define key_M 3000                                        //宏定义长按(约1/3s)
  9. #define key_S 100                                        //宏定义短按(约20ms)仿真
  10. #define key_L 2000                                        //宏定义长按(约2/3s)
  11. #define key_M 1000                                        //宏定义长按(约1/3s)
  12. sbit K1 = P1^0;                                                //走时时间调整选择/退出
  13. sbit K2 = P1^1;                                                //++,长按连+
  14. sbit K3 = P1^2;                                                //--,长按连-
  15. sbit K4 = P1^3;                                                //闹钟时间调整选择/退出
  16. sbit wela1=P2^0;                                        //位选1
  17. sbit wela2=P2^1;                                        //位选2
  18. sbit wela3=P2^2;                                        //位选3
  19. sbit wela4=P2^3;                                        //位选4
  20. sbit Buzzer=P3^7;                                        //蜂鸣器
  21. uchar code table[]={//共阳数码管段码"0~f-."
  22.                 0xc0,0xf9,0xa4,0xb0,
  23.                 0x99,0x92,0x82,0xf8,
  24.                 0x80,0x90,0x88,0x83,
  25.                 0xc6,0xa1,0x86,0x8e,0xbf,0x7f};
  26. uint Cnt200us;                                                //定义200微秒变量
  27. uchar hour=12,min=0,sec=0;                        //定义时、分、秒变量
  28. uchar hour4=0,min4=0;                                //定义闹钟时、分变量
  29. uchar  Choice=0,Choice4=0;                        //调整走时的选择变量、设置闹钟的选择变量
  30. bit Buzzer_sign;                                        //蜂鸣器闹钟标志
  31. bit Twinkle,second=1;                                //闪烁标志、秒标志
  32. /**************************************
  33.         定时器0初始化程序 @12.000MHz
  34. **************************************/
  35. void Timer_Init(void)
  36. {
  37.         TMOD= 0x02;                        //设置定时器模式
  38.         TL0 = 0x38;                        //设置定时初值200微秒
  39.         TH0 = 0x38;                        //设置定时重载值200微秒
  40.         TR0 = 1;                        //定时器0开始计时
  41.         EA=1;                                //开总中断
  42.         ET0=1;                                //开定时器1中断
  43. }
  44. /***************************************
  45.         定时器0初始化程序 @11.0592MHz
  46. ***************************************/
  47. /*
  48. void Timer_Init()
  49. {
  50.         TMOD = 0x02;                //设置自动重载模式
  51.         TL0 = 0x48;                        //设置定时初值200微秒
  52.         TH0 = 0x48;                        //设置定时重载值200微秒
  53.         TR0 = 1;                        //定时器0开始计时
  54.         EA=1;                                //开总中断
  55.         ET0=1;                                //开定时器1中断
  56. }*/
  57. /*************************
  58.           按键扫描程序
  59. *************************/
  60. void key_scan()
  61. {
  62.         static bit key1_sign,key4_sign;        //按键自锁标志变量
  63.         static uint count1,count2,count3=0,count4=0;//消抖计数变量                       

  64.         if(!K1)                                                        //检测按键1按下
  65.         {
  66.                 count1++;                                        //消抖计数1自+1
  67.                 if((count1>=key_S)&&(key1_sign==0))//检测消抖计数与按键1自锁标志
  68.                 {                       
  69.                         key1_sign=1;                        //按键1自锁标志置1
  70.                         Choice++;                                //调整选择变量自+1
  71.                         if(Choice>=3)                        //调整时间选择0正常走时,1调时,2调分
  72.                         {
  73.                                 Choice=0;                        //调整时间选择清0
  74.                                 Cnt200us=0;                        //时间变量Cnt200us清0
  75.                                 sec=0;
  76.                         }
  77.                 }
  78.         }
  79.         else
  80.         {
  81.                 key1_sign=0;                                //按键1自锁标志清0
  82.                 count1=0;                                        //消抖计数count1清0
  83.         }
  84.                                
  85.         if(!K2)   
  86.         {  
  87.                 count2++;  
  88.                 if(count2>=key_L)                        //长按快调
  89.                 {
  90.                         if(Choice==1)                        //选择变量1调时
  91.                         {
  92.                                 hour++;
  93.                                 if(hour>=24)
  94.                                         hour=0;
  95.                         }
  96.                         if(Choice==2)                        //选择变量2调分
  97.                         {
  98.                                 min++;
  99.                                 if(min>=60)
  100.                                         min=0;
  101.                         }
  102.                         if(Choice4==1)                        //选择变量1调时
  103.                         {
  104.                                 hour4++;
  105.                                 if(hour4>=24)
  106.                                         hour4=0;
  107.                         }
  108.                         if(Choice4==2)                        //选择变量2调分
  109.                         {
  110.                                 min4++;
  111.                                 if(min4>=60)
  112.                                         min4=0;
  113.                         }
  114.                         count2=key_M;
  115.                 }
  116.         }  
  117.         else                                                        //按键抬起
  118.         {  
  119.                 if(count2>key_S && count2<key_L)//短按
  120.                 {
  121.                         if(Choice==1)                        //选择变量1调时
  122.                         {
  123.                                 hour++;
  124.                                 if(hour>=24)
  125.                                         hour=0;
  126.                         }
  127.                         if(Choice==2)                        //选择变量2调分
  128.                         {
  129.                                 min++;
  130.                                 if(min>=60)
  131.                                         min=0;
  132.                         }
  133.                         if(Choice4==1)                        //选择变量1调时
  134.                         {
  135.                                 hour4++;
  136.                                 if(hour4>=24)
  137.                                         hour4=0;
  138.                         }
  139.                         if(Choice4==2)                        //选择变量2调分
  140.                         {
  141.                                 min4++;
  142.                                 if(min4>=60)
  143.                                         min4=0;
  144.                         }
  145.                 }
  146.                 count2=0;                                        //count2清0
  147.         }   
  148.         if(!K3)   
  149.         {  
  150.                 count3++;  
  151.                 if(count3>=key_L)                        //长按
  152.                 {
  153.                         if(Choice==1)                        //选择变量
  154.                         {
  155.                                 hour--;
  156.                                 if(hour>=24)
  157.                                         hour=23;
  158.                         }
  159.                         if(Choice==2)                        //选择变量
  160.                         {
  161.                                 min--;
  162.                                 if(min>=60)
  163.                                         min=59;
  164.                         }
  165.                         if(Choice4==1)                        //选择变量
  166.                         {
  167.                                 hour4--;
  168.                                 if(hour4>=24)
  169.                                         hour4=23;
  170.                         }
  171.                         if(Choice4==2)                        //选择变量
  172.                         {
  173.                                 min4--;
  174.                                 if(min4>=60)
  175.                                         min4=59;
  176.                         }
  177.                         count3=key_M;
  178.                 }
  179.         }  
  180.         else                                                        //按键抬起
  181.         {  
  182.                 if(count3>key_S && count3<key_L)//短按
  183.                 {
  184.                         if(Choice==1)                        //选择变量
  185.                         {
  186.                                 hour--;
  187.                                 if(hour>=24)
  188.                                         hour=23;
  189.                         }
  190.                         if(Choice==2)                        //选择变量
  191.                         {
  192.                                 min--;
  193.                                 if(min>=60)
  194.                                         min=59;
  195.                         }
  196.                         if(Choice4==1)                        //选择变量
  197.                         {
  198.                                 hour4--;
  199.                                 if(hour4>=24)
  200.                                         hour4=23;
  201.                         }
  202.                         if(Choice4==2)                        //选择变量
  203.                         {
  204.                                 min4--;
  205.                                 if(min4>=60)
  206.                                         min4=59;
  207.                         }
  208.                 }
  209.                 count3=0;                                        //count3清0
  210.         }   
  211.         if(!K4)                                                        //检测按键1按下
  212.         {
  213.                 count4++;                                        //消抖计数1自+1
  214.                 if((count4>=key_S)&&(key4_sign==0))//检测消抖计数与按键1自锁标志
  215.                 {                       
  216.                         key4_sign=1;                        //按键1自锁标志置1
  217.                         Choice4++;                                //调整选择变量自+1
  218.                         if(Choice4>=4)                        //调整闹钟时间选择0闹钟关闭,1调时,2调分,3开启闹钟
  219.                         {
  220.                                 Choice4=0;                        //调整时间选择清0
  221.                         }
  222.                 }
  223.         }
  224.         else
  225.         {
  226.                 key4_sign=0;                                //按键1自锁标志清0
  227.                 count4=0;                                        //消抖计数count1清0
  228.         }
  229. }
  230. /********************************
  231.                 数码管显示程序
  232. ********************************/
  233. void display()
  234. {
  235.         static uchar num=0;                                //分时显示变量
  236.         if((Choice4>0)&&(Choice4<3))        //闹钟设置显示部分
  237.         {
  238.                 P0=0xff;        //消隐
  239.                 switch(num)
  240.                 {
  241.                         case 0:
  242. //                                P2=0x01;                        //时十位位码
  243.                                 P2=0xfe;                        //加PNP管反向
  244.                                 P0=table[hour4/10];        //时十位段码
  245.                                 num++;
  246.                          break;       
  247.        
  248.                         case 1:
  249. //                                P2=0x02;                        //时个位位码
  250.                                 P2=0xfd;                        //加PNP管反向
  251.                                 if((Twinkle==1)&&(Choice4==1))//时点闪烁
  252.                                         P0=table[hour4%10];
  253.                                 else
  254.                                         P0=table[hour4%10]&0x7f;//时个位段码+点
  255.                                 num++;
  256.                          break;       
  257.        
  258.                         case 2:
  259. //                                P2=0x04;                        //分十位位码
  260.                                 P2=0xfb;                        //加PNP管反向
  261.                                 P0=table[min4/10];        //分十位段码
  262.                                 num++;
  263.                          break;       
  264.        
  265.                         case 3:
  266. //                                P2=0x08;                        //分个位位码
  267.                                 P2=0xf7;                        //加PNP管反向
  268.                                 if((Twinkle==1)&&(Choice4==2))//分点闪烁
  269.                                         P0=table[min4%10];
  270.                                 else
  271.                                         P0=table[min4%10]&0x7f;//分个位段码+点
  272.                                 num=0;
  273.                          break;       
  274.                 }
  275.         }
  276.         else        //正常走时显示部分
  277.         {
  278.                 P0=0xff;        //消隐
  279.                 switch(num)
  280.                 {
  281.                         case 0:
  282. //                                P2=0x01;                        //时十位位码
  283.                                 P2=0xfe;                        //加PNP管反向
  284.                                 P0=table[hour/10];        //时十位段码
  285.                                 num++;
  286.                          break;       
  287.        
  288.                         case 1:
  289. //                                P2=0x02;                        //时个位位码
  290.                                 P2=0xfd;                        //加PNP管反向
  291.                                 if((Twinkle==1)&&(Choice==1))//时点闪烁
  292.                                         P0=table[hour%10];
  293.                                 else
  294.                                         P0=table[hour%10]&0x7f;//时个位段码+点
  295.                                 num++;
  296.                          break;       
  297.        
  298.                         case 2:
  299. //                                P2=0x04;                        //分十位位码
  300.                                 P2=0xfb;                        //加PNP管反向
  301.                                 P0=table[min/10];        //分十位段码
  302.                                 num++;
  303.                          break;       
  304.        
  305.                         case 3:
  306. //                                P2=0x08;                        //分个位位码
  307.                                 P2=0xf7;                        //加PNP管反向
  308.                                 if(Choice4==3)
  309.                                         P0=table[min%10]&0x7f;//闹钟启动后秒个位+点
  310.                                 else if((Twinkle==1)&&(Choice==2))//分+点闪烁
  311.                                         P0=table[min%10]&0x7f;
  312.                                 else if(Choice==1)        //分+点
  313.                                         P0=table[min%10]&0x7f;//分个位段码+点
  314.                                 else
  315.                                         P0=table[min%10];//分个位段码
  316.                                 num=0;
  317.                          break;       
  318.                 }
  319.         }
  320. }
  321. /********************************
  322.                 闹钟程序
  323. ********************************/
  324. void Buzzer_nz()
  325. {
  326.         if((Choice4==3)&&(hour4==hour)&&(min4==min)&&(sec<30))
  327.                 Buzzer_sign=1;
  328.         else Buzzer_sign=0;

  329.         if((second==1)&&(Buzzer_sign==1))//计时周期1s       
  330.                 Buzzer=0;                                        //蜂鸣器响
  331.         else Buzzer=1;
  332. }
  333. /********************************
  334.                 主程序
  335. ********************************/
  336. void main(void)
  337. {
  338.         Timer_Init();                                        //初始化定时器
  339.         while(1)
  340.         {
  341.                 key_scan();                                        //按键扫描函数
  342.                 display();                                        //显示函数
  343.                 Buzzer_nz();                                //闹钟函数
  344.         }
  345. }
  346. /*-----------------------------
  347.   定时器0中断服务程序  200微秒
  348. ------------------------------*/
  349. void timer0() interrupt        1
  350. {
  351.         Cnt200us++;                                                //时间变量Cnt200us自+1
  352.         if((Cnt200us>1250 && Cnt200us<2500)||(Cnt200us>3750 && Cnt200us<5000))//闪烁频率2Hz               
  353.                 Twinkle=1;                                        //闪烁标志
  354.         else Twinkle=0;
  355.         if(Cnt200us>=5000)                            //在此可以调整走时精度
  356.         {
  357.                 Cnt200us=0;                                        //变量Cnt200us清0
  358.                 second=~second;                                //秒标志取反
  359.                 if(Choice==0)                                //调整选择变量>0停止走秒
  360.                 {
  361.                         sec++;                                        //秒自+1
  362.                         if(sec>=60)                                //如果秒>=60
  363.                         {
  364.                                 sec=0;                                //秒清0
  365.                                 min++;                                //分自+1
  366.                                 if(min>=60)                        //分>=60
  367.                                 {
  368.                                         min=0;                        //分清0
  369.                                         hour++;                  //小时自+1
  370.                                         if(hour>=24)        //小时>=24
  371.                                                 hour=0;                //小时清0
  372.                                 }
  373.                         }
  374.                 }
  375.         }
  376. }


复制代码



回复

使用道具 举报

沙发
ID:213173 发表于 2019-4-3 11:21 | 显示全部楼层
zsf333666 发表于 2019-4-3 09:29
用不同的机器居然可以仿真了! 运行的很好,按键也能调整了。那个4069为啥不能用三极管代替

按键完全失效是因为用主循环计数方式消抖和判断长短按,仿真时主循环周期要比实际电路长得多(与PC配置有关),按键在预定消抖时间内没有响应,需要按的时间长些才行。4069就是反相器,实物完全可以用三极管代替,但仿真用三极管会不正常。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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