|
单片机按键设计方法探究
汪志军
(南昌航空大学 10406)
摘要:介绍单片机按键设计方法,简要坦述它们设计思路和原理。
关键词:按键设计 51单片机
引言: 自单片机诞生以后,它就步入人们的生活,如洗衣机、电冰箱、电子玩具等家用电器配上单片机后,提高了智能化程度,增加了功能,倍受人们喜爱。本论文介绍了如何更好的设计单片机外部按键,充分利用单片机IO口。
作者概述:本论文主要讲述单片机按键设计方法,电路图和汇编程序都较为简单。写本论文的目的是为了使读者对按键有更深的了解,论文重在设计启发,激发大家自己设计更好的按键方法。论文全部的程序和电路图都是作者亲自制作,有些设计思路是从网上书上获得的,有些是自己想出来的。本人希望以自己的亲身感受来谈谈自己对按键设计方法的认识。本论文程序设计可能会有点乱,希望读者原谅,同时也欢迎读者提出本论文的错误或不足。
作者联系方式——邮箱:gin0101@126.com
QQ:382594424
本论文主要介绍:1、独立按键 2、矩阵按键 3、组合键式按键 4、累加式按键 5、编码器按键 6、AD按键 7、二进制式按键 8、频率式按键 9、模块克隆式按键10、其他按键(长按与短按、单击与双击)
为了尽量简化本论文,该论文使用的汇编程序大部分只写出它的按键扫描程序。所有按键的键值都储存在寄存器R1中,键值通过P1口各个IO口的高低电平显示,P2口与按键连接。
部分按键设计需要利用到得测试程序。
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN:
LCALL KEYSCAN
MOV P1,R1 ;把键值赋给P1口
JMP MAIN
;----------按键扫描子程序-----------
TIME20MS:
MOV R6,#40
GIN: MOV R7,#250
DJNZ R7,$
DJNZ R6,GIN
RET
END
下面将分别介绍这些按键的具体设计
1. 独立按键
1.1 电路图
图1
1.2 汇编程序
;按键扫描子程序
KEYSCAN:
MOV P2,#0FFH
MOV A,P2
CJNE A,#0FFH,AGAIN1
JMP EXIT
AGAIN1: LCALL TIME20MS ;延时去抖动
MOV A,P2
CJNE A,#0FFH,KEYSCAN1
JMP EXIT
KEYSCAN1: ;键值查找
MOV R1,#0
AGAIN2: INC R1
RRC A
JC AGAIN2
EXIT: RET
1.3 设计思路
独立按键设计是简单的按键设计方法。是大部分人第一次接触的按键方法。它适用于按键比较少的设计电路中使用。51有32个IO口,最多只能安放32个独立按键。
优点:设计简单、容易控制、支持多点操作
缺点:占用单片机的IO口多
2. 矩阵按键
2.1 电路图
图2
2.2 汇编程序
2.2.1逐点扫描法
KEYSCAN:
MOV P2,#0F0H
MOV A,P2
CJNE A,#0F0H,AGAIN
JMP EXIT
AGAIN: LCALL TIME20MS ;延时去抖动
MOV A,P2
CJNE A,#0F0H,KEYSCAN1 ;查找是否有键按下
JMP EXIT
KEYSCAN1: ;第一行扫描
MOV P2,#0FEH
MOV A,#0
KEYSCAN1_1: ;第一行第一例扫描
JB P2.4,KEYSCAN1_2
JMP ADD1
KEYSCAN1_2: ;第一行第二例扫描
JB P2.5,KEYSCAN1_3
JMP ADD2
KEYSCAN1_3: ;第一行第三例扫描
JB P2.6,KEYSCAN1_4
JMP ADD3
KEYSCAN1_4: ;第一行第四例扫描
JB P2.7,KEYSCAN2
JMP ADD4
KEYSCAN2: ;第二行扫描
MOV P2,#0FDH
MOV A,#4
KEYSCAN2_1:
JB P2.4,KEYSCAN2_2
JMP ADD1
KEYSCAN2_2:
JB P2.5,KEYSCAN2_3
JMP ADD2
KEYSCAN2_3:
JB P2.6,KEYSCAN2_4
JMP ADD3
KEYSCAN2_4:
JB P2.7,KEYSCAN3
JMP ADD4
KEYSCAN3: ;第三行扫描
MOV P2,#0FBH
MOV A,#8
KEYSCAN3_1:
JB P2.4,KEYSCAN3_2
JMP ADD1
KEYSCAN3_2:
JB P2.5,KEYSCAN3_3
JMP ADD2
KEYSCAN3_3:
JB P2.6,KEYSCAN3_4
JMP ADD3
KEYSCAN3_4:
JB P2.7,KEYSCAN4
JMP ADD4
KEYSCAN4: ;第四行扫描
MOV P2,#0F7H
MOV A,#12
KEYSCAN4_1:
JB P2.4,KEYSCAN4_2
JMP ADD1
KEYSCAN4_2:
JB P2.5,KEYSCAN4_3
JMP ADD2
KEYSCAN4_3:
JB P2.6,KEYSCAN4_4
JMP ADD3
KEYSCAN4_4:
JMP ADD4
ADD1: ADD A,#1
JMP EXIT1
ADD2: ADD A,#2
JMP EXIT1
ADD3: ADD A,#3
JMP EXIT1
ADD4: ADD A,#4
EXIT1: MOV R1,A
EXIT: RET
2.2.2逐行(列)扫描法
KEYSCAN:
MOV P2,#0F0H
MOV A,P2
CJNE A,#0F0H,AGAIN
JMP EXIT
AGAIN: LCALL TIME20MS ;延时去抖动
MOV A,P2
CJNE A,#0F0H,KEYSCAN1 ;查找是否有键按下
JMP EXIT
KEYSCAN1: ;第一行扫描
MOV P2,#0FEH
MOV R1,#0
MOV A,P2
ANL A,#0F0H
CJNE A,#0F0H,FUZHI
KEYSCAN2: ;第二行扫描
MOV P2,#0FDH
MOV R1,#4
MOV A,P2
ANL A,#0F0H
CJNE A,#0F0H,FUZHI
KEYSCAN3: ;第三行扫描
MOV P2,#0FBH
MOV R1,#8
MOV A,P2
ANL A,#0F0H
CJNE A,#0F0H,FUZHI
KEYSCAN4: ;第四行扫描
MOV P2,#0F7H
MOV R1,#12
MOV A,P2
ANL A,#0F0H
CJNE A,#0F0H,FUZHI
FUZHI: MOV R2,A ;给键值赋值
MOV A,R1
CJNE R2,#0E0H,ADD2
ADD1: ADD A,#1
JMP EXIT1
ADD2: CJNE R2,#0D0H,ADD3
ADD A,#2
JMP EXIT1
ADD3: CJNE R2,#0B0H,ADD4
ADD A,#3
JMP EXIT1
ADD4: ADD A,#4
EXIT1: MOV R1,A
EXIT: RET
2.2.3 反转扫描法
KEYSCAN:
MOV P2,#0F0H
MOV A,P2
CJNE A,#0F0H,AGAIN
JMP EXIT
AGAIN: LCALL TIME20MS ;延时去抖动
MOV A,P2
CJNE A,#0F0H,KEYSCAN1 ;查找是否有键按下
JMP EXIT
KEYSCAN1:
MOV P2,#0FH
MOV B,P2
ORL A,B
MOV B,A
MOV DPTR,#TABLE
MOV R1,#0
AGAIN2: MOV A,R1
MOVC A,@A+DPTR
CJNE A,B,INCR1 ;通过表中的值来确定键值
JMP EXIT1
INCR1: INC R1
JMP AGAIN2
EXIT1: INC R1
EXIT: RET
TABLE: DB 0EEH,0DEH,0BEH,7EH ;键值表
DB 0EDH,0DDH,0BDH,7DH
DB 0EBH,0DBH,0BBH,7BH
DB 0E7H,0D7H,0B7H,77H
2.3 设计思路
矩阵按键扫描法是比较好的按键设计方法,51单片机32个IO口最多可以组成16*16=256个按键。上面介绍了三种扫描方式,下面来一一介绍他们的不同。
首先,逐点扫描法,它扫描的时间相对要多一点,它可以直接对每一个按键进行扫描,所以它可以扫描到同时多个键按下,支持多点。利用这种扫描方式,可以允许组合键的使用,而且不会混淆;再次,逐行(列)扫描法,扫描时间相对少,是逐行(列)扫描,支持多点,可以允许组合键的使用;最后,反转扫描法,扫描时间最少,最大的特点是利用了查表来确定键值,不支持多点。
在给出的程序中都没牵涉多点操作,只在单个按键按下有效。如果要考虑组合键的使用则使用逐点扫描法较好。
3. 组合键式按键
3.1 电路图
图3
3.2 汇编程序
KEYSCAN:
MOV P2,#3FH
MOV A,P2
CJNE A,#3FH,AGAIN
JMP EXIT
AGAIN: LCALL TIME20MS
MOV A,P2
CJNE A,#3FH,KEYSCAN1
JMP EXIT
KEYSCAN1:MOV P2,#0FFH ;第一轮扫描
MOV R1,#0
CLR P2.7
NOP
JNB P2.5,ADD1
JNB P2.4,ADD2
JMP KEYSCAN2
ADD1: MOV A,R1
ADD A,#1
MOV R1,A
JNB P2.4,ADD2
JMP KEYSCAN2
ADD2: MOV A,R1
ADD A,#2
MOV R1,A
KEYSCAN2:MOV P2,#0FFH ;第二轮扫描
CLR P2.6
NOP
JNB P2.5,ADD4
JNB P2.4,ADD6
JMP EXIT
ADD4: MOV A,R1
ADD A,#4
MOV R1,A
JNB P2.4,ADD6
JMP EXIT1
ADD6: MOV A,R1
ADD A,#6
MOV R1,A
EXIT1: CJNE R1,#10,EXIT
MOV R1,#7
EXIT: RET
3.3 设计思路
在我们平时按键设计中,我们都是用两根电路线,但你们想没想过用三根或更多电路线组成一个按键呢。组合键式按键最大特点就是利用了组合键,把组合键也单立一个按键,所以它不支持多点。它的电路设计简单,但按键要求是可以同时开/关多条电路的复合按键。你可以把三条电路线复合成一个按键,也可以把四根电路线复合成一个按键,当然也可以同时复合。当你把三条电路线复合成一个按键,将可以组合:在总共四条电路线中选三条,有4种;当你把四条电路线复合成一个按键,将可以组合1个按键;在加上我们平时常用的两根电路线组成的按键,也就是四种选二有6种,这样四根电路线总共可以组成4+1+6=11个按键。
4. 累加式按键
4.1 电路图
图4
4.2 汇编程序
KEYSCAN:
MOV P2,#0FFH
KEYSCAN1: ;键值小于等于8的扫描(1到8)
MOV A,P2
CJNE A,#0FFH,KEYSCAN1_1
JMP KEYSCAN2
KEYSCAN1_1:
LCALL TIME20MS
MOV A,P2
CJNE A,#0FFH,KEYSCAN1_2
JMP KEYSCAN2
KEYSCAN1_2:
MOV R1,#0
AGAIN1: INC R1
RRC A
JC AGAIN1
JMP EXIT
KEYSCAN2: ;键值大于8的扫描(9到36)
KEYSCAN2_1:
MOV P2,#0FEH
MOV A,P2
CJNE A,#0FEH,GIN2_1_1
JMP KEYSCAN2_2
GIN2_1_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0FEH,GIN2_1_2
JMP KEYSCAN2_2
GIN2_1_2:MOV R1,#7
ORL A,#1
AGAIN2_1:INC R1
RRC A
JC AGAIN2_1
JMP EXIT
KEYSCAN2_2:
MOV P2,#0FDH
MOV A,P2
CJNE A,#0FDH,GIN2_2_1
JMP KEYSCAN2_3
GIN2_2_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0FDH,GIN2_2_2
JMP KEYSCAN2_3
GIN2_2_2:MOV R1,#13
ORL A,#2
AGAIN2_2:INC R1
RRC A
JC AGAIN2_2
JMP EXIT
KEYSCAN2_3:
MOV P2,#0FBH
MOV A,P2
CJNE A,#0FBH,GIN2_3_1
JMP KEYSCAN2_4
GIN2_3_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0FBH,GIN2_3_2
JMP KEYSCAN2_4
GIN2_3_2:MOV R1,#18
ORL A,#4
AGAIN2_3:INC R1
RRC A
JC AGAIN2_3
JMP EXIT
KEYSCAN2_4:
MOV P2,#0F7H
MOV A,P2
CJNE A,#0F7H,GIN2_4_1
JMP KEYSCAN2_5
GIN2_4_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0F7H,GIN2_4_2
JMP KEYSCAN2_5
GIN2_4_2:MOV R1,#22
ORL A,#8
AGAIN2_4:INC R1
RRC A
JC AGAIN2_4
JMP EXIT
KEYSCAN2_5:
MOV P2,#0EFH
MOV A,P2
CJNE A,#0EFH,GIN2_5_1
JMP KEYSCAN2_6
GIN2_5_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0EFH,GIN2_5_2
JMP KEYSCAN2_6
GIN2_5_2:MOV R1,#25
ORL A,#10H
AGAIN2_5:INC R1
RRC A
JC AGAIN2_5
JMP EXIT
KEYSCAN2_6:
MOV P2,#0DFH
MOV A,P2
CJNE A,#0DFH,GIN2_6_1
JMP KEYSCAN2_7
GIN2_6_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0DFH,GIN2_6_2
JMP KEYSCAN2_7
GIN2_6_2:MOV R1,#27
ORL A,#20H
AGAIN2_6:INC R1
RRC A
JC AGAIN2_6
JMP EXIT
KEYSCAN2_7:
MOV P2,#0BFH
MOV A,P2
CJNE A,#0BFH,GIN2_7_1
JMP EXIT
GIN2_7_1:LCALL TIME20MS
MOV A,P2
CJNE A,#0BFH,GIN2_7_2
JMP EXIT
GIN2_7_2:MOV R1,#36
EXIT: RET
4.3 设计思路
本方案按键可以分为两个方面,一个是独立按键,另一个是两线制组合按键。独立按键就不在这再叙述了,我们重点来讲讲两线制组合按键。
它分为七组,每一组都有一个公共端。扫描时把公共端置0,其它IO口都置1,然后读取被置1的 IO口的值,为0则表明有键按下。它支持多点操作,但程序中没牵涉。一个端口有八个IO口(程序以P2为例),可以组成七组,有七个公共端,第一个公共端(图中为靠近51单片机的)可以设置七个按键,第二个公共端可以设置六个按键,其它公共端可以以此类推。这样可以组成7+6+5+4+3+2+1=28按键,再加上独立按键8个按键,这样一个端口就可以组成8+7+6+5+4+3+2+1=36(等式是一个累加式)个按键。
5. 编码器按键
5.1 电路图
图5
5.2 汇编程序
KEYSCAN:
SETB P2.0 ;SETB P2.0, SETB P2.1, SETB P2.2,而不直接MOV P2,#0FFH
SETB P2.1 ; 是因为直接把0FFH赋给P2端口会影响其他没有参加按键扫描的IO口
SETB P2.2 ;但在本论文中有些程序是直接赋值的,这只是为了方便,简化程序
MOV A,#0
MOV C,P2.2
RLC A
MOV C,P2.1
RLC A
MOV C,P2.0
RLC A
CJNE A,#7,AGAIN
JMP EXIT
AGAIN: LCALL TIME20MS
MOV A,#0
MOV C,P2.2
RLC A
MOV C,P2.1
RLC A
MOV C,P2.0
RLC A
CJNE A,#7,FUZHI
JMP EXIT
FUZHI: XRL A,#7
MOV R1,A
EXIT: RET
5.3 设计思路
利用了8421编码器,当然如果有特别的要求也可以用优选编码器。3—8编码器,可以把51单片机的3个IO口扩展到7个。在使用3—8编码器时一定要给编码器的8个输入端加上上拉电阻。有人会问3—8编码器怎么不是可以把51单片机的3个IO口扩展到8个啊?为什么不是8个呢,因为单片机必须有一个默认状态也就是没有任何按键按下的时候,比如111,这要3—8编码器也就必须有一个默认状态,那就是第0输入端口保持为1。所以3—8编码器最多只能设置7个按键。它的程序较为简单,不支持多点操作。如果要进一步扩展IO口,可以将多个3—8编码器连接起来使用。
6. AD按键
6.1 电路图
图6
6.2 汇编程序
ORG 0000H
LJMP MAIN
ORG 0100H
MAIN:
MOV R1,#0
MOV R2,#0
MOV R3,#0
START:
LCALL KEYSCAN
MOV P1,R1
NOP
JMP START
KEYSCAN:
CLR P2.0 ;置/CS为0,使芯片开始工作
NOP
NOP
SETB P2.1
NOP
NOP
SETB P2.2
NOP
NOP
CLR P2.1 ;向D1端口输入1
NOP
NOP
SETB P2.1
NOP
NOP
SETB P2.2
NOP
NOP
CLR P2.1 ;向D1端口输入1
NOP
NOP
CLR P2.2
NOP
NOP
SETB P2.1
NOP
NOP
CLR P2.1 ;向D1端口输入0
NOP
NOP
MOV R2,#8
SETB P2.2
AGAIN1: SETB P2.1 ;读取D0数据
NOP
NOP
CLR P2.1
MOV C,P2.2
RLC A
DJNZ R2,AGAIN1
SETB P2.0
MOV R2,A
GINNY: MOV DPTR,#TABLE
MOV R3,#0
WZQ: MOV A,R3
MOVC A,@A+DPTR
CJNE A,#255,WZQWZJ ;不加这条程序初始AD的误转换使R1超出范围,没有按下键R1也被赋值而且超出了键值范围
JMP EXIT
WZQWZJ: SUBB A,R2
JC INCR3
CJNE R3,#0,FUR1
JMP EXIT
FUR1: MOV A,R3
MOV R1,A
JMP EXIT
INCR3: INC R3
JMP WZQ
EXIT: RET
TABLE: DB 10,25,40,55,70,85,100,120,255 ;255是为了防止R1的值超出范围
TIME20MS:
MOV R6,#40
GIN: MOV R7,#250
DJNZ R7,$
DJNZ R6,GIN
RET
END
;在这个程序中读取AD值时省略读取反字节过程,一般是不能省略,在这只是为了简化程序
6.3 设计思路
AD设计按键现在已经比较多人在用了,它的重点在于时序的掌握。在读取AD值时要先对ADC芯片(程序以ADC0832为例)电平设置,须先将/CS使能端置低电平并且保持低电平直到转换完全结束。此时芯片开始工作,同时由处理器向芯片时钟输入端CLK输入时钟脉冲,D0/D1端则使用D1端输入通道功能选择的数据信号。在第1个时钟脉冲的下沉之前D1端必须是高电平,表示启动信号。在地2、3个脉冲下沉之前D1端应输入2位数据用于选择通道功能,当此2位数据为1,0,时,只对CH0进行单通道转换。到第3个脉冲下沉后D1端的输入电平就失去输入作用,此后D0/D1端则开始利用数据输出D0进行转换数据的读取。从第4个脉冲下沉开始有D0端输出转换数据最高位,随后每一个脉冲下沉D0端输出下一个数据,直到第11个脉冲时发出最低位数据,一个字节的数据输出完成。从第12个脉冲下沉时,D0输出数据的反字节,到第19个脉冲时标志着一次A\D转换的结束,最后将/CS置高电平禁用芯片。
时钟信号可以形象的描述为,把数据挤进去或拉出来。在向D1输入数据时,就是把数据挤进去,每一次下沉就把一个数据挤进去;在读取D0数据时,就是把数据拉出来,每一次下沉就把一个数据拉出来。
表 TABLE: DB 10,25,40,55,70,85,100,120,255 是设置了一个范围。小于10则键值为0(没有按键按下),大于10小于25则键值为1,大于25小于40则键值为2,大于40小于55则键值为3,大于55小于70则键值为4,大于70小于85则键值为5,大于85小于100则键值为6,大于100小于120则键值为7。但如果大于120小于255键值则为0,因为大于120小于255,超出了硬件电路ADC0832分得的最大电压值所对应的表值,是出现异常时转换的数据,实验证明如果不加上这个表值,在单片机启动时,键值会出错(没有按键也被赋键值)。这些表值不是算出来的,是通过相应按键按下时单片机读取的,然后通过这些表值反过来推导出键值,这样键值会更加稳定、准确。
理论上一个ADC芯片一个通道可以设置255个按键。一个ADC芯片可以同时多个通道同时设置按键。AD按键设计方案不支持多点操作。
7. 二进制式按键
7.1 电路图
图7
7.2 汇编程序
;程序与编码器按键程序一样
7.3 设计思路
每一个IO口都有两种状态‘1’,‘0’,两个IO口就可以组成四种状态,n个IO口就有2^n(2的n次方)种状态。理论上n个IO口就可以组成2^n—1个按键,还有一个状态是默认的状态(没有任何按键的情况下),实际上设计二进制式按键比较繁琐,IO口多了就非常难设计它的电路图。图7是设计了三个IO口的二进制式按键,用二极管单向导通功能来防止键与键之间的影响。
不支持多点操作。
8. 频率式按键
8.1 电路图
图8
8.2 汇编程序
ORG 0000H
LJMP MAIN
ORG 001BH
LJMP TIME1
ORG 0100H
MAIN:
MOV TH1,#33H
MOV TL1,#28H
MOV TMOD,#16H ;T/C0计数方式2,T/C1定时方式1
MOV TL0,#0
MOV IE,#88H
MOV SP,#0EFH
MOV R3,#0
MOV R1,#0
START: LCALL KEYSCAN
MOV P1,R1
NOP
JMP START
KEYSCAN:
CJNE R3,#0,EXIT
SETB TR1
SETB TR0
MOV R3,#1
EXIT: RET
TIME1: ORL TL1,#28H
MOV TH1,#33H
MOV R3,#0
CLR TR1
CLR TR0
CLR TF0
MOV R2,TL0
MOV TL0,#0
MOV DPTR,#TABLE
MOV R4,#0
GINNY: MOV A,R4
MOVC A,@A+DPTR
SUBB A,R2
JC INCR4
CJNE R4,#0,FUR1
JMP EXIT_TIME1
FUR1: MOV A,R4
MOV R1,A
JMP EXIT_TIME1
INCR4: INC R4
JMP GINNY
EXIT_TIME1:RETI
TABLE: DB 10,18,23,28,33,38,45 ;键值范围表
;这种方式,不太稳定,容易误判。因为你不知道频率什么时候定下来,
;tl0很可能只计到部分计数,常常会使键值偏小
8.3 设计思路
频率式按键程序设计有两种,一种是在一定时间内读取它的周期个数(上述汇编程序就是用这种方法),这种方法不准确,容易误判,因为你不知道频率什么时候定下来,很可能只都到部分计数,常常会使键值偏小;另一种方法是读取若干个周期的时间,这种方法准确,程序编辑相对复杂一点。
每个按键按下对应接入到555的电阻都不同,555产生的频率就会不同,当单片机读取到这些频率,然后查表,就可以根据频率的差异,相应赋键值。最好每个按键产生的频率差异尽量大一点,这样单片机就更容易识别这些按键。
不支持多点操作。
9. 模块克隆式按键
9.1 电路图
图9
9.2 汇编程序
KEYSCAN:
MOV A,P2
ORL A,#1FH
MOV P2,A
CLR P2.0
CLR P2.1
MOV A,P2
ANL A,#0CH
CJNE A,#0CH,AGAIN1
JMP EXIT
AGAIN1: LCALL TIME20MS
MOV A,P2
ANL A,#0CH
CJNE A,#0CH,AGAIN2
JMP EXIT
AGAIN2: JNB P2.4,KEYADD4 ;检测是否是第二模块有按键按下,有则跳转
MOV R1,#0
JMP KEYSCAN1
KEYADD4:MOV R1,#4
KEYSCAN1:MOV A,P2
ORL A,#1FH
MOV P2,A
CLR P2.0
JNB P2.2,ADD1
JNB P2.3,ADD2
JMP KEYSCAN2
ADD1: MOV A,R1
ADD A,#1
MOV R1,A
JMP EXIT
ADD2: MOV A,R1
ADD A,#2
MOV R1,A
JMP EXIT
KEYSCAN2:SETB P2.0
CLR P2.1
JNB P2.2,ADD3
JNB P2.3,ADD4
JMP EXIT
ADD3: MOV A,R1
ADD A,#3
MOV R1,A
JMP EXIT
ADD4: MOV A,R1
ADD A,#4
MOV R1,A
EXIT: RET
;该程序没错,但放入proteus中不会出结果,经检查proteus中或门出问题,目前这个问题还没被解决
;希望读者能者指出错误所在,谢谢!
9.3 设计思路
模块克隆式按键顾名思义就是以一个模块为模板,然后以这个模板进行克隆复制。图9就是一个四个键的模块为模板来克隆复制,图中复制了一次。当然可以再次克隆,再次克隆就是以上次的全部按键为模板来复制。每个模板通过逻辑门和一个IO口来区别,如图9是通过或门区别。每复制一次就只要一个IO口,这要一个端口就可以组成4*2^(8-4)=2^6=64个按键,这是理论上可行,实际现实是很困难的。按照这个原理复制则一个51单片机的四个端口最多可以组成2^(6+8+8+8)=2^30=1024^3=1073741824个按键。克隆复制方法还可以还其他按键方法一起使用比如独立按键、二进制式按键等,如果和独立按键使用则最多可以组成2^(7+8+8+8)=2^31=2147483648个按键。
不支持多点操作。
10. 其他按键
电路图与独立按键一样,但这里只用了独立按键的P2.0一个IO口。
10.1其他按键—长按与短按
;延时法
KEYSCAN:
SETB P2.0
NOP
JB P2.0,EXIT
AGAIN1: LCALL TIME20MS
JB P2.0,EXIT ;判断是否有按键按下
AGAIN2: MOV R3,#10
GINNY: MOV R2,#10 ;检测按键按下的时间是否达到长按的要求
WZQ: LCALL TIME20MS
DJNZ R2,WZQ
JB P2.0,EXIT2 ;按键在长按的要求时间内抬起则为短按键值为1
DJNZ R3,GINNY
MOV R1,#2 ;达到长按的要求时间则为长按键值为2
JMP EXIT1
EXIT2: MOV R1,#1
EXIT1: JNB P2.0,$ ;判断按键是否抬起
EXIT: RET
10.1.1 设计思路
长按与短按可以用两种方法检测,一种是延时法检测(上述程序),另一种是定时法。
延时法是在延时的时间内不断地检测按键是否被抬起,如果在延时过后按键还是没被抬起则说明按键是长按操作,如果在延时范围内被抬起则说明按键是短按操作,一般延时为一秒以上。当检测是长按操作时,要等待按键被抬起,否则可能又会被检测到一个短按操作,因为长按时间很可能大于延时,当延时完成后就立即赋键值后退出,而这时按键又处于按下状态,这样程序很可能再次检测这个按下的按键,如果在第二个延时检测中按键被抬起,这时程序就会误把上次的长按操作变成本次检测的短按操作。但延时法会降低单片机处理效率,会影响单片机其他外设的操作,比如数码管的显示等。
定时法和延时法的原理一样,只是采用的方式不同。定时是每隔一段时间就检测一下按键的状态,在规定的读取次数,根据读取到的按键状态来判断按键是长按还是短按。当然这也的注意到长按操作后的处理,要在读取到长按操作后不能马上关闭定时中断,要检测到按键抬起再关闭,才可以进行下一次按键状态检测。定时法在一定程度上不会影响单片机其他外设的操作。
10.2其他按键—单击与双击
;延时法
KEYSCAN:
SETB P2.0
NOP
NOP
JB P2.0,EXIT
AGAIN1: LCALL TIME20MS
JB P2.0,EXIT ;判断是否有按键按下
MOV R1,#1
AGAIN2: MOV R2,#25
GINNY1:
LCALL TIME20MS
JNB P2.0,NEXT1 ;规定时间内等待按键抬起
JMP GINNY2
NEXT1: DJNZ R2,GINNY1
JMP EXIT
GINNY2: LCALL TIME20MS
JB P2.0,NEXT2 ;在规定时间内判断按键抬起后是否有再按下操作
JMP ADDR1 ;在规定时间内按键再次按下则跳转
NEXT2: DJNZ R2,GINNY2
JMP EXIT ;超过双击检测时间则退出
ADDR1: INC R1
JNB P2.0,$ ;等待按键抬起
EXIT: RET
10.2.1 设计思路
单击与双击也可以用两种方法检测,一种是延时法检测(上述程序),另一种是定时法。单击与双击的检测方法和长按与短按的检测方法很相似。
延时法就是在延时范围内检测有几个按下操作,如果有两个按下操作则退出延时,说明是双击,如果在延时后只有一个按下操作,则说明单击。在得到键值后要等待按键抬起,原因和长按与短按的一样。
定时法也是每隔一段时间检测一次按键状态,在规定的次数中读取按键按下的次数,当读到按键次数为两次则赋键值说明是双击,读到两次按下操作后如果检测到按抬起则关闭中断,如果在规定的次数中只检测到一个按下操作则说明是单击。
相关资料可以到: javascript:; 或 javascript:;的论坛的原创中下载。