这种方式,有一个问题,就是对于实时性要求比较高的场合,显然这就是一个问题了。中断处理函数中,做了过多的事情,这显然是一个不合理的设计方案。

设置状态标志消抖

在上面的设想中,如果用到了rtos,那么我们可以在中断中读引脚电平,并且设置一个状态标志位,将线程资源释放给其他资源,等10ms后再次切换到这个线程,去读取按键的状态,如果状态一致,则认为按键按下,这显然是比第一种直接在中断中去读状态好了许多。

但是,也会存在随机的可能性,比如我们在移动设备的过程中,并不是人为操作的按键,但是恰好两次10ms都读到了触发中断的电平,这是极有可能的,虽然可能性比较小,但是对于产品而已,我们不能抱有侥幸心理,要解决这个问题。

多点采样方案消抖

于是,我们提出了多次取点采样的方案进行设计。

我们知道,机械按键触发了中断,无论是否人为操作,我们都需要去读取电平状态,我们用一个字节表示电平的状态,每一位代表一个采样点,则我们可以抽象出如下的模型:

如果我们每10ms采样一次,将这个采样的信号用一个字节的数据表示。

那么我们每次采样都往这个字节的最低位补充,直到这个数据变成全0或者全1为止。

下面是一个误触造成的抖动过程的抽象模型

机械按键如何去处理按键抖动的问题

当进行采样的时候,黑色表示读到的是触发时的电平,白色表示未触发是的电平,当我们读到连续的都是白色的时候,则我们认为这次的采样是无效的。同理我们来看一下正常按下时的操作。

机械按键如何去处理按键抖动的问题

也是一个同理的过程,当我们读到0xFF是,则认为电平稳定有效,此时表按下状态。

从程序上表示如下:

//key_ptr 按键GPIO的引脚指针

//step_time采样间隔

//timeout 超时时间

KeyStatus key_val_get(volatile unsigned long *key_ptr, tu32 step_time, tu32 timeout)

{

static tu8 keybuf = 0xff;

KeyStatus keysta = key_Unstable;

rt_tick_t start_time = rt_tick_get,cost_time;

while(1)

{

cost_time = rt_tick_get - start_time;

if(cost_time 《 timeout)

{

rt_thread_delay(step_time);

keybuf = (( keybuf 《《 1 ) | (*key_ptr)) ;//每次读取按键值

if ( 0x00 == keybuf )

{

keysta = key_Low;

  • UC3846控制芯片工作原理控制图 逆变焊机原理与用途
  • 数字万用表电阻档测试二极管正反向没有阻值(使用万用表测量二极管的正向电阻,为什么各档)
  • 学单片机需要学数电模电吗(学单片机要先学数电模电吗)
  • 电工怎么选择适合自己用的万用表(电工初学者买什么样的万用表好)
  • 单片机需要同时运行多个任务怎么办(单片机怎么同时执行多个任务)
  • 电机保护的方案取决于负载的机械特性
  • 绝缘电阻表正负搭接不复零位是怎么回事
  • 短路怎么用万用表查