内核定时器消除按键抖动

原创 2017年03月02日 21:46:48

按键抖动

按键所用的开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,开关不会马上稳定地接通或断开。因而在闭合及断开的瞬间总是伴随有一连串的抖动。

按键去抖动的方法主要有两种:一是硬件电路去抖动;另外一种是软件延时去抖。而延时又一般分为两种,一种是for循环等待,另外一种是定时器延时。在操作系统中,由于效率方面的原因,一般不允许使用for循环来等待,只能使用定时器


范例代码

#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <mach/gpio.h>
#include<linux/cdev.h>
#include <linux/poll.h>
#include<linux/slab.h>


int key_id;
struct cdev cdev;
dev_t devno;


wait_queue_head_t button_q;
static struct timer_list button_timer;//定义一个定时器
unsigned int key_num=0;


struct class *my_class;


static int id=0;


static irqreturn_t key_func(int irq,void *dev_id)
{
id = (int)dev_id;
//10ms后启动定时器
mod_timer(&button_timer,jiffies+HZ/100);//修改定时器的超时时间 jiffes是个全局变量,每隔10ms就会有个系统时钟中断,在系统时钟中断里面这个值就会累加。1s就是1hz。HZ就是100,这个意思是1s中jiffes这个值会增加100。
return IRQ_RETVAL(IRQ_HANDLED);
}


static void button_timer_function(unsigned long data)
{
key_num=1;
if(id==0)
{
return;
}//因为在把定时器加载到内核里面去的时候,没有设置超时所以会直接进来
wake_up_interruptible(&button_q);
return 0;




}


static int key_open(struct inode *inode,struct file *filp)
{
request_irq(IRQ_EINT(16),key_func,IRQF_TRIGGER_FALLING,"k1",1);
request_irq(IRQ_EINT(17),key_func,IRQF_TRIGGER_FALLING,"k2",2);
request_irq(IRQ_EINT(18),key_func,IRQF_TRIGGER_FALLING,"k3",3);
request_irq(IRQ_EINT(19),key_func,IRQF_TRIGGER_FALLING,"k4",4);
request_irq(IRQ_EINT(24),key_func,IRQF_TRIGGER_FALLING,"k5",5);
request_irq(IRQ_EINT(25),key_func,IRQF_TRIGGER_FALLING,"k6",6);
request_irq(IRQ_EINT(26),key_func,IRQF_TRIGGER_FALLING,"k7",7);
request_irq(IRQ_EINT(27),key_func,IRQF_TRIGGER_FALLING,"k8",8);
return 0;
}


static int key_close(struct inode *inode,struct file *file)
{
free_irq(IRQ_EINT(16),1);
free_irq(IRQ_EINT(17),2);
free_irq(IRQ_EINT(18),3);
free_irq(IRQ_EINT(19),4);
free_irq(IRQ_EINT(24),5);
free_irq(IRQ_EINT(25),6);
free_irq(IRQ_EINT(26),7);
free_irq(IRQ_EINT(27),8);
return 0;
}


ssize_t key_read(struct file *filp,char __user *buf,size_t size,loff_t *pos)
{

wait_event_interruptible(button_q,key_num);
copy_to_user(buf,&id,4);
key_num=0;


return 0;
}


static struct file_operations key_fops=
{
.owner = THIS_MODULE,
.open = key_open,
.release = key_close,
.read = key_read,


};


static int  key_timerlist_init(void)
{
init_timer(&button_timer);//初始化定时器
// button_timer.data = //传递给处理函数的参数
//button_timer.expires = //超时时间
//button_timer.function = //处理函数
button_timer.function=button_timer_function;
add_timer(&button_timer);//把定时器告诉给内核
cdev_init(&cdev,&key_fops);
alloc_chrdev_region(&devno, 0 , 1 , "mykey_timerlist");
cdev_add(&cdev, devno, 1);
my_class = class_create(THIS_MODULE, "key_timerlist_class");
if(IS_ERR(my_class))
{
printk("Err: failed in creating class.\n");
return -1;
}
device_create(my_class, NULL, devno,NULL,"key_timerlist_driver");
init_waitqueue_head(&button_q);
return 0;
}


static void key_timerlist_exit(void)
{
device_destroy(my_class,devno);
class_destroy(my_class);
cdev_del(&cdev);
unregister_chrdev_region(devno,1);
}




module_init(key_timerlist_init);
module_exit(key_timerlist_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("EIGHT_FIVE");



测试程序

#include<stdio.h>
#include<sys/ioctl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


int main(int argv,char **argc)
{
int fd,buf;
fd=open("/dev/key_timerlist_driver",0x666);
if(fd<0)
{
printf("can't open\n");
return -1;
}
while(1)
{


read(fd,&buf,4);
printf("key_val =%d\n",buf);
}


close(fd);
return 0;


}

嵌入式S3C2440按键消抖--定时器操作

主要思路:在驱动初始化函数中初始化定时器,但是不设置定时时间,定时时间在按键中断函数中来设置。这样一来在按键物理抖动的时候,中断叠加,一次等待中断还未结束,按键的抖动又产生中断,这样就会叠加,到最后只...
  • yzilong
  • yzilong
  • 2016年05月06日 23:40
  • 490

ARM学习随笔(11)中断学习深入之按键去抖

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产...
  • bgk083
  • bgk083
  • 2014年07月26日 11:38
  • 978

字符设备驱动程序之定时器防抖动-韦东山

原理:通过
  • Ritcheqq
  • Ritcheqq
  • 2014年10月01日 10:43
  • 1166

STM32之系统时基定时器中如何完成按键防抖动问题

在按键演示防抖动部分的主要思路是:利用系统定时器溢出间隔中断来延时防抖。这样做可以提高代码的执行效率。我们怎么去很好的利用这个系统定时器来延时呢?如果只是简单在系统定时器中断中置位延时标志位,没有任何...
  • Cherish511842885
  • Cherish511842885
  • 2016年10月10日 15:44
  • 1180

按键抖动与处理

为什么会有按键抖动(百度百科)         通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而...
  • iLoveHdr
  • iLoveHdr
  • 2013年11月21日 10:22
  • 3496

基于延时采样的按键消抖方法

基于延时采样的按键消抖方法本作品采用知识共享署名-相同方式共享 3.0 未本地化版本许可协议进行许可。按键抖动常见的按键有轻触按键和触摸按键。前者通过内部金属片受力弹动实现按键的接通和断开,后者通过电...
  • liberatetheus
  • liberatetheus
  • 2017年06月03日 20:54
  • 483

linux驱动程序之定时器防按键抖动

前提:按键按下通过中断方式进行处理。本博文基于上一个博文改写:上一篇博文 目的: 使用定时器防止按键抖动产生中断。 方法: 每次发生按键中断后,推迟10ms进行处理,最终将会只执行一次定时器中断处理...
  • a912293097
  • a912293097
  • 2014年12月24日 18:35
  • 1689

AVR单片机软件按钮消抖与确认

第一次写博客,有不对或不好的地方欢迎指正。                                      按钮在按下与弹起的过程中会出现一定的抖动,这有时会对应用过程产生影响,所以我想了一...
  • shuguang1223
  • shuguang1223
  • 2017年03月14日 11:10
  • 231

linux 定时器去抖 按键驱动(转载)

linux 定时器去抖 按键驱动(转载)  本文转载自边缘之火《linux 定时器去抖 按键驱动(转载)》 嵌入式Linux之我行——按键驱动在2440上的实例开发(带去...
  • wangxueang224
  • wangxueang224
  • 2013年09月04日 10:01
  • 2287

【Arduino官方教程第一辑】示例程序 2-3 按键去抖

由于物理性质和机械特性的原因,矩阵按键经常在按下后的一小段时间产生不定状态。这很可能被程序误认为是短时间内的多次按键操作。本例向你展示如何进行按键去抖。...
  • amagamag
  • amagamag
  • 2016年04月21日 16:45
  • 3665
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:内核定时器消除按键抖动
举报原因:
原因补充:

(最多只允许输入30个字)