[PIC®/AVR®/dsPIC®产品] 按键抗抖动高级处理方案

[复制链接]
3160|20
 楼主| gaoyang9992006 发表于 2023-9-7 13:04 | 显示全部楼层 |阅读模式
本帖最后由 gaoyang9992006 于 2023-9-7 13:18 编辑

按键是单片机交互中常用的元件,通常按键默认是通过上拉电阻拉高端口电平,另外一个引脚接地,当按下后拉低端口电压。只要检测这个拉低信号即可实现按键检测。

单个按键检测常用的手段有:扫描法;中断法。
扫描法通常被称为笨办法,让单片机主函数不停的去测试端口电压,当检测到端口为低电平的时候记作按键被按下,根据相关逻辑实现按键调节某个变量的应用。这种方法通常不可取,因为要系统一直来处理按键工作,增加了开销。同样的,这种方法也避免不了因为机械抖动产生的噪声干扰,可能一次按下会产生多次触发。
另外一种方法就是在中断里,检测IO的中断,当按键按下的瞬间会产生一个上升沿,当按键松手的那一刹那会产生一个下降沿。因此通常的做法是检测其中一个跳变产生的中断信号。这种做法通常也会因为机械抖动产生的干扰造成错误的多次判断。很多人这时候会进行消抖处理,通过软件延时判断等一系列的骚操作实现消除抖动的功能,这无疑增加了系统的开销,同时会让程序为此耽搁一段时间,虽然这段时间很短很短。

新方法:我们观察当我们使用按键的时候通常是想得到这样一个结果,我按下抬起一次算一次按键,只操作这么一次。这个情况我们可以发现这一完整过程包含了一个下降沿+一个上升沿,因此我们可以用这一完整的跳变过程作为判断一次有效按键的依据。
这需要使用到双边沿触发模式,也就是下降沿和上升沿都可以产生中断信号。
刚好我们的PIC单片机的IO具备这一功能,配置如下:

代码实现:
当按键按下,第一次中断触发后,我们要对第一次做一个标记,按键被按下过:bool SW_flag = 0;
当按键松开,第二次中断触发后,我们要判断第一次做的标记,如果存在清理它,并记录为一次有效按键操作。
  1. bool SW_flag = 0; //记录是否发生了下降沿中断
  2. bool SW_Button_active_flag =0; //有效按键激活标记


  3. void SW_Button_Interrupt_Handle(void)
  4. {
  5.     if(SW_GetValue()==LOW)
  6.     {
  7.         SW_flag = 1;
  8.     }
  9.     else if( ( SW_GetValue()==HIGH ) && (SW_flag == 1) )
  10.     {
  11.         SW_Button_active_flag =1;
  12.         SW_flag = 0;
  13.     }
  14. }
最后我们将中断处理函数的指针传递给中断调用函数
SW_SetInterruptHandler(SW_Button_Interrupt_Handle);
经过测试,当无法出现一次完整的中断过程(下降沿+上升沿)按键不被激活,这样就避免了按下一次多次触发的尴尬局面。按键也变的更加稳定可靠了。
同样,在此基础上,如果启用一个定时器作为观察者,我们还可以实现按下时间长短触发不同的按键效果的操作,这里大家可以自行完成。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| gaoyang9992006 发表于 2023-9-7 13:17 | 显示全部楼层
完整的测试代码如下所示
  1. #include "mcc_generated_files/system/system.h"

  2. bool SW_flag = 0; //记录是否发生了下降沿中断
  3. bool SW_Button_active_flag =0; //有效按键激活标记


  4. void SW_Button_Interrupt_Handle(void)
  5. {
  6.     if(SW_GetValue()==LOW)
  7.     {
  8.         SW_flag = 1;
  9.     }
  10.     else if( ( SW_GetValue()==HIGH ) && (SW_flag == 1) )
  11.     {
  12.         SW_Button_active_flag =1;
  13.         SW_flag = 0;
  14.     }
  15. }


  16. /*
  17.     Main application
  18. */


  19. int main(void)
  20. {
  21.     SYSTEM_Initialize();

  22.     // If using interrupts in PIC18 High/Low Priority Mode you need to enable the Global High and Low Interrupts
  23.     // If using interrupts in PIC Mid-Range Compatibility Mode you need to enable the Global Interrupts
  24.     // Use the following macros to:

  25.     // Enable the Global Interrupts
  26.     INTERRUPT_GlobalInterruptEnable();

  27.     // Disable the Global Interrupts
  28.     //INTERRUPT_GlobalInterruptDisable();

  29.     SW_SetInterruptHandler(SW_Button_Interrupt_Handle);

  30.     while(1)
  31.     {
  32.         if(SW_Button_active_flag == 1)
  33.         {
  34.             SW_Button_active_flag = 0;
  35.             LED_Toggle();
  36.             UART1_Write('A');UART1_Write('-');
  37.             printf("Hello PIC18F16Q40 ! \n");
  38.         }
  39.     }   
  40. }


PICfan007 发表于 2023-9-8 11:30 | 显示全部楼层
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断
 楼主| gaoyang9992006 发表于 2023-9-8 14:06 | 显示全部楼层
PICfan007 发表于 2023-9-8 11:30
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断 ...

理论上你不懂硬件触发中断的规则和原则。所以你没理解,这个想理解,先打赏下,我私信告诉你。
单片小菜 发表于 2023-9-9 11:05 | 显示全部楼层
PICfan007 发表于 2023-9-8 11:30
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断 ...

是的
ewfrg 发表于 2023-9-12 11:21 | 显示全部楼层
学习大牛
tpgf 发表于 2023-10-10 19:23 | 显示全部楼层
但是抖动的话是不是也会产生这两种边沿呀
nawu 发表于 2023-10-10 19:43 | 显示全部楼层
gaoyang9992006 发表于 2023-9-8 14:06
理论上你不懂硬件触发中断的规则和原则。所以你没理解,这个想理解,先打赏下,我私信告诉你。 ...

楼主您好 请问一下能详细说一下这个原则吗
aoyi 发表于 2023-10-10 20:01 | 显示全部楼层
会有检测不到的现象发生吗
 楼主| gaoyang9992006 发表于 2023-10-11 08:31 | 显示全部楼层
aoyi 发表于 2023-10-10 20:01
会有检测不到的现象发生吗

刚开始我以为下降了必然会上升,但是实际上不是所有的上升和下降会触发,这里面有个IO的硬件保护机制导致,特别短的抖动不会完全触发,但是单边的跳动抖动却在触发。
zljiu 发表于 2023-10-11 10:44 | 显示全部楼层
gaoyang9992006 发表于 2023-10-11 08:31
刚开始我以为下降了必然会上升,但是实际上不是所有的上升和下降会触发,这里面有个IO的硬件保护机制导致 ...

也就是说双边沿触发因为有保护机制会有防抖效果 但是单边沿触发就没有这个效果了是吗
gwsan 发表于 2023-10-11 11:05 | 显示全部楼层
这样处理效果不错 能可靠检测的按键频率有测试过吗
tfqi 发表于 2023-10-11 11:26 | 显示全部楼层
这种处理方式就是不会产生误判了 非常不错
 楼主| gaoyang9992006 发表于 2023-10-11 16:20 | 显示全部楼层
zljiu 发表于 2023-10-11 10:44
也就是说双边沿触发因为有保护机制会有防抖效果 但是单边沿触发就没有这个效果了是吗 ...

因为最终的开始和结束是成对出现的,中间那些反复就无所谓了,直到最后一个定下来。
21mengnan 发表于 2023-10-12 20:22 | 显示全部楼层
支持任意边沿中断的,很牛啊。
Bowclad 发表于 2023-11-23 16:17 来自手机 | 显示全部楼层
抖动会不会影响啊
guijial511 发表于 2023-11-24 08:13 来自手机 | 显示全部楼层
硬件滤波或者滤波,加入分辨率设置。
 楼主| gaoyang9992006 发表于 2023-11-24 09:04 | 显示全部楼层
guijial511 发表于 2023-11-24 08:13
硬件滤波或者滤波,加入分辨率设置。

硬件滤波很容易做,增加一个0.1uF电容,然后按键抖动彻底消失。
Bowclad 发表于 2023-11-27 14:21 来自手机 | 显示全部楼层
并个电容
meeagle 发表于 2023-11-28 08:50 | 显示全部楼层
然而,并电容开关是不是容易坏?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:如果你觉得我的分享或者答复还可以,请给我点赞,谢谢。

2052

主题

16404

帖子

222

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