按键去抖动的方法主要有两种,一种是硬件电路去抖动;另外一种就是软件延时去抖。而延时又一般分为两种,一种是for循环等待,另一种是定时器延时。在操作系统中,由于效率方面的原因,一般不允许使用for循环来等待,只能使用定时器。
Linux内核使用struct timer_list来描述一个定时器:
{
struct list_head entry;
unsigned long expires; //定时器定时时间
void (*function)(unsigned long);//定时器发生后调用函数
unsigned long data;
struct tvec_base *base;
};
Linux内核定时器使用流程:
1.定义定时器变量
2.初始化定时器
2.1init_timer初始化
2.2设置超时函数
3.add_timer注册定时器
4.mod_timer启动定时器
struct work_struct *work;
struct timer_list xxx_timer;
/* 当进入中断函数,首先执行关于中断硬件的部分,然后调用工作队列工作work_func */
/* work_func函数调用mod_timer开启定时器,开始计时,计时结束后调用xxx_timer_function函数*/
/* 进入xxx_timer_function函数识别中断源,执行中断函数功能*/
void work_func(struct work_struct *work)
{
mod_timer(&xxx_timer, jiffies + (HZ /10));
//jiffies是一个全局变量,表示现在的时间(使用滴答表示,一秒一千个滴答),
//一个HZ是一秒,HZ /10表示一百个毫秒
}
void xxx_timer_function(unsigned long data)
{
}
irqreturn_t xxx_int(int irq, void *dev_id)
{
//执行关于硬件部分程序
//提交下半部
schedule_work(work);
//return 0;
return IRQ_HANDLED;
}
int xxx_open(struct inode *node,struct file *filp)
{
return 0;
}
struct file_operations xxx_fops =
{
.open = xxx_open,
};
struct miscdevice xxx_miscdev = {
.minor = 200,
.name = " ",
.fops = &xxx_fops,
};
static int xxx_init()
{
//注册混杂设备
misc_register(&xxx_miscdev);
//注册中断处理程序
request_irq(IRQ_EINT0,xxx_int,IRQF_TRIGGER_FALLING," ",0);
//创建工作(队列工作)
work = kmalloc(sizeof(struct work_struct),GFP_KERNEL);
INIT_WORK(work, work_func);
/* 初始化定时器 */
init_timer(&xxx_timer);
/* 指定定时器中断发生后调用函数 */
xxx_timer.function = xxx_timer_function;
/* 向内核注册一个定时器 */
add_timer(&xxx_timer);
return 0;
}
static void button_exit()
{
/* 注销混杂设备 */
misc_deregister(&xxx_miscdev);
}
module_init(xxx_init);
module_exit(xxx_exit);