[创客交流] 解决按键控制数码管带来闪灭显示问题的项目工程优化版2

[复制链接]
 楼主| zhamatu 发表于 2020-10-25 17:28 | 显示全部楼层 |阅读模式
  1. /*****
  2. 承接上一个解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)来
  3. 做解决按键控制数码管带来闪灭显示问题的项目工程(优化版二)。为何呢?
  4. 由于上一个解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)
  5. 程序内按键扫描函数和数码管显示函数存在大量的不精准延时,导致CPU消耗
  6. 过大,拖慢CPU处理指令的速度。如何来解决呢?请看下面讲解。
  7. 为什么按下按键到按键抬起后,会干扰到数码管的显示?原因:如果按键扫描
  8. 函数和数码管显示函数都放在主函数的固定循环内,当按键按下后,按键扫描
  9. 函数进行按键扫描,在扫描到按键延时后,CPU被限制在按键延时处进行计时,
  10. 却无法运行其他程序,从而导致数码管显示函数无法运行,就会出现数码管闪
  11. 灭显示问题。人能看到数码管闪烁是因为人眼能识别高频率(人眼看不到闪烁
  12. 的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪
  13. 烁,数码管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高
  14. 好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
  15. 除了以上问题,解决按键控制数码管带来闪灭显示问题的项目工程(优化版一)
  16. 还存在程序内按键扫描函数和数码管显示函数存在大量的不精准延时,导致CPU
  17. 消耗过大,拖慢CPU处理指令的速度。
  18. 本程序分两个程序。一个是程序一,按键控制数码管带来闪灭显示问题的程序。
  19. 另一个是程序二,解决按键控制数码管带来闪灭显示问题的项目工程(优化版
  20. 二)。通过去掉按键控制数码管带来闪灭显示问题的项目工程(优化版一)程
  21. 序内按键扫描函数和数码管显示函数存在大量的不精准延时。定时器解决按键
  22. 消抖原理:编写一个类似普通延时函数的定时器延时函数,用来替换掉普通延
  23. 时即可。提醒:先试程序一,再试程序二,之后两者对比,找出不同点,取最
  24. 适合的。
  25. *****/


 楼主| zhamatu 发表于 2020-10-25 17:30 | 显示全部楼层
  1. //程序一:按键控制数码管带来闪灭显示问题的程序
  2. //#include<reg51.h>
  3. //#define uchar unsigned char
  4. //#define uint unsigned int
  5. //sbit add=P3^0;
  6. //sbit dec=P3^4;
  7. //uchar lingweiflag;
  8. //uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。
  9. //uint num;
  10. //uint qian,bai,shi,ge;//定义拆字变量
  11. //  /**ms级延时子程序**/
  12. //  void delay(uint x)
  13. //{
  14. //   uint i,j;                       
  15. //   for(i=0;i<x;i++)     
  16. //    for(j=0;j<110;j++);
  17. //  }
  18. //  void display()
  19. //{
  20. //   qian=num/1000;//取得千位数字
  21. //   bai=num%1000/100;//取得百位数字
  22. //   shi=num%100/10;//取得十位数字
  23. //   ge=num%10;//取得个位数字
  24. //
  25. //   P2=0xfe;//数码管千位显示位
  26. //   P1=table[qian];//数码管千位数值显示
  27. //   delay(2);//延时
  28. //
  29. //   P2=0xfd;//数码管百位显示位
  30. //   P1=table[bai];//数码管百位数值显示
  31. //   delay(2);//延时
  32. //
  33. //   P2=0xfb;//数码管十位显示位
  34. //   P1=table[shi];//数码管十位数值显示
  35. //   delay(2);//延时
  36. //
  37. //   P2=0xf7;//数码管个位显示位
  38. //   P1=table[ge];//数码管个位数值显示
  39. //   delay(2);//延时
  40. // }
  41. //  void keyscan()
  42. //{
  43. //   if(add==0)
  44. // {         
  45. //    delay(5);
  46. //    if(add==0)
  47. //  {
  48. //     num++;
  49. //     while(!add);
  50. //     lingweiflag=0;
  51. //    }
  52. //   }
  53. //   if(dec==0&&lingweiflag==0)
  54. // {         
  55. //    delay(5);
  56. //    if(dec==0)
  57. //  {
  58. //     num--;
  59. //     while(!dec);
  60. //    }
  61. //   }
  62. //   if(num>9999)
  63. // {
  64. //      num=0;
  65. //   }
  66. //   if(num==0)
  67. // {
  68. //       num=0;
  69. //       lingweiflag=1;
  70. //   }
  71. // }
  72. //  void main()
  73. //{
  74. //   while(1)
  75. // {
  76. //    display();
  77. //    keyscan();
  78. //   }
  79. //  }
 楼主| zhamatu 发表于 2020-10-25 17:31 | 显示全部楼层
  1. //程序二:解决按键控制数码管带来闪灭显示问题的程序
  2. #include<reg51.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit add=P3^0;
  6. sbit dec=P3^4;
  7. sbit led=P3^5;
  8. sbit led2=P3^6;
  9. uchar count;//定时器中断次数变量
  10. uchar time;//按键定时器延时变量
  11. uchar lingweiflag;//显示0标志位变量
  12. uchar code weima[]={0xfe,0xfd,0xfb,0xf7};//数码管位码表
  13. uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f} ; //共阴数码管段码数字0~9字码表,高电平点亮数码管段码数字0~9。
  14. uint num;//数值变量
  15. uint qian,bai,shi,ge;//定义拆字变量
  16. //  /**ms级延时子程序**/
  17. //  void delay(uint x)
  18. //{
  19. //   uint i,j;                       
  20. //   for(i=0;i<x;i++)     
  21. //    for(j=0;j<110;j++);
  22. //  }
  23. /**定时器ms级延时子程序**/
  24.   void time0_delay(uchar time)//注意这里不是普通延时,而是定时器延时函数。
  25. {
  26.    count = 0;//需要定时器延时count,先清零,再循环检测是否计到count,是则退出。
  27.    while(1)
  28. {
  29.     if(count>=time)
  30.   {         
  31.      break;
  32.    }
  33.   }  
  34. }
  35. //  void display()
  36. //{
  37. //   qian=num/1000;//取得千位数字
  38. //   bai=num%1000/100;//取得百位数字
  39. //   shi=num%100/10;//取得十位数字
  40. //   ge=num%10;//取得个位数字
  41. //
  42. //   P2=0xfe;//数码管千位显示位
  43. //   P1=table[qian];//数码管千位数值显示
  44. //   delay(2);//延时
  45. //
  46. //   P2=0xfd;//数码管百位显示位
  47. //   P1=table[bai];//数码管百位数值显示
  48. //   delay(2);//延时
  49. //
  50. //   P2=0xfb;//数码管十位显示位
  51. //   P1=table[shi];//数码管十位数值显示
  52. //   delay(2);//延时
  53. //
  54. //   P2=0xf7;//数码管个位显示位
  55. //   P1=table[ge];//数码管个位数值显示
  56. //   delay(2);//延时
  57. // }
  58.   void display()//显示程序
  59. {
  60.    static uchar i;
  61.    P1=0x00;
  62.    P2=weima[i];
  63.    switch(i)
  64. {
  65.     case 0:
  66.            P1=table[num/1000];
  67.            break;
  68.     case 1:
  69.            P1=table[num%1000/100];
  70.            break;
  71.     case 2:
  72.            P1=table[num%100/10];
  73.            break;
  74.     case 3:
  75.            P1=table[num%10];
  76.            break;
  77.   }
  78.    i++;
  79.    i%=4;
  80. }
  81.   void keyscan()
  82. {
  83. //   if(add==0)
  84. // {         
  85. //    delay(5);
  86. //    if(add==0)
  87. //  {
  88. //     num++;
  89. //     while(!add);
  90. //     lingweiflag=0;
  91. //    }
  92. //   }
  93.    if(add==0)
  94. {         
  95.     time0_delay(20);//注意这里不是普通延时,而是定时器延时函数。
  96.     if(add==0)
  97.   {         
  98.      time0_delay(20);//注意这里不是普通延时,而是定时器延时函数。
  99.      while(!add);
  100.      num++;
  101.      lingweiflag=0;
  102.     }
  103.    }
  104. //   if(dec==0&&lingweiflag==0)
  105. // {         
  106. //    delay(5);
  107. //    if(dec==0)
  108. //  {
  109. //     num--;
  110. //     while(!dec);
  111. //    }
  112. //   }
  113.    if(dec==0&&lingweiflag==0)
  114. {         
  115.     time0_delay(20);//注意这里不是普通延时,而是定时器延时函数。
  116.     if(dec==0)
  117.   {         
  118.      time0_delay(20);//注意这里不是普通延时,而是定时器延时函数。
  119.      while(!dec);
  120.      num--;   
  121.     }
  122.    }
  123.    if(num>9999)
  124. {
  125.     num=0;
  126.    }
  127.    if(num==0)
  128. {
  129.     num=0;
  130.     lingweiflag=1;
  131.    }
  132. }
  133.   void Time0_init()
  134. {
  135.    TMOD=0x01;
  136.    TH0=(65536-2000)/256;//为什么取定时器中断时间为2000微妙,即2毫秒,亦0.002秒,则频率为1/0.002S=500Hz?由于人眼能看到数码管闪烁是源于人眼能识别高频率(人眼看不到闪烁的频率为50Hz)低于50Hz,即1/50Hz=0.02秒,因此要想让人眼看不到数码管闪烁,数管显示函数的显示频率至少是50Hz,即1/50Hz=0.02秒,也不是越高越好,还要结合按键扫描函数的按键延时来取出最恰当的显示频率。
  137.    TL0=(65536-2000)%256;
  138.    EA=1;
  139.    ET0=1;
  140.    TR0=1;
  141.   }
  142.   void time0() interrupt 1
  143. {
  144.    TH0=(65536-2000)/256;
  145.    TL0=(65536-2000)%256;
  146.    count++;
  147.    display();
  148.   }
  149.   void main()
  150. {
  151.    Time0_init();
  152.    while(1)
  153. {
  154.     keyscan();
  155.    }
  156.   }
 楼主| zhamatu 发表于 2020-10-25 17:32 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

63

主题

504

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部