由于机械开关按键时,金属弹片会出现多次抖动,这样就会产生多次中断,读取多次键值。需要引入定时器,比如10ms后再处理定时器函数,这样每次抖动产生中断会过10ms后再处理,这样多次抖动会响应一次定时器中断处理。
定时器使用:两要素:a.时间 b.函数4
1)定义一个定时器结构体:static struct timer_list button_timer;
2)定时器初始化:驱动入口函数init进行定时器初始化
init_timer(&button_timer);
//button_timer.data = (unsigned long)scpnt;//给function处理函数用的
//button_timer.expires = jiffies + 100*HZ;/*10s*/,HZ定义为100 在中断处理程序用程序
//button_timer.function = (void (*)(unsigned long)) timer_expired;
button_timer.function = buttons_timer_function;
3)编写定时器处理函数
static void buttons_timer_function(unsigned long data)
{
struct pin_desc *pindesc = (struct pin_desc *)dev_id;
unsigned int pinval;
if(!pindesc )//判断是否有按键按下,即是否为空
return;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if(pinval)
{
/*松开*/
keyval = (0x80 | pindesc->key_val);
}
else
{
keyval = pindesc->key_val;
}
ev_press = 1; /*表示中断发发生了*/
wake_up_interruptible(&button_waitq);
kill_fasync(&buton_async,SIGIO,POLL_IN);
//printk("irq = %d\n",irq);
}
4)在入口函数即init使用add_timer(&button_timer),因为此时超时时间系统初始化button_timer.expires =0;此时调用add_timer函数时jiffies >=0,即立即执行定时器处理函数,但是因为现在没有按键按下,所以需要在定时器处理函数判断dev_id是否为空即是否有按键按下。用这个函数把定时器告诉内核,当里面定时器时间到了之后,就调用定时器处理函数void buttons_timer_function(unsigned long data)
5)在中断处理函数中添加下面内容,先定义引脚static struct pin_desc *irq_pd
static irqreturn_t buttons_irq(int irq,void *dev_id)
{
irq_pd = (struct pin_desc *)dev_id;
mod_timer(&button_timer, jiffies + HZ/100);//10ms过后启动定时器
return IRQ_RETVAL(IRQ_HANDLED);
}