前言
本文将使用定时器进行按键消抖。按键驱动程序在《嵌入式Linux按键驱动框架》中已经说明,本文将在它的基础上进行定时器的学习。
程序框架
结构信息的定义
struct timer_list {
...
unsigned long expires; //#1
void (*function)(unsigned long); //#2
unsigned long data; //#3
...
};
static struct timer_list buttons_timer; //#4
- #1: 定时器的超时时间
- #2:定时器的超时处理函数
- #3:需要传入超时处理函数的参数
定时器初始化。
static int sixth_drv_init(void)
{
...
init_timer(&buttons_timer); //#1
buttons_timer.function = buttons_timer_function; //#2
//buttons_timer.expires = 0; //#3
add_timer(&buttons_timer); //#4
...
}
- #1: 初始化定时器。
- #2和#3:将定时器信息赋给结构体
- #4:往系统里添加定时器,定时器生效,由于处理函数里只有检测到中断后,才执行相应操作,所以该定时器在驱动初始化时生效一次但是不执行任何操作。
超时处理函数
static void buttons_timer_function(unsigned long data)
{
struct pin_desc * pindesc = irq_pd; //#1
unsigned int pinval;
if (!pindesc) //#2
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);
}
- 该函数将原本在按键中断中所处理的内容挪到超时处理函数中,这样就完成了按键后延时10ms的操作。
- #1和#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); //#1
return IRQ_RETVAL(IRQ_HANDLED);
}
- #1:修改定时器超时时间为10ms。HZ代表1秒,初始化定时器一次。