按键时,一般都会因为物理原因存在抖动,怎么把它去除掉呢?
这节,我们又定时器的方法把这个抖动去掉。
定时器 两个要素:① 超时时间; ②处理函数。
定时器消抖的原理就是中间出现的几个抖动引起的中断都不处理,定时时间到的中断才处理。
怎么使用定时器呢?
1. 定义一个定时器结构 struct time_list;
2. 初始化
3. 通过 add_timer();注册到内核,当超时时,就会调用处理函数。
定时器结构中的 expire是超时时间,它是基于jiffies的,+1就是10ms. HZ 是表示1S。
看一下定时的驱动怎么改:
1. 首先 在入口函数中 定义定时器结构,添加定时器初始化和注册
小知识:
jiffies:它是一个系统的全局变量,每隔10ms 它就会产生一个系统时钟中断,在系统时钟中断中这个值就会累加。可以查看:# cat /proc/interupts 其中有个s3c2410 Timer Tick 这就是我们的系统时钟中断,不断查看,可以看到这个值不断变大。
这节,我们又定时器的方法把这个抖动去掉。
定时器 两个要素:① 超时时间; ②处理函数。
定时器消抖的原理就是中间出现的几个抖动引起的中断都不处理,定时时间到的中断才处理。
怎么使用定时器呢?
1. 定义一个定时器结构 struct time_list;
2. 初始化
3. 通过 add_timer();注册到内核,当超时时,就会调用处理函数。
定时器结构中的 expire是超时时间,它是基于jiffies的,+1就是10ms. HZ 是表示1S。
看一下定时的驱动怎么改:
1. 首先 在入口函数中 定义定时器结构,添加定时器初始化和注册
static struct timer_list buttons_timer; //定义定时器结构
static int sixth_drv_init(void)
{ /*添加定时器初始化和注册*/
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function;
//buttons_timer.expires = 0;
add_timer(&buttons_timer);
......
}
2. 在按键中断中 更改定时超时时间
static irqreturn_t buttons_irq(int irq, void *dev_id)
{
/* 10ms后启动定时器 */
irq_pd = (struct pin_desc *)dev_id;
mod_timer(&buttons_timer, jiffies+HZ/100);
return IRQ_RETVAL(IRQ_HANDLED);
}
3. 在定时中断中 处理按键值、发信号等
static void buttons_timer_function(unsigned long data)
{
struct pin_desc * pindesc = irq_pd;
unsigned int pinval;
if (!pindesc)
return;
pinval = s3c2410_gpio_getpin(pindesc->pin);
if (pinval)
{
/* 松开 */
key_val = 0x80 | pindesc->key_val;
}
else
{
/* 按下 */
key_val = pindesc->key_val;
}
ev_press = 1; /* 表示中断发生了 */
wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */
kill_fasync (&button_async, SIGIO, POLL_IN);
}
在入口函数中 添加定时器结构,并初始化 ,添加添加定时器处理函数,然后add_timer(); 按下按键后,以前是在中断中处理按键值、发信号等,现在 修改定时器 超时时间为10ms之后,然后就不管了; 当10ms 还没到时,又有中断信号来了,超时再推迟10ms;当超时时间到,在超时处理函数中按键值、发信号等。这样就去抖成功了。
小知识:
jiffies:它是一个系统的全局变量,每隔10ms 它就会产生一个系统时钟中断,在系统时钟中断中这个值就会累加。可以查看:# cat /proc/interupts 其中有个s3c2410 Timer Tick 这就是我们的系统时钟中断,不断查看,可以看到这个值不断变大。