字符设备驱动之定时器

一,定时器:引入这个概念将“抖动”去掉

定时器有两个概念:
1,超时时间:
2,时间到了之后的“处理函数”。
可以在中断处理中,如定时 10ms 后处理确定按键值上报。
产生中断
在中断中加定时器,当遇到 A 中断时加一个 10ms 的定时器,过了 10ms 后就去执行“处理
函数”(确定按键值上
报)。因为机械的抖动会非常快,没等到 10ms 后的处理,这时因为抖动又来了一个中断 B,
这时中断 B 把之前的那个定时器修改了。所以 A 中断的定时器就取消了。最后又来了一个
中断 C,同样会修改掉 B 中断的定时器。上图中是假设抖动时产生了 3 个中断,所以对于同
一个“定时器”,最终中断 C 的定时器没有被修改,所以 10ms 后由中断 C 的处理函数上报
了按键值。最后这个 10ms 是从抖动 C 处开始。
这样 3 个抖动的中断只会导致最后处理一个“上报按键值”(定时器过后的处理函数只会执
行一次)。以上便是用定
时器消除抖动的原理。
因为是修改同一个定时器,所以前面的定时又取消,相当于把“闹钟”时间往后调整时,最
终只要响一次闹铃。

1,在内核中查找 add_timer(&timer)的用法:
在这里插入图片描述

定义一个 timer_list 结构体变量“timer”。
在这里插入图片描述
2,在自已的驱动程序中可以仿照着上面“定义–>初始化–>使用”
定时器的定义和触发时间:jiffies 相关概念。
在入口函数中使用:static int sixth_drv_init(void):
初始化定时器:buttons_timer_function()。
设备定时器处理函数:buttons_timer.function = buttons_timer_function;
将定时器加到内核:add_timer(&buttons_timer);
当按下按键后—>到中断处理函数“buttons_irq()”中去。
中断处理函数以前是确实热键值,唤醒应用程序或者发信号等等操作。现在并没先做这些事
情,而是为了防止按键抖动。加了定时器,让唤醒 APP 或发信号让定时器到达时间时的“定
时器处理函数”中完成。而这里“中断处理函数”中先是修改定时器的超时时间为 10ms:
Mod_timer(&buttons_timer, jiffies+HZ/100);
这里产生中断到到这个中断处理函数时,会来一个抖动就把时间基于当前时间值推后 10ms。
(看上图),这样就把多个中断合并成了一个定时器处理。
接着“中断处理函数 buttons_irq()”就不再操作,返回:return IRQ_RETVAL(IRQ_HANDLED);

在这里插入图片描述
上面最后的处理函数我们自已定义的是“buttons_timer_function”,可以查看 timer_list 结构
中 function 的定义原型:

在这里插入图片描述

根据定时器处理函数原型写一个定时器处理函数:
在这里插入图片描述
定时器有两要素:超时时间 和 定时器处理函数。上面时间还没有写,处理函数框架写出来
了。

用“add_timer()”去使用这个时间,它是把“定时器”告诉内核,当定时器中的超时时间到
了后,定时器处理函数“buttons_timer_function()”就会被调用。
在中断处理程序中启动修改定时器的超时时间,下面是以前的中断程序:

在这里插入图片描述

这个中断程序中只需要修改超时时间。Mod_timer();超时是指“闹钟”什么时间闹铃。基于
“jiffles”这个值,这是一个全局变量,系统每隔 10ms,这个值就会产生一个系统时钟中断。

在这里插入图片描述
超时时间可以设置成“当前值”加上某个值。如 1 秒就是 HZ,从定义中可以看到 HZ 是 100.
这里的意思是 1 秒钟里这个当前的 jiffies 值会增加 100.
add_timer(&buttons_timer,jiffies+HZ);是指当前 jiffies 时间过了 100 个系统时钟中断(系统滴
答)后,这个定时器的超时时间“buttons_timer”就到达了。HZ 是 1 秒,那么定时器在 10ms
时启动的话,就是 HZ/100 即 10ms。
假设现在,jiffies 的值为“50”,HZ 为“100”,那么这个定时器 buttons_timer 的超时时间为:
Buttons_times.expires = 50+100/100(jieeies+HZ/100) = 51.
系统是每隔 10ms 产生一个系统时钟中断,系统时钟中断中这个 jiffies 的值会累加。这里假
设 jiffies 为 50,则下一个系统时钟时,jiffies 就变成 51 了,51 一到,在这个系统时钟中断处
理函数里面会从这个定时器链表里面把这里的定时器找出来,看看哪个定时器的时间已经到
了(buttons_timer 这个定时器就在这个链表中)。
若这里的 jiffies 已经大于等于这个“buttons_timer”的定时器超时时间“expires”时
(jiffies>=buttons_timer.expirs),就去调用与这个定时器相关的定时器处理函数。这里要是
buttons_timer.expirs 已经超时,就会调用上面自已定义的“buttons_timer_function()”这个
定时器处理函数。
当定时器超时时,定时器处理函数的工作:

首先“dev_id”要记录下来:
要定义一个结构体,static struct pid_desc *irq_pd;发生中断时的引脚描述。
在这里插入图片描述

在这里插入图片描述
接着这个“irq_pd”就可以在“定时器”处理函数“buttons_timer_function()”中使用了:

在这里插入图片描述这里要判断下,因为在入口函数中没有设置超时时间,这样超时时间就为 0,一旦 add_timer()
把这个定时器放到内核中去,那么在这个系统时钟中断里面,就会 jiffies >= 0 .这样就立即
调用了定时器处理函数
buttons_timer_function()。但这个时间并没有按键中断产生。所以上面的“pindesc”要判断
下。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值