找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机按键扫描消抖经典算法实现以及Proteus实例仿真对比

[复制链接]
跳转到指定楼层
楼主
按键扫描消抖经典算法实现以及Proteus实例仿真对比

  • 算法实现函数:
  1. unsigned char Trg;
  2. unsigned char Cont;
  3. void KeyRead( void )
  4. {
  5.     unsigned char ReadData = P1^0xff;   // 注解1
  6.     Trg = ReadData & (ReadData ^ Cont);   // 注解2
  7.     Cont = ReadData;                      // 注解3
  8. }
复制代码
  • Trg(triger) 代表的是触发,Cont(continue)代表的是连续按下。

  • 注解1:读P1的端口数据,取反,然后送到ReadData 临时变量里面保存起来。

  • 注解2:用来计算触发变量的。一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。

  • 注解3:用来计算连续变量。
  • 上述实现算法不仅适用于端口以总线方式来读取判断,也同样适用于独立IO口信号的判断和处理,具体实现函数如下:
    1. unsigned char Trg;
    2. unsigned char Cont;
    3. void KeyRead( void )
    4. {
    5.     unsigned char ReadData = P10^0x01;   //
    6.     Trg = ReadData & (ReadData ^ Cont);   //
    7.     Cont = ReadData;                     /
    8.     }
    复制代码

  • 1. 没有按键的时候
  • 没有按下时,IO口为高电平,就是P10为0x01,ReadData读端口并且和0x01进行取反,很显然,P10^0x01的值就是 0x00。
  • Trg = ReadData & (ReadData ^ Cont); (初始状态下,Cont也是为0的)很简单的数学计算,因为ReadData为0,则它和任何数“相与”,结果也是为0。
  • Cont = ReadData; 保存Cont 其实就是等于ReadData为0。
2. 第一次IO口按键按下的情况:
  • 端口没有触发时,IO口状态为0x01,ReadData读端口并且取反,很显然,就是 0x01 。

  • Trg = ReadData & (ReadData ^ Cont); 因为这是第一次按下,所以Cont是上次的值,应为为0。那么这个式子的值也不难算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01。
  • Cont = ReadData = 0x01;
    1. ReadData = 0x01;
    2. Trg = 0x01;//Trg只会在这个时候对应位的值为1,其它时候都为0
    3. Cont = 0x01;<span style="background-color: rgb(255, 255, 255); color: rgb(79, 79, 79); font-family: &quot;PingFang SC&quot;, &quot;Microsoft YaHei&quot;, SimHei, Arial, SimSun; font-weight: normal;"></span>
    复制代码

3. IO口按键按着不松(长按键)的情况:
  • 端口数据为0xfe,ReadData读端口并且取反是 0x01 。

  • Trg = ReadData & (ReadData ^ Cont); 因为这是连续按下,所以Cont是上次的值,应为为0x01。那么这个式子就变成了 Trg = 0x01 & (0x01^0x01) = 0x00
Cont = ReadData = 0x01
  1.         ReadData = 0x01;
  2.         Trg = 0x00;
  3.         Cont = 0x01;
复制代码
因为现在按键是长按着,所以MCU会每个一定时间(20ms左右)不断的执行这个函数,那么下次执行的时候情况会是怎么样的呢?

  • ReadData = 0x01;这个不会变,因为按键没有松开.
  • Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按键没有松开,这个Trg值永远为 0.
  • Cont = 0x01;只要按键没有松开,这个值永远是0x0.
4. 按键松开的情况:端口数据为0xff,ReadData读端口并且取反是 0x00 。
  • Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00;
  • Cont = ReadData = 0x00;
    1.         ReadData = 0x00;
    2.         Trg = 0x00;
    3.         Cont = 0x00;
    复制代码
    回到了初始状态,也就是没有按键按下的状态.
Proteus仿真


  • 代码:
    1. #include <REGX52.H>
    2. #include <intrins.h>
    3. sbit KeyValue=P3^7;
    4. unsigned char code segment[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
    5. //定义数码管显示0~9

    6. unsigned char Trg;
    7. unsigned char Cont;
    8.     static char count=1;
    9. void KeyRead( void )
    10. {
    11.     unsigned char ReadData = KeyValue^0x01;   // 注解1
    12.     Trg = ReadData & (ReadData ^ Cont);   // 注解2
    13.     Cont = ReadData;                     // 注解3
    14.         
    15. }

    16. void main() {
    17.                 P3=0XFF;
    18.     P0=segment[0]; //开始运行显示0
    19.     while(1) {
    20.                         KeyRead();
    21.         if(Trg==1) {
    22.             P0=segment[count];
    23.             count++;
    24.             if(count>=10) {  //超过0~9,数码管显示回到0
    25.                 count=0;
    26.             }
    27.         }
    28.     }
    29. }
    30. //void main() {//这是没有经过消抖处理的代码
    31. //                P3=0XFF;
    32. //    P0=segment[0]; //开始运行显示0
    33. //    while(1) {
    34. //               
    35. //        if(KeyValue==0) {
    36. //            P0=segment[count];
    37. //            count++;
    38. //            if(count>=10) {  //超过0~9,数码管显示回到0
    39. //                count=0;
    40. //            }
    41. //        }
    42. //    }
    43. //}
    复制代码
  • 这种算法摒弃了使用延时的常规做法。
  • 仿真文件和程序建附件


全部资料51hei附件下载:
按键扫描消抖算法实现.zip (61.47 KB, 下载次数: 33)

评分

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

查看全部评分

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

使用道具 举报

沙发
ID:34149 发表于 2021-9-11 19:12 | 只看该作者
楼主辛苦了,值得学习!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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