?? 96key.txt
字號:
;-------96鍵程序-------------------------
;這是1個回復題中的應用示例,已通過軟仿真“驗證”
;這只是鍵掃描技術的1個“縮影”,方法實在太多.
;有“難看之處”,敬請高手們批評指教.
;HotPower將虛心接受,堅決改正.重新做人.
;發表目的: 在21IC中壯大游擊隊.
;----------------------------------------------------
;由于2051資源問題,本程序只取多任務鍵盤的壓放鍵2個事件
;廢除長壓鍵(壓鍵1段時間后才激活)事件
;廢除長放鍵(放鍵1段時間后才激活)事件
;廢除雙擊鍵事件
;廢除任意組合鍵事件
;----------常數定義------------------------------
TIME208US EQU -208;20mS/96=208uS
TIME50MS EQU -5000;50000uS
;KEYCOUNT EQU 1;鍵盤鍵個數(軟仿真時用)
;------------------------------------------------
KEYCOUNT EQU 96;鍵盤鍵個數(實際應用)
;----------RAM地址定義----------------------------
;--------96鍵鍵狀態標志位數組Bits[12*8位]--------
KEYBUFF1 DATA 08H;08H~13H(12個字節96位)對應96鍵
;--------96鍵鍵跳變標志位數組Bits[12*8位]--------
KEYBUFF2 DATA 14H;14H~1FH(12個字節96位)對應96鍵
;------------------------------------------------
KEYNUM DATA 30H;
HotPower_55H DATA 6EH
HotPower_AAH DATA 6FH
;---------------------------------------
SP_MIN DATA HotPower_AAH
;-------主程序開始----------------------
ORG 0000H
START:
LJMP MAINSTART;主程序開始
ORG 0003H
;-------掉電保護中斷INT0服務程序--------
INT0_INTADDR:
RETI
ORG 000BH
;-------定時器T0中斷服務程序------------
;工作在8位自動裝載方式,每208uS中斷一次
T0_INTADDR:
LJMP T0INTPROC;定時器T0中斷服務程序
RETI
ORG 0013H
;-------外部中斷INT1服務程序------------
INT1_INTADDR:
RETI
ORG 001BH
;-------定時器T1中斷服務程序------------
T1_INTADDR:
LJMP T1INTPROC;定時器T1中斷服務程序
RETI
; ORG 0023H
;-------串行中斷服務程序----------------
;SINT_INTADDR:
; RETI
;-------------------------------------------
; ORG 002BH
;-------定時器T2中斷服務程序------------
; LJMP T2INTPROC;執行中斷服務程序
; RETI
;-------執行鍵盤命令----------------------
;本程序利用散轉回收技術(指針函數)
;它的最大優點是散轉處的子程序可被它用(函數)
;它比JMP @A+DPTR指令要“游擊”很多,靈活和隱蔽了許多
;它在對付“反匯編”方面,比JMP @A+DPTR更“壞”
;HotPower打死也不用JMP @A+DPTR
KEYPROC:
;入口: DPTR散轉地址表
; ACC 散轉號
CJNE A,#KEYCOUNT,$+3
JNC KEYPROC_EXIT;非法鍵(96~255)防止程序飛,不散轉
RL A;*2;地址需要2字節(像ARM的大端模式)
ADD A,DPL
MOV DPL,A
CLR A
ADDC A,DPH
MOV DPH,A
MOV A,#01H;低8位
MOVC A,@A+DPTR;取低8位地址
PUSH ACC;壓入事件處理低8位地址
CLR A;高8位
MOVC A,@A+DPTR;取高8位地址
PUSH ACC;壓入事件處理高8位地址
KEYPROC_EXIT:
RET;執行鍵盤命令(散轉JMP @A+DPTR)
;-------壓鍵事件處理地址表--------------------
KEYJMPPROCTAB:
DW KEYPROC0;0鍵壓鍵
DW KEYPROC1
DW KEYPROC2
;............................
DW KEYPROC95;95鍵壓鍵
;-------放鍵事件處理地址表--------------------
KEYJMPPROCTABX:
DW KEYPROC0X;0鍵放鍵
DW KEYPROC1X
DW KEYPROC2X
;............................
DW KEYPROC95X;95鍵放鍵
MAINSTART:
;-------P0口初始化------------------
MOV P0,#11111111B
;-------P1口初始化------------------
MOV P1,#11111111B
;-------P2口初始化------------------
MOV P2,#11111111B
;-------P3口初始化------------------
MOV P3,#11111111B
;--------------------------------
MOV IE,#00000000B;EA=0,ES=ET2=ET1=EX1=ET0=EX0=0
MOV SP,#SP_MIN;
MOV PSW,#00000000B;RS1RS0=00,R0~R7=00H~07H
MOV A,#LOW(MAINNEXT)
PUSH ACC
MOV A,#HIGH(MAINNEXT)
PUSH ACC
RETI
MAINPROC:
LCALL MAININIT;系統初始化
MOV IE,#10001010B;開中斷
;-------主循環-------------------------------
MAINLOOP:
ORL PCON,#10001101B;待機
SJMP MAINLOOP;死循環
MAINNEXT:
MOV A,#LOW(MAINPROC)
PUSH ACC
MOV A,#HIGH(MAINPROC)
PUSH ACC
RETI
;-------主程序初始化------------------------
MAININIT:
;-------接口初始化--------------------------
;-------內存初始化-------------------------
MOV A,HotPower_55H
XRL A,HotPower_AAH
CPL A
JZ MAININITNEXT;內存未破壞
MOV HotPower_55H,#055H
MOV HotPower_AAH,#0AAH
LCALL SYSTEMINIT;系統初始化
MAININITNEXT:
;-------運行初始化---------------
LCALL SYSTEMSETUP;系統設置
RET
SYSTEMINIT:
LCALL KEYBUFFINIT
RET
SYSTEMSETUP:
;-------系統主頻12MHz---------------------------------
; MOV IP,#00100001B;中斷優先級EX0>ET2>ET0>EX1>ES
MOV TMOD,#00010010B;T1=MODE1(16位定時器),T0=MODE2(8位定時器)
MOV TCON,#01010101B;啟動定時器TR1EQUTR0EQU1,IT1EQUIT0EQU1
;------------------------------------------------------
MOV TL0,#TIME208US;設置定時器0時間常數
MOV TH0,#TIME208US;設置定時器0時間常數
;------------------------------------------------------
; MOV TL1,#LOW(TIMEXMS);設置定時器1時間常數
; MOV TH1,#HIGH(TIMEXMS)
;-------
KEYBUFFINIT:
MOV KEYNUM,#00H
MOV R0,#KEYBUFF1
KEYBUFFINITLOOP:
MOV @R0,#00H
INC R0
CJNE R0,#KEYBUFF2+12,KEYBUFFINITLOOP
RET
;---------------------------------------------
INKEY:
;T0每中斷1次,將進行1次鍵"掃描"
LCALL TESTKEY;鍵盤測試(不掃但描)
;-------鍵盤軟仿真測試點-----------------
;在此 A=0 無鍵壓下,A<>0有鍵壓下
;若調試n個鍵,需將KEYCOUNT設置為n.(KEYCOUNT=1~96)
;----------------------------------------
JNZ INKEY1;有鍵壓下
INKEY0:
;-------無鍵壓下------------------------
LCALL GETKEYBIT;取鍵狀態
JZ INKEY01;鍵狀態未發生變化
LCALL CLRKEYBIT;設置放鍵標志
LCALL SETKEYBITK;設置跳變標志(防止放鍵抖動)
RET
INKEY01:
LCALL GETKEYBITK;取鍵跳變標志
JZ INKEY02;鍵未發生跳變(防止2次事件處理)
LCALL CLRKEYBITX;設置重入標志
MOV A,KEYNUM;取鍵號
MOV DPTR,#KEYJMPPROCTABX;鍵盤放鍵事件處理表
LCALL KEYPROC;執行鍵盤放鍵事件處理
INKEY02:
RET
INKEY1:
;-------有鍵壓下------------------------
LCALL GETKEYBIT;取鍵狀態
JNZ INKEY11;鍵狀態未發生變化(防止2次事件處理)
LCALL SETKEYBIT;設置壓鍵標志
LCALL SETKEYBITK;設置跳變標志(防止壓鍵抖動)
RET
INKEY11:
LCALL GETKEYBITK;取鍵跳變標志
JZ INKEY12;鍵未發生跳變
LCALL CLRKEYBITX;設置重入標志
MOV A,KEYNUM;取鍵號
MOV DPTR,#KEYJMPPROCTAB;鍵盤壓鍵事件處理表
LCALL KEYPROC;執行鍵盤壓鍵事件處理
INKEY12:
RET
GETKEYBITK:
MOV A,R0
ADD A,#12
MOV R0,A
SJMP GETKEYBITX
GETKEYBIT:
LCALL GETKEYBITADDR
LCALL GETKEYBITVAL
GETKEYBITX:
MOV A,@R0
ANL A,B
RET
SETKEYBITK:
MOV A,R0
ADD A,#12
MOV R0,A
SJMP SETKEYBITX
SETKEYBIT:
LCALL GETKEYBITADDR
LCALL GETKEYBITVAL
SETKEYBITX:
MOV A,@R0
ORL A,B
MOV @R0,A
RET
CLRKEYBITK:
MOV A,R0
ADD A,#12
MOV R0,A
SJMP CLRKEYBITX
CLRKEYBIT:
LCALL GETKEYBITADDR
LCALL GETKEYBITVAL
CLRKEYBITX:
MOV A,@R0
XRL B,#0FFH;取反B
ANL A,B
XRL B,#0FFH;還原B
MOV @R0,A
RET
;-----------------------------------
;CPLKEYBITK:
; MOV A,R0
; ADD A,#12
; MOV R0,A
; SJMP CPLKEYBITX
;CPLKEYBIT:
; LCALL GETKEYBITADDR
; LCALL GETKEYBITVAL
;CPLKEYBITX:
; MOV A,@R0
; XRL A,B
; MOV @R0,A
; RET
;---------------------------------------------
GETKEYBITVAL:
MOV A,KEYNUM
ANL A,#07H
ADD A,#GETKEYBITTAB-GETKEYBITTABOFF
MOVC A,@A+PC
GETKEYBITTABOFF:
MOV B,A
RET
GETKEYBITTAB:
DB 00000001B
DB 00000010B
DB 00000100B
DB 00001000B
DB 00010000B
DB 00100000B
DB 01000000B
DB 10000000B
RET
;----------------------------------------------
GETKEYBITADDR:
MOV A,KEYNUM
ANL A,#01111000B
RR A
RR A
RR A
ADD A,#KEYBUFF1
MOV R0,A
RET
;-------鍵測試子程序--------------------------
TESTKEY:
;鍵號KEYNUM=000 0000B~101 1111B(0~95)
;入口 無
;出口 ACC==0 無鍵壓下(鍵號KEYNUM)
; ACC<>0 有鍵壓下(鍵號KEYNUM)
MOV A,KEYNUM;取鍵號
ANL A,#0FH;取行號(鍵號低4位)
ANL P3,#0F0H;清行信號
ORL P3,A;發送行掃描信號DCBA;P3.3~P3.0
MOV A,KEYNUM;取鍵號
ANL A,#01110000B;取列號(鍵號高3位)
SWAP A;變換到低3位
ADD A,#TESTKEYTAB-TESTKEYTABOFF;得到表地址
MOVC A,@A+PC;取列表值
TESTKEYTABOFF:
JZ TESTKEYEXIT;6,7非法列,認為無鍵壓下
PUSH B;保護現場
MOV B,A;暫存
ANL A,P1;接收列值P1.7~P1.2,有鍵壓下為0
XRL A,B;有鍵壓下非0
POP B;恢復現場
TESTKEYEXIT:
RET
TESTKEYTAB:
DB 00000100B;0列
DB 00001000B;1列
DB 00010000B;2列
DB 00100000B;3列
DB 01000000B;4列
DB 10000000B;5列
DB 00000000B;6列非法
DB 00000000B;7列非法
;-------定時器T0中斷服務程序--------------------
;每個鍵20mS掃描1次,并自動進行壓鍵或放鍵消抖處理
;這是1個大規模(96鍵)的鍵盤游擊戰的非典戰例
;特點:
;1.不需鍵掃描.(T0中斷的次序即為鍵掃描號)
;2.不需鍵消抖.(在T0中斷96次后自動消抖)
;3.壓鍵放鍵事件分離(散轉回收技術)
;4.用戶事件"并行處理"(mS級分時)
T0INTPROC:
PUSH PSW
PUSH ACC
PUSH B
PUSH DPL
PUSH DPH
T0INTPROC_START:
LCALL INKEY;鍵掃描并執行壓放鍵事件處理
INC KEYNUM;準備下一鍵號(T0中斷計數)
MOV A,KEYNUM
CJNE A,#KEYCOUNT,T0INTPROC_EXIT
MOV KEYNUM,#00H;開始下1輪鍵掃描
T0INTPROC_EXIT:
POP DPH
POP DPL
POP B
POP ACC
POP PSW
RETI
;-------定時器T1中斷服務程序------------
T1INTPROC:
RETI
;-------0鍵壓鍵事件處理---------------------
KEYPROC0:
;在此添加用戶壓鍵事件
RET
;-------1鍵壓鍵事件處理---------------------
KEYPROC1:
;在此添加用戶壓鍵事件
RET
;-------2鍵壓鍵事件處理---------------------
KEYPROC2:
;在此添加用戶壓鍵事件
RET
;-------95鍵壓鍵事件處理---------------------
KEYPROC95:
;在此添加用戶壓鍵事件
RET
;-------0鍵放鍵事件處理---------------------
KEYPROC0X:
;在此添加用戶放鍵事件
RET
;-------1鍵放鍵事件處理---------------------
KEYPROC1X:
;在此添加用戶放鍵事件
RET
;-------2鍵放鍵事件處理---------------------
KEYPROC2X:
;在此添加用戶放鍵事件
RET
;-------95鍵放鍵事件處理---------------------
KEYPROC95X:
;在此添加用戶放鍵事件
RET
;-------全部程序結束--------------------------------------
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -