定时器相关函数
setup_timer(timer, fn, data):设置定时器,主要是初始化timer_list结构体,设置其中的函数、参数。
void add_timer(struct timer_list *timer):向内核添加定时器。
timer->expires表示超时时间。
当超时时间到达,内核就会调用这个函数:timer->function(timer->data)。
int mod_timer(struct timer_list *timer, unsigned long expires): 修改定时器的超时时间,
它等同于:del_timer(timer); timer->expires = expires; add_timer(timer); 但是更加高效。
int del_timer(struct timer_list *timer):删除定时器。
使用定时器处理按键抖动
在实际的按键操作中,可能会有机械抖动:
按下或松开一个按键,它的GPIO电平会反复变化,最后才稳定。一般是几十毫秒才会稳定。
如果不处理抖动的话,用户只操作一次按键,中断程序可能会上报多个数据。
怎么处理?
1. 在按键中断程序中,可以循环判断几十亳秒,发现电平稳定之后再上报
2. 使用定时器
显然第1种方法太耗时,违背“中断要尽快处理”的原则,你的系统会很卡。
怎么使用定时器?看下图:
核心在于:在GPIO中断中并不立刻记录按键值,而是修改定时器超时时间,10ms后再处理。
如果10ms内又发生了GPIO中断,那就认为是抖动,这时再次修改超时时间为10ms。
只有10ms之内再无GPIO中断发生,那么定时器的函数才会被调用。
在定时器函数中记录按键值。
编程思路
probe函数中调用 setup_timer(), add_timer()
中断服务程序中不记录按键值,而是修改超时时间mod_timer()
定时器超时函数中记录按键值,唤醒线程,发送信号