本帖最后由 天雨粟 于 2010-9-21 22:04 编辑
学习与思考之二——这个键盘程序还不错
单片机学习,键盘程序,应该是一个重要的课题。一般介绍单片机的书,对键盘程序的介绍,我总觉得不够深入——篇幅不多,介绍也很简略。对键盘程序作专题研究,是完全可以写一本书的——当然,这有待于高手。我倘能供献一点素材,也就满意了。
这是一个用定时中断写的键盘程序,见于周航慈老师的书。这个程序提供了一种支持长按的办法。
击键,在某些方面很类似于开枪。只支持单击,相当于三八大盖;还支持长按,那就相当于是卡宾枪了。
卡宾枪与三八大盖,那火力是有天壤之别的、技术上也是不可同日而语的,原因在于卡宾枪不仅可以连发即扫射,而且可以单发即点射。
问题其实就在于这里:支持连发,但同时又要支持单发,并且射速还要有一定的范围(太快太慢都不妥)——这就对程序作者提出了很大的挑战!
另外,不支持长按的键,你长时间按着,也只响应一次。好比三八大盖,你扣一次扳机,即便不放手,也只能发射一粒子弹。在三八大盖,这个是自然的,但按键在程序中,还要动些脑筋,才能达到这个效果。
闲言少叙,且看周老师是如何解决这个问题的。
;10ms定时中断键扫描的核心程序
KEYCODE DATA 38H ;键码放在38H中
KEYT DATA 39H ;KEYT是键龄,注意周老师提出的这个概念
KEYOK BIT 2DH.5 ;键已执行标志
KEY: LCALL KEYIN ;KEYIN是键扫描子程序,读出的键码放在A中
CPL A ;无键则读出全1,取反的话则变为0,否则是变不了0的
JZ KEY0 ;显然前面的那个取反正是为这个判断指令埋下的伏笔
CPL A ;有按键则恢复键码,这三条指令岂非丝丝入扣呢?
INC KEYT ;有按键,则键龄加1
XCH A,KEYCODE; 这条指令很关键
;表面上只是将A与KEYCODE中的值互换,其实其中藏有玄机.开机时KEYCODE
;是随机值,首次执行时装载当前扫描所得键码,而A中装入随机值;二次及以后执行
;时,KEYCODE中仍装载当时键码,但通过这个互换指令,A中却装入了上一次的键
;码,以后始终如此——即新旧两个键码总是分别在A及KEYCODE中!递推?推挽?
;没有合适的词来形容这种现象,只觉得有味哉,其写之也!
;随机值有时是危险的,固建议开机时置KEYCODE为0FFH,使首次执行时与A值绝
;对不同,以牢牢控制程序流程,防止程序流程异常.
XRL A,KEYCODE
JZ KEY1 ;相同跳,相异则初始化”键龄”及”已执行”标志,退出
;请注意,检测到”按下” “释放”两个不同的状态,则程序宣布一次按键事件结束,
;即始终以按键弹起来作为按键事件结束标志。也是一手二牍之法。一显然是
;用于“去抖”,二则宣布按键事件结束。其玄机如此。
KEY0: MOV KEYT,#0
CLR KEYOK
LJMP KEYEND
KEY1: MOV B,#0FEH ;有有效按键,执行至此,对B进行初始化
;请注意其中的玄机,不管该键是否支持长按,有有效按键,先执行一次再说,
;用此解决所有键都可以点射(单击)功能。
JNB KEYOK,KEY2 ;未执行跳至KEY2。已执行,判其是否是支持长按的键
MOV B,#0E7H ;初始化B备用,以控制射速即响应速度
MOV A,KEYCODE
XRL A,#5 ;假设键码为5的键支持长按
JZ KEY2 ;是则转KEY2,否则退出。
LJMP KEYOFF ;捋一下,执行至此是何状态:有有效按键、已执行过
;但不支持长按,则转至KEYOFF处(置已执行标志及清键龄计数器),用此控制不支
;持长按的键按一次(无论久暂)只执行一次,防止误触发。其用心之深,比普通
;按键程序,有几何级数的差异.
;KEY2,相当于是C的函数,用KEYT及B传递参数.其功能为二者相加溢出则
;调函数KEY3,否则return(RETI)。
KEY2: MOV A,KEYT ;由于B值不同,点射时立即执行,扫射时有节奏地进行
ADD A,B
JC KEY3 ;判是否溢出,与定时器原理同
LJMP KEYEND
KEY3: MOV A,KEYCODE
;以下就是散转,要注意的是执行了键功能后返回KEYOFF
;处,置已执行标志及清键龄,为下一次读键准备条件
MOV B,#3
MUL AB
MOV DPTR,#KEYN
JMP @A+DPTR
KEYN: LJMP KEYWK0
LJMP KEYWK1
LJMP KEYWK2
.
.
.
KEYOFF:SETB KEYOK
MOV KEYT,#0
KEYEND:
由于采取按键然后响应这样的编程机制,所以不支持一键多义。如再支持一键多义,其难度又会上升到何种程度,有不可测度者。
有神童级别的人物,不数年功夫,即精通主要的PC机编程语言、主要的嵌入式系统编程语言、主要的绘图软件使用、精通各种单片机、ARM、DSP、FTGP等,至于模电、数电等更不在话下。自己学有年矣,却还在为键盘程序伤脑筋。把自己的学习心得写出来,是想据此推测:高手的高度实在是难以仰望!且与诸位初学们共勉罢! |