嵌入式Linux--定时器

500 阅读1分钟

前言

本文将使用定时器进行按键消抖。按键驱动程序在《嵌入式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秒,初始化定时器一次。