• 5.按键定时器去抖动


    按键定时器去抖动

    按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,开关不会马上稳定地接通或断开。因而在闭合及断开的瞬间总是伴有一连串的抖动的。按键去抖动的方法主要有两种,一种是硬件电路去抖动;另一种就是软件延时去抖动。而延时又一般分为了两种,一种是for循环等待,另一种是定时器延时。在操作系统中,由于效率方面的原因,一般不允许使用for循环来等待,只能使用定时器。

    上面是内核定时器的结构。其中expires是定时器延时的时间,function函数是定时器超时后要做的事情。

    由上面可以知道,定时器的使用分为了四个步骤:1.定义定时器的变量,就是timer_list结构。2.要对结构进行初始化。Init_timer是系统自动运行的初始化函数,能初始化很大部分timer_list里面的成员。但是,超时函数是需要我们自己设置,就是function。3.使用add_timer函数注册定时器。4.mod_timer重启定时器。注意,定时器不是循环的,需要重复调用mod_timer函数。

    接下来是例子:

    Nkey.c:

    #include <linux/module.h>        /* For module specific items */

    #include <linux/fs.h>            /* For file operations */

    #include <linux/ioport.h>        /* For io-port access */

    #include <linux/io.h>            /* For inb/outb/... */

    #include <linux/init.h>

    #include <linux/miscdevice.h>

    #include <linux/interrupt.h>

    #include <linux/slab.h>

    #define GPNCON 0x7f008830

    #define GPNDAT 0x7f008834

    struct work_struct *work1;

    struct timer_list key_timer;//定义定时器

    unsigned int *gpio_data;

    void work1_func(struct work_struct *work)

    {

        //启动定时器 100毫秒超时=HZ/10,HZ=1秒。jiffies是系统当前时间

        mod_timer(&key_timer,jiffies+HZ/10);

    }

    void key_timer_func(unsigned long data)

    {

        unsigned int key_val;

        //超时的时候,就要读取data

        key_val=readw(gpio_data)&0x01;//读出一个按键EINT0的值。

        //当他被按下,就是低电平的时候,就是被按下了。才是有效的按键

        if(0==key_val)//真正按下

            printk("<0> key down! ");

    }

    irqreturn_t key_int(int irq, void *dev_id)

    {

        //1.检测是否发生了按键中断

        //2.清除已经发生的按键中断

    //前面的都是硬件相关的工作,必须在中断里面执行

    //下面是硬件无关的工作,我们把它提到中断以外的work1_func函数去处理。

        //3.打印按键值

        schedule_work(work1);

        

        return 0;

    }

    void key_hw_init()

    {

        unsigned int *gpio_config;

        unsigned short data;

        gpio_config = ioremap(GPNCON,4);

        data = readw(gpio_config);

        data &= ~0b11;

        data |= 0b10;

        writew(data,gpio_config);

        gpio_data = ioremap(GPNDAT,4);

    }

    int key_open(struct inode *node, struct file *filp)

    {

        return 0;

    }

    struct file_operations key_fops =

    {

        .open = key_open,

    };

    struct miscdevice key_miscdevice =

    {

        .minor = 200,

        .name = "OK6410key",

        .fops = &key_fops,

    };

    static int key_init()

    {

        misc_register(&key_miscdevice);

        //硬件初始化

        key_hw_init();

        //注册中断处理程序

        request_irq(IRQ_EINT(0),key_int, IRQF_TRIGGER_FALLING,"OK6410key",0);

        //2. 创建工作

        work1 = kmalloc(sizeof(struct work_struct),GFP_KERNEL);

        INIT_WORK(work1, work1_func);

        //定时器初始化

        init_timer(&key_timer);

        key_timer.function=key_timer_func;

        

        //注册定时器

        add_timer(&key_timer);

        return 0;

    }

    static void key_exit()

    {

        misc_deregister(&key_miscdevice);

        

    }

    module_init(key_init);

    module_exit(key_exit);

    编译成功,拷贝生成的.ko驱动文件到开发板运行。

  • 相关阅读:
    修改url地址参数
    jquery点击click事件和blur事件冲突如何解决
    js 小数点 取整数
    js正则表达式 验证手机号,email地址和邮政编码
    js轮播功能 标签自动切换 同页面多轮播js
    json 数组操作
    Jquery页面中添加键盘按键事件,如ESC事件
    记录一下。。。服务器 共享文件夹 模拟模拟 IIS 验证的帐户或用户
    vs2015 js 无智能提示解决办法
    解决poshytip 表单高度大于屏幕高端 显示问题
  • 原文地址:https://www.cnblogs.com/FORFISH/p/5188562.html
Copyright © 2020-2023  润新知