打印

键法偶得

[复制链接]
1935|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
天雨粟|  楼主 | 2009-5-28 14:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式


    学习单片机常常免不了要练剑法,当然PC机也有剑法,但不管单击、双击、右击、Key_Up,编译器都帮你搞好,单片机却都得自己来。
    据说VB程序是事件驱动机制,但在我看来,单片机程序同样是如此,只是其事件比VB的事件少些罢了,其中重要的事件之一就是按键事件。
    凡事件驱动,须先确定这个事件,并进一步确定事件的性质,这是练单片机剑法须首先解决的问题。讲单片机剑法的资料当然也是不少,但我觉得从理论上讲得十分透彻的尚不多见。
    按键事件,则先得有剑,当然,六脉神剑(触摸感应式按键)例外,剑的质量至关重要。我最初的按键问题是未等键释放,则程序判断为多次按下,加了等释放后,问题解决。但以后仍遇到过类似的问题。曾仔细考校程序,检测、延时去抖、再次检测、等待释放,每个环节都做到了,为何仍被程序判断为多次按下,百思不解,由于按键时手感并不好,考虑问题出在剑的质量上,换了几把后再试,就圆转如意,随心所欲了。
    第三次的按键问题,则即使是加了等按键释放的抖动,仍被程序判断为多次按下。先考虑有干扰,在键两端并一个104瓷片,有改进,但未解决,改为光耦合驱动,犹未解决,再并上1µF电解,仍未解决,一口气并一个47µF,这才基本解决。
    我拆开过军级按键(微动开关),其机制是,按压时磷铜片逐步充满张力,复位弹簧亦同步受力,当磷铜片过了平衡点后,迅速反弹,释放弹性势能,闭合触点,释放时复位弹簧释放弹力,将磷铜片顶回初态。适合单片机用的廉价按键不知是何结构,但按下后一声脆响,释放也干净利落。操作过多次这样的按键,用常规剑法,亦自有目送飞鸿、手挥五弦之妙,无不如意。
    第三次问题中的按键,现想来并不适合作单片机的按键。凭手感,它是靠手的推压直接闭合触点,同时复位弹簧受力,松开后回位,所以其预行程超长,相应地,其闭合与断开的抖动时间也属超长,若此,用常规的剑法,就难免跋前踬后、缚手缚脚了。
    回过头来再梳理按键事件。凡事件,须得有开始、过程、结束三个阶段。其中结束阶段最容易被人忽略,但若无结束阶段,据何判断另一个事件的开始?无End Sub,则此事即是彼事、彼事无异此事。事有不同,方分彼此,若乎彼此彼此,斯云滥矣!
    对应于操作者按按键这个事,则开始是“按下”,过程是“按住”,结束是“释放”(即等待下一次按下状态)。
    单片机的剑法,即跟随操作者按按键的各个阶段,判明操作者的意图,作出相应处理。由于单片机运行速度相比于人的动作属于超快,所以操作者使的即便是辟邪剑法,对单片机而言也是慢动作秀,何况根据分析,按键的闭合与释放,在单片机看来,有一个反复多次的若续若断、将断未断过程。
    追踪一个按键事件,其各阶段的电平情况如下:等待按下状态(逻辑1)、若续若断阶段(随机逻辑值)、稳定闭合阶段(逻辑0)、将断未断阶段(随机逻辑值)、稳定释放阶段(逻辑1)。
    单片机不停地查询按键(或用定时中断不停地动态扫描),当在若续若断阶段检测到按键,但单片机绝不能据此操作,原因是这两条,一,可能是一个干扰;二,倘若据此操作,响应事件,然后交出对CPU的控制权,若后面还是——一般来说就是——按键检测,则此事彼事或将合为一事(按键如处于若续若断阶段,对应的端口状态为随机逻辑值,单片机继续扫描按键,极有可能判定又有按键按下,并进而执行一个事件,但该事件对操作者而言,属再一次按下后才可执行的。操作者举杯邀明月,不料却对影成了三人,不是操作者眼花难明白,实因单片机变化太快),遂至事事难明(古人云:世事难明谁可问,浊酒且尽手中杯。难得糊涂了事)。一石数鸟,或有无辜;一箭双雕,或恐误伤。所以单片机剑法讲究不管单击、连击,长击,都须随心所欲,剑人合一,剑随心动。倘非如此,则在事件响应时,难免他事未卜此事休,明矣!
    按键延时去抖的要义当在于此——控制住CPU,临时屏蔽其对按键的扫描——延多长时间呢?delay(8) or delay(10) || delay(12)?这须得根据按键的datasheet而定,当然按键是否有datasheet,我不知道,或者这个可以有罢——但延时时间非常重要,据前分析,短了就毫无意义(延时后端口必须处于稳定的逻辑状态)。
    延时后继续检测,在延时时间合理的情况下,应能检测到一个稳定的值(逻辑0),如属逻辑1则属干扰,应退出事件。经过这样的两次检测,应可确定一个按键事件的发生,可据此响应按键事件。响应结束,还得依上法等按键释放,一桩事才算有始有终,有条不紊——此落则彼起,引而不发,跃如也!
    根据以上分析,并一个大电容能避免误判的理由如下:电容有很大的惰性,因具有很好的抗干扰作用。按键时电容快速放电,在闭合抖动的若续若断阶段,放得极快,充得很慢(有上拉电阻),程序经过一段小延时(常规剑法如此),两次检测,由于小延时足以将电放光,因能确定有键按下,接下来我的程序是等待释放(阻塞式,空等待),由于放得快充得慢,在将断未断的释放抖动阶段,几乎充不上电,直到完全稳定地释放,这才缓慢充满,成功地避开的释放抖动阶段。之后又是一段小延时(也是常规剑法,这里成为增加可靠性),再次判断为逻辑1,这才执行下面的程序,这样,事件的三要素:开始、经过、结束,都已具备,条理清楚、逻辑连贯,误判事件就基本上不会发生了。
    当然,并大电容是不足法的,也并不能做到百发百中,偶然误判还是难以避免,因为不适合单片机用的按键其闭合与释放过程可能偶然性地存在抖动——稳定——又抖动——再次稳定这样的反复,甚至会多次重复这样的反复,如果这样,则任何软硬措施都通归无效,所以,实际使用中仍应选用适合单片机用的按键为要。
    关于单片机剑法,总结如下:
1)    首次检测到按键后,不宜立即执行,原因1,可能是一个干扰;2,执行后,程序会继续检测端口,如端口仍处于抖动阶段,检测结果为不可知,程序执行结果也为未可知,所以,此时必须控制住CPU,不让其继续检测按键,直到状态稳定后才释放CPU,使其不至于错误检测——定时中断按键检测去抖原理与此类似!
2)    执行后,必须确认按键释放,方法仍是控制住CPU,直至键释放。表明一事结束,再次检测到按键,则属另一事开始,倘非如此,则一次按键可能会执行两桩甚至多桩事,形成一个“事变”。
3)    释放阶段的抖动是否应处理。一般来说不再需要,因退出事件后会继续回到按键检测阶段,而按键检测是有严格处理程序的,可以保证不致误判。意即有键按下,必可检测到;如检测不到,则属于无键或有抖动。换句说,即按键的检测是一箭双雕:检测到了,表明有按键,未检测到,也表明按键处于抖动或释放阶段。合而言之,闭合去抖的处理同时也用于了释放去抖的处理,所以判断释放,勿需再作出去抖的处理。
    以上拉扎地谈了一些对按键处理的看法,或有未当,祈方家指正为幸!
    

相关帖子

沙发
41dean| | 2009-5-29 16:33 | 只看该作者

延时

延时一般要根据按键的特性参数来定吧

使用特权

评论回复
板凳
天雨粟|  楼主 | 2009-5-29 17:00 | 只看该作者

回二楼

想来应该如此,但少有资料提及,故提出来请教大家!

使用特权

评论回复
地板
ljm810010| | 2009-5-29 20:22 | 只看该作者

这个过程不省为妙

3)    释放阶段的抖动是否应处理。一般来说不再需要

不处理,很有可能击键一次误判为两次。

使用特权

评论回复
5
ningling_21| | 2009-5-29 21:23 | 只看该作者

省略掉也许会判断为按下两次或更多次

使用特权

评论回复
6
红心j| | 2009-5-30 12:53 | 只看该作者

按键该注意两点,你才偶得0.5点

使用特权

评论回复
7
electron0101| | 2009-5-30 15:20 | 只看该作者

光判断 按下的时间 就OK了

举例

按下 1秒表示  按下

少于 1秒  或大于1秒 都不算

使用特权

评论回复
8
天雨粟|  楼主 | 2009-5-30 18:46 | 只看该作者

感谢大家不吝赐教!

回4楼,5楼:不知二位实际中是如何处理的,看过一些资料,少有作释放去抖处理的,只是理由未给,在下进行了一些思考,认为闭合去抖的处理同时也用于了释放去抖的处理,自己实际中也是这样做的,未发现问题,且再继续关注!

回6楼红心j大师:另外的1.5点,极想知道,可得有幸而闻欤?

回7楼:您提的方案极具启发意义,但初看似难于操作,担忧时间限定后,易引起漏检,我再琢磨琢磨!

使用特权

评论回复
9
9pin| | 2009-5-30 23:19 | 只看该作者

re

普通按键 响应时间一般取40MS
所以定时2MS 中断 连续检测到变化20次(与旧状态不同为变化) 确定按键 松开同样 只是检测到稳定变化但是不做动作而已,除非非常特别按键,一般都会得到满意结果(不同按键可调节次数与定时器时间)

使用特权

评论回复
10
天雨粟|  楼主 | 2009-5-31 20:49 | 只看该作者

回9楼10楼

回9楼刘前辈:
"干扰"问题,自然以高手的意见为准,个人意见,由于"干扰"机制难明,作一些防干扰的软硬措施,所谓有备

无患吧!
"消抖:是防止一次按键多次执行",我也是这样想的,本坛已有结论,在下未能躬逢其盛,甚憾,然与高手意见

暗合,亦所忻慕焉!感谢您的指点.

回10楼:
关于统计按键状态时间,我一般是这样做的:10ms定时中断扫描按键,闭合一个中断周期,视为一次单击,继

续闭合三十个中断周期,视为长按开始,之后每三十个中断周期(0.3s)执行一次按键事件, 释放时停止.
"启动/停止"式按键不适合这样安排.
个人意见,支持长按,则统计闭合时间;
"启动/停止"式按键,采用常规键法.
感谢您的帮助!

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

16

主题

168

帖子

0

粉丝