由于在学习用DS1302来做LED时钟时,发现开发板附的程序对按键操作,很不灵活,后来在网上找到一篇《一个按键的多次击键组合判别技巧》;
C51汇编的参考程序,经学习摸索已改成C51汇编了,并已用XL400 单片;
;以下主程序演示了不同组合按键时,分别控制P2.0-P2.5各端口的LED灯的亮灭。
;单次短击=>P2.0/LED1
;单次长击=>P2.1/LED2
;短击+短击=>P2.2/LED3
;短击+长击=>P2.3/LED4
;长击+短击=>P2.4/LED5
;长击+长击=>P2.5/LED6
;------------------------------------------------------------
ORG 0040H
AJMP MAIN
MAIN:
MOV P1,#0FFH
MOV P2,#0FFH ;初始化端口
LOOP:
CALL SREAD_KEY ;读单按键--子程序
MOV R0,KEY_NUM
CJNE R0,#00000010B,MAIN1 ;比较键值不等跳
CPL LED1_6.0 ;取反P2.0
MAIN1:
CJNE R0,#00000011B,MAIN2 ;比较键值不等跳
CPL LED1_6.1 ;取反P2.1
MAIN2:
CJNE R0,#00000100B,MAIN3 ;比较键值不等跳
CPL LED1_6.2 ;取反P2.2
MAIN3:
CJNE R0,#00000101B,MAIN4 ;比较键值不等跳
CPL LED1_6.3 ;取反P2.3
MAIN4:
CJNE R0,#00000110B,MAIN5 ;比较键值不等跳
CPL LED1_6.4 ;取反P2.4
MAIN5:
CJNE R0,#00000111B,MAIN_EXIT ;比较键值不等跳
CPL LED1_6.5 ;取反P2.5
MAIN_EXIT:
JMP LOOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;读单按键--子程序
;子程序执行后返回值KEY_NUM即键值
;-----------------------------说明----------------------------
;短击:键按下时间<500MS
;长击:键按下时间>500MS
;两次按键间隔时间<700MS
;键值定义:
;KEY_NUM="00000000": 无键按下
;KEY_NUM="00000001": 无意义
;KEY_NUM="00000010": 单次短击
;KEY_NUM="00000011": 单次长击
;KEY_NUM="00000100": 短击+短击
;KEY_NUM="00000101": 短击+长击
;KEY_NUM="00000110": 长击+短击
;KEY_NUM="00000111": 长击+长击
;KEY_NUM="00001000": 短击+短击+短击
;KEY_NUM="00001001": 短击+短击+长击
;KEY_NUM="00001011": 短击+长击+长击
;KEY_NUM="00001111": 长击+长击+长击
;以编码从左看起第一个1看作为分界线,左边为0、而右边的0和1表示为:
;0短击1长击。
;以上组合已足够用了!
;*************************************************************
; KEY EQU P1.0
; KEY_NUM EQU 20H
;*************************************************************
SREAD_KEY:
MOV KEY_NUM,#00H ;键值清0
JB KEY,SKEY_EXIT ;键未按下跳
CALL DL10MS ;延时去抖动
JB KEY,SKEY_EXIT ;键未按下跳
MOV KEY_NUM,#1 ;置键值为#00000001B
SKEY_A:
MOV R0,#00H ;清计数器
CLR C ;清CY
SKEY_B:
CALL DL10MS
INC R0
MOV A,#50
SUBB A,R0
JC SKEY_C ;当键按下>500MS跳
JNB KEY,SKEY_B ;键未释放跳
CALL DL10MS ;延时去抖动
JNB KEY,SKEY_B ;键未释放跳
CLR C ;CY置0
JMP SKEY_D
SKEY_C:
JNB KEY,$ ;键未释放停
CALL DL10MS ;延时去抖动
JNB KEY,$ ;键未释放停
SETB C ;CY置1
SKEY_D:
MOV A,KEY_NUM
RLC A ;键值左移一位,C->键值低位
MOV KEY_NUM,A
JB KEY_NUM.2,SKEY_EXIT ;判断按键检测是否完成,完成跳
;说明:KEY_NUM.1时只判断单次按键两种组合,KEY_NUM.2时可判断两次按键4种组合+单次按键的2种组合=6种,以此类推。
MOV R0,#00H ;清计数器
CLR C ;CY置0
SKEY_E:
CALL DL10MS
INC R0
MOV A,#70
SUBB A,R0
JC SKEY_EXIT ;当未按下>700MS跳出
JB KEY,SKEY_E ;键释放跳
CALL DL10MS ;延时去抖动
JB KEY,SKEY_E ;键释放跳
JMP SKEY_A ;当未按下<700MS再次检测
SKEY_EXIT:
RET
;************************************************************
;延时10mS
;************************************************************
DL10ms:
MOV R5,#14H ;20 ;10.262ms=20*511+2*20+1=20.261
TIME10MS_1:
MOV R6,#0FFH ;255 ;511us=255*2+1
DJNZ R6,$
DJNZ R5,TIME10MS_1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END
C51汇编的参考程序,经学习摸索已改成C51汇编了,并已用XL400 单片;
;以下主程序演示了不同组合按键时,分别控制P2.0-P2.5各端口的LED灯的亮灭。
;单次短击=>P2.0/LED1
;单次长击=>P2.1/LED2
;短击+短击=>P2.2/LED3
;短击+长击=>P2.3/LED4
;长击+短击=>P2.4/LED5
;长击+长击=>P2.5/LED6
;------------------------------------------------------------
ORG 0040H
AJMP MAIN
MAIN:
MOV P1,#0FFH
MOV P2,#0FFH ;初始化端口
LOOP:
CALL SREAD_KEY ;读单按键--子程序
MOV R0,KEY_NUM
CJNE R0,#00000010B,MAIN1 ;比较键值不等跳
CPL LED1_6.0 ;取反P2.0
MAIN1:
CJNE R0,#00000011B,MAIN2 ;比较键值不等跳
CPL LED1_6.1 ;取反P2.1
MAIN2:
CJNE R0,#00000100B,MAIN3 ;比较键值不等跳
CPL LED1_6.2 ;取反P2.2
MAIN3:
CJNE R0,#00000101B,MAIN4 ;比较键值不等跳
CPL LED1_6.3 ;取反P2.3
MAIN4:
CJNE R0,#00000110B,MAIN5 ;比较键值不等跳
CPL LED1_6.4 ;取反P2.4
MAIN5:
CJNE R0,#00000111B,MAIN_EXIT ;比较键值不等跳
CPL LED1_6.5 ;取反P2.5
MAIN_EXIT:
JMP LOOP
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;读单按键--子程序
;子程序执行后返回值KEY_NUM即键值
;-----------------------------说明----------------------------
;短击:键按下时间<500MS
;长击:键按下时间>500MS
;两次按键间隔时间<700MS
;键值定义:
;KEY_NUM="00000000": 无键按下
;KEY_NUM="00000001": 无意义
;KEY_NUM="00000010": 单次短击
;KEY_NUM="00000011": 单次长击
;KEY_NUM="00000100": 短击+短击
;KEY_NUM="00000101": 短击+长击
;KEY_NUM="00000110": 长击+短击
;KEY_NUM="00000111": 长击+长击
;KEY_NUM="00001000": 短击+短击+短击
;KEY_NUM="00001001": 短击+短击+长击
;KEY_NUM="00001011": 短击+长击+长击
;KEY_NUM="00001111": 长击+长击+长击
;以编码从左看起第一个1看作为分界线,左边为0、而右边的0和1表示为:
;0短击1长击。
;以上组合已足够用了!
;*************************************************************
; KEY EQU P1.0
; KEY_NUM EQU 20H
;*************************************************************
SREAD_KEY:
MOV KEY_NUM,#00H ;键值清0
JB KEY,SKEY_EXIT ;键未按下跳
CALL DL10MS ;延时去抖动
JB KEY,SKEY_EXIT ;键未按下跳
MOV KEY_NUM,#1 ;置键值为#00000001B
SKEY_A:
MOV R0,#00H ;清计数器
CLR C ;清CY
SKEY_B:
CALL DL10MS
INC R0
MOV A,#50
SUBB A,R0
JC SKEY_C ;当键按下>500MS跳
JNB KEY,SKEY_B ;键未释放跳
CALL DL10MS ;延时去抖动
JNB KEY,SKEY_B ;键未释放跳
CLR C ;CY置0
JMP SKEY_D
SKEY_C:
JNB KEY,$ ;键未释放停
CALL DL10MS ;延时去抖动
JNB KEY,$ ;键未释放停
SETB C ;CY置1
SKEY_D:
MOV A,KEY_NUM
RLC A ;键值左移一位,C->键值低位
MOV KEY_NUM,A
JB KEY_NUM.2,SKEY_EXIT ;判断按键检测是否完成,完成跳
;说明:KEY_NUM.1时只判断单次按键两种组合,KEY_NUM.2时可判断两次按键4种组合+单次按键的2种组合=6种,以此类推。
MOV R0,#00H ;清计数器
CLR C ;CY置0
SKEY_E:
CALL DL10MS
INC R0
MOV A,#70
SUBB A,R0
JC SKEY_EXIT ;当未按下>700MS跳出
JB KEY,SKEY_E ;键释放跳
CALL DL10MS ;延时去抖动
JB KEY,SKEY_E ;键释放跳
JMP SKEY_A ;当未按下<700MS再次检测
SKEY_EXIT:
RET
;************************************************************
;延时10mS
;************************************************************
DL10ms:
MOV R5,#14H ;20 ;10.262ms=20*511+2*20+1=20.261
TIME10MS_1:
MOV R6,#0FFH ;255 ;511us=255*2+1
DJNZ R6,$
DJNZ R5,TIME10MS_1
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
END
评论
查看更多