IMX6ULL裸机篇之按键消抖实验

一.  按键消抖

在之前的 按键中断实验时,我们讲了如何使用中断的方式驱动按键或GPIO。如果通过中断的方式处理按键的话,按键是需要消抖处理的。

而在之前 按键中断实验中,在中断处理函数中对按键进行消抖,调用了 delay 延时函数。

但是,实际开发中,中断函数中不允许使用 delay 延时函数!!!  

因为中断服务函数要快进快出!

按键消抖:通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

按键消抖的必要性:

为确保 CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

二.  定时器按键消抖

1.  定时器按键消抖原理

本篇讲一下,按键既要用中断的方式驱动,同时,合理的实现一个按键的消抖处理。我们就使用EPIT定时器来实现按键消抖。这种方法也是 Linux内核中对按键的一个处理方式,Linux内核实现按键消抖也是用的这种方法。

上一章我们学习了 EPIT 定时器,定时器设置好定时时间,然后 CPU 就可以做其他事情去了,定时时间到了以后就会触发中断,然后在中断中做相应的处理即可。
因此,我们可以借助定时器来实现消抖,按键采用中断驱动方式。
当按键按下以后触发按键中断,在 按键中断中开启一个定时器,定时周期为 10ms ,当定时时间到了以后就会触发定时器中断,最 后在定时器中断处理函数中读取按键的值,如果按键值还是按下状态,那就表示这是一次有效的 按键。

下面通过实际举例说明:

这里,假如按键按下为下降沿触发。
此会在 t1 t2 t3 这三个时刻会触发按键中断,每次进入中断处理函数都会重新开器定时器中
断, 所以,会在 t1 、t2 t3 这三个时刻开器定时器中断。
但是 t1~t2 t2~t3 这两个时间段是小于我们设置的定时器中断周期也就是消抖时间,比如 10ms) ,所以虽然 t1 开启了定时器,但是定 时器定时时间还没到, t2 时刻就重置了定时器,最终只有 t3 时刻开启的定时器能完整的完成 整个定时周期并触发中断。
我们就可以在中断处理函数里面做按键处理了,这就是定时器实现 按键防抖的原理。
Linux 里面的按键驱动用的就是这个原理!

2.   代码实现

(1)  大体工作思路

①  配置按键IO中断,即将按键IO设置为中断模式

② 初始化 EPIT1定时器

③  实现中断服务函数

④  实现定时器中断服务函数

(2)  代码实现

bsp 文件夹下创建名为keyfilter的文件夹,然后在 bsp/keyfilter 中新建 bsp_keyfilter.h bsp_keyfilter.c 这两个文件。

bsp_keyfilter.c 文件代码如下:

#include "bsp_key_filter.h"
#include "bsp_gpio.h"
#include "bsp_int.h"
#include "bsp_beep.h"


/* keyFilter初始化 */
//将按键IO配置为中断模式
void key_filter_init(void)
{
/*按键的IO初始化 */
    gpio_pin_config_t  key_config;
    //复用为GPIO功能
    IOMUXC_SetPinMux(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0);
    //配置电气特性
    IOMUXC_SetPinConfig(IOMUXC_UART1_CTS_B_GPIO1_IO18, 0X1070);

    //GPIO初始化
    key_config.direction = kGPIO_DigitalInput;
    key_config.interruptMode = kGPIO_IntFallingEdge;
    gpio_init(GPIO1, 18, &key_config);

    //使能GIC控制器
    GIC_EnableIRQ(GPIO1_Combined_16_31_IRQn);
    //注册按键中断函数
    system_register_irqhandler(GPIO1_Combined_16_31_IRQn, gpio_16_31_irqhandler, NULL);
    //设置中断使能(不同于上面的GIC控制器使能)
    gpio_interrupt_enable(GPIO1, 18);


/*初始化EPIT1定时器*/
    key_epit1_init(66000000/100);
}

/* 初始化EPIT1定时器*/
//reload_value: 定时器计数加载值
void key_epit1_init(unsigned int reload_value)
{
    EPIT1->CR = 0;
    EPIT1->CR = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 24); //1分频
    EPIT1->LR = reload_value;
    EPIT1->CMPR = 0; //比较值写0(即定时器reload_value每次与0比较)

    //初始化GIC中断
    GIC_EnableIRQ(EPIT1_IRQn);
    //注册EPIT1定时器中断函数
    system_register_irqhandler(EPIT1_IRQn, key_filter_epit1_inter, NULL);
}

/* 中断服务函数 */
void gpio_16_31_irqhandler(unsigned int gicciar, void* param)
{
    //开启定时器
    restart_epit1(66000000/100);  //10ms
    //清除IO中断标志位
    gpio_clearintflags(GPIO1, 18);
}

/* EPIT1定时器中断服务函数*/
void key_filter_epit1_inter(unsigned int gicciar, void* param)
{
    static unsigned char beep_state = OFF;
    
   if((EPIT1->SR) & (1 << 0)) //EPIT1定时器中断是否发生
    {
        //关闭EPIT1定时器
        close_epit1();
        beep_state = !beep_state;
        beep_switch(beep_state);
    }
    //清除EPIT1定时器标志位
    EPIT1->SR = (1 << 0);
}

/*关闭EPIT1定时器*/
void close_epit1(void)
{
    EPIT1->CR &= ~(1 << 0);
}

/* 重启EPIT1定时器 */
void restart_epit1(unsigned int reload_value)
{
    EPIT1->CR &= ~(1 << 0);
    EPIT1->LR = reload_value;
    EPIT1->CR |= (1 << 0);
}

main.c 文件代码如下:

主函数中,添加 按键消抖初始化接口。如下所示:

int main(void)
{
    unsigned char led_state = OFF;

    int_init();           //中断初始化
    imux6ull_clk_init();  //初始化系统时钟
    clk_enable();        //使能外设时钟
    led_init();          //Led初始化
    beep_init();         //蜂鸣器初始化
    key_init();         //key按键初始化
    key_filter_init();

    while(1)
    {
        led_state = !led_state; 
        led_switch(LED0, led_state);
        delay(500);
    }

    return 0;
}

以上就是使用 EPIT1定时器实现了按键的消抖。按键IO设置为中断方式,再结合定时器最终实现按键的消抖。

据左大神讲解,Linux 内核中的按键消抖也是这种实现原理。

按键消抖实验就总结到这里。加油!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值