找回密码
 立即注册

QQ登录

只需一步,快速开始

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

解决单片机按键控制数码管带来闪灭显示问题的项目工程(优化版一)

[复制链接]
ID:171036 发表于 2020-5-20 21:31 | 显示全部楼层 |阅读模式
本帖最后由 51黑电子会员 于 2020-5-22 08:38 编辑
  1. /*****
  2. 为什么按下按键到按键抬起后,会干扰到数码管的显示?原因:如果按键扫描
  3. 函数和数码管显示函数都放在主函数的固定循环内,当按键按下后,按键扫描
  4. 函数进行按键扫描,在扫描到按键延时后,CPU被限制在按键延时处进行计时,
  5. 却无法运行其他程序,从而导致数码管显示函数无法运行,就会出现数码管闪
  6. 灭显示问题。人能看到数码管闪烁是因为人眼能识别高频率(人眼看不到闪烁
  7. 的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪
  8. 烁,数码管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高
  9. 好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
  10. 本程序分两个程序。一个是程序一,按键控制数码管带来闪灭显示问题的程序。
  11. 另一个是程序二,解决按键控制数码管带来闪灭显示问题的程序。通过把数码
  12. 管显示函数放在定时器中断子程序中,以及把按键扫描函数放在主函数固定循
  13. 环内。提醒:先试程序一,再试程序二,之后两者对比,找出不同点,取最适
  14. 合的。
  15. *****/
  16. //程序一:按键控制数码管带来闪灭显示问题的程序
  17. //#include<reg51.h>
  18. //#define uchar unsigned char
  19. //#define uint unsigned int
  20. //sbit add=P3^0;
  21. //sbit dec=P3^4;
  22. //uchar lingweiflag;
  23. //uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。
  24. //uint num;
  25. //uint qian,bai,shi,ge;//定义拆字变量
  26. //  /**ms级延时子程序**/
  27. //  void delay(uint x)
  28. //{
  29. //   uint i,j;                       
  30. //   for(i=0;i<x;i++)     
  31. //    for(j=0;j<110;j++);
  32. //  }
  33. //  void display()
  34. //{
  35. //   qian=num/1000;//取得千位数字
  36. //   bai=num%1000/100;//取得百位数字
  37. //   shi=num%100/10;//取得十位数字
  38. //   ge=num%10;//取得个位数字
  39. //
  40. //   P2=0xfe;//数码管千位显示位
  41. //   P1=table[qian];//数码管千位数值显示
  42. //   delay(2);//延时
  43. //
  44. //   P2=0xfd;//数码管百位显示位
  45. //   P1=table[bai];//数码管百位数值显示
  46. //   delay(2);//延时
  47. //
  48. //   P2=0xfb;//数码管十位显示位
  49. //   P1=table[shi];//数码管十位数值显示
  50. //   delay(2);//延时
  51. //
  52. //   P2=0xf7;//数码管个位显示位
  53. //   P1=table[ge];//数码管个位数值显示
  54. //   delay(2);//延时
  55. // }
  56. //  void keyscan()
  57. //{
  58. //   if(add==0)
  59. // {         
  60. //    delay(5);
  61. //    if(add==0)
  62. //  {
  63. //     num++;
  64. //     while(!add);
  65. //     lingweiflag=0;
  66. //    }
  67. //   }
  68. //   if(dec==0&&lingweiflag==0)
  69. // {         
  70. //    delay(5);
  71. //    if(dec==0)
  72. //  {
  73. //     num--;
  74. //     while(!dec);
  75. //    }
  76. //   }
  77. //   if(num>9999)
  78. // {
  79. //      num=0;
  80. //   }
  81. //   if(num==0)
  82. // {
  83. //       num=0;
  84. //       lingweiflag=1;
  85. //   }
  86. // }
  87. //  void main()
  88. //{
  89. //   while(1)
  90. // {
  91. //    display();
  92. //    keyscan();
  93. //   }
  94. //  }



  95. //程序二:解决按键控制数码管带来闪灭显示问题的程序
  96. #include<reg51.h>
  97. #define uchar unsigned char
  98. #define uint unsigned int
  99. sbit add=P3^0;
  100. sbit dec=P3^4;
  101. uchar lingweiflag;
  102. uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。
  103. uint num;
  104. uint qian,bai,shi,ge;//定义拆字变量
  105.   /**ms级延时子程序**/
  106.   void delay(uint x)
  107. {
  108.    uint i,j;                       
  109.    for(i=0;i<x;i++)     
  110.     for(j=0;j<110;j++);
  111.   }
  112.   void display()
  113. {
  114.    qian=num/1000;//取得千位数字
  115.    bai=num%1000/100;//取得百位数字
  116.    shi=num%100/10;//取得十位数字
  117.    ge=num%10;//取得个位数字

  118.    P2=0xfe;//数码管千位显示位
  119.    P1=table[qian];//数码管千位数值显示
  120.    delay(2);//延时

  121.    P2=0xfd;//数码管百位显示位
  122.    P1=table[bai];//数码管百位数值显示
  123.    delay(2);//延时

  124.    P2=0xfb;//数码管十位显示位
  125.    P1=table[shi];//数码管十位数值显示
  126.    delay(2);//延时

  127.    P2=0xf7;//数码管个位显示位
  128.    P1=table[ge];//数码管个位数值显示
  129.    delay(2);//延时
  130. }
  131.   void keyscan()
  132. {
  133.    if(add==0)
  134. {         
  135.     delay(5);
  136.     if(add==0)
  137.   {
  138.      num++;
  139.      while(!add);
  140.      lingweiflag=0;
  141.     }
  142.    }
  143.    if(dec==0&&lingweiflag==0)
  144. {         
  145.     delay(5);
  146.     if(dec==0)
  147.   {
  148.      num--;
  149.      while(!dec);
  150.     }
  151.    }
  152.    if(num>9999)
  153. {
  154.     num=0;
  155.    }
  156.    if(num==0)
  157. {
  158.     num=0;
  159.     lingweiflag=1;
  160.    }
  161. }
  162.   void Time0_init()
  163. {
  164.    TMOD=0x01;
  165.    TH0=(65536-10000)/256;//为什么取定时器中断时间为10000微妙,即10毫秒,亦0.01秒,则频率为1/0.01S=100Hz?由于人眼能看到数码管闪烁是源于人眼能识别高频率(人眼看不到闪烁的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪烁,数管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高越好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
  166.    TL0=(65536-10000)%256;
  167.    EA=1;
  168.    ET0=1;
  169.    TR0=1;
  170.   }
  171.   void time0() interrupt 1
  172. {
  173.    TH0=(65536-10000)/256;
  174.    TL0=(65536-10000)%256;
  175.    display();
  176.   }
  177.   void main()
  178. {
  179.    Time0_init();
  180.    while(1)
  181. {
  182.     keyscan();
  183.    }
  184.   }
复制代码
1680900-20200520213008932-420492329.png

评分

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

查看全部评分

回复

使用道具 举报

ID:584814 发表于 2020-5-21 20:07 | 显示全部楼层
大段注释程序行行用//可以显示耐力优化略显呵呵
回复

使用道具 举报

ID:171036 发表于 2020-5-21 21:54 | 显示全部楼层
man1234567 发表于 2020-5-21 20:07
大段注释程序行行用//可以显示耐力优化略显呵呵

基础扎不扎实  看基本功
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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