打印
[PIC®/AVR®/dsPIC®产品]

按键抗抖动高级处理方案

[复制链接]
1421|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 gaoyang9992006 于 2023-9-7 13:18 编辑

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

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

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

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


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


使用特权

评论回复
沙发
gaoyang9992006|  楼主 | 2023-9-7 13:17 | 只看该作者
完整的测试代码如下所示
#include "mcc_generated_files/system/system.h"

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


void SW_Button_Interrupt_Handle(void)
{
    if(SW_GetValue()==LOW)
    {
        SW_flag = 1;
    }
    else if( ( SW_GetValue()==HIGH ) && (SW_flag == 1) )
    {
        SW_Button_active_flag =1;
        SW_flag = 0;
    }
}


/*
    Main application
*/


int main(void)
{
    SYSTEM_Initialize();

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

    // Enable the Global Interrupts
    INTERRUPT_GlobalInterruptEnable();

    // Disable the Global Interrupts
    //INTERRUPT_GlobalInterruptDisable();

    SW_SetInterruptHandler(SW_Button_Interrupt_Handle);

    while(1)
    {
        if(SW_Button_active_flag == 1)
        {
            SW_Button_active_flag = 0;
            LED_Toggle();
            UART1_Write('A');UART1_Write('-');
            printf("Hello PIC18F16Q40 ! \n");
        }
    }   
}


使用特权

评论回复
板凳
PICfan007| | 2023-9-8 11:30 | 只看该作者
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断

使用特权

评论回复
地板
gaoyang9992006|  楼主 | 2023-9-8 14:06 | 只看该作者
PICfan007 发表于 2023-9-8 11:30
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断 ...

理论上你不懂硬件触发中断的规则和原则。所以你没理解,这个想理解,先打赏下,我私信告诉你。

使用特权

评论回复
5
单片小菜| | 2023-9-9 11:05 | 只看该作者
PICfan007 发表于 2023-9-8 11:30
您好,仔细的学习后还是不太理解,理论上抖动期间iO上会有很多上升下降沿,会不停的产生中断 ...

是的

使用特权

评论回复
6
ewfrg| | 2023-9-12 11:21 | 只看该作者
学习大牛

使用特权

评论回复
7
tpgf| | 2023-10-10 19:23 | 只看该作者
但是抖动的话是不是也会产生这两种边沿呀

使用特权

评论回复
8
nawu| | 2023-10-10 19:43 | 只看该作者
gaoyang9992006 发表于 2023-9-8 14:06
理论上你不懂硬件触发中断的规则和原则。所以你没理解,这个想理解,先打赏下,我私信告诉你。 ...

楼主您好 请问一下能详细说一下这个原则吗

使用特权

评论回复
9
aoyi| | 2023-10-10 20:01 | 只看该作者
会有检测不到的现象发生吗

使用特权

评论回复
10
gaoyang9992006|  楼主 | 2023-10-11 08:31 | 只看该作者
aoyi 发表于 2023-10-10 20:01
会有检测不到的现象发生吗

刚开始我以为下降了必然会上升,但是实际上不是所有的上升和下降会触发,这里面有个IO的硬件保护机制导致,特别短的抖动不会完全触发,但是单边的跳动抖动却在触发。

使用特权

评论回复
11
zljiu| | 2023-10-11 10:44 | 只看该作者
gaoyang9992006 发表于 2023-10-11 08:31
刚开始我以为下降了必然会上升,但是实际上不是所有的上升和下降会触发,这里面有个IO的硬件保护机制导致 ...

也就是说双边沿触发因为有保护机制会有防抖效果 但是单边沿触发就没有这个效果了是吗

使用特权

评论回复
12
gwsan| | 2023-10-11 11:05 | 只看该作者
这样处理效果不错 能可靠检测的按键频率有测试过吗

使用特权

评论回复
13
tfqi| | 2023-10-11 11:26 | 只看该作者
这种处理方式就是不会产生误判了 非常不错

使用特权

评论回复
14
gaoyang9992006|  楼主 | 2023-10-11 16:20 | 只看该作者
zljiu 发表于 2023-10-11 10:44
也就是说双边沿触发因为有保护机制会有防抖效果 但是单边沿触发就没有这个效果了是吗 ...

因为最终的开始和结束是成对出现的,中间那些反复就无所谓了,直到最后一个定下来。

使用特权

评论回复
15
21mengnan| | 2023-10-12 20:22 | 只看该作者
支持任意边沿中断的,很牛啊。

使用特权

评论回复
16
Bowclad| | 2023-11-23 16:17 | 只看该作者
抖动会不会影响啊

使用特权

评论回复
17
guijial511| | 2023-11-24 08:13 | 只看该作者
硬件滤波或者滤波,加入分辨率设置。

使用特权

评论回复
18
gaoyang9992006|  楼主 | 2023-11-24 09:04 | 只看该作者
guijial511 发表于 2023-11-24 08:13
硬件滤波或者滤波,加入分辨率设置。

硬件滤波很容易做,增加一个0.1uF电容,然后按键抖动彻底消失。

使用特权

评论回复
19
Bowclad| | 2023-11-27 14:21 | 只看该作者
并个电容

使用特权

评论回复
20
meeagle| | 2023-11-28 08:50 | 只看该作者
然而,并电容开关是不是容易坏?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:西安公路研究院南京院
简介:主要工作从事监控网络与通信网络设计,以及从事基于嵌入式的通信与控制设备研发。擅长单片机嵌入式系统物联网设备开发,音频功放电路开发。

1896

主题

15631

帖子

198

粉丝