96-key zero-delay acquisition
HotPower Published on 2003-11-5 18:04 Talking about microcontrollers ← Back to the page
;-------96-key demonstration program-------------------------
;This is an application example in a reply question, which has been "verified" by software simulation
; This is just a "miniature" of key scanning technology, and there are too many methods.
;There are "ugly places", and experts are welcome to criticize and advise.
;HotPower will accept it humbly, resolutely correct it and make a new start.
;Purpose of publication: To strengthen the guerrillas in 21IC.
;----------------------------------------------------
;Due to the problem of 2051 resources, this program only takes the two events of the press and release keys of the multi-tasking keyboard
; Abolish the long press key event (press the key for a period of time before activation)
; Abolish the long release key event (release the key for a period of time before activation)
; Abolish the double-click key event
; Abolish any combination of key events
;----------Constant definition------------------------------
TIME208US EQU -208;20mS/96=208uS
TIME50MS EQU -5000;50000uS
;KEYCOUNT EQU 1; Number of keyboard keys (used in software simulation)
;------------------------------------------------
KEYCOUNT EQU 96; Number of keyboard keys (actual application)
;----------RAM address definition----------------------------
;--------96-key key status flag bit array Bits[12*8 bits]--------
KEYBUFF1 DATA 08H;08H~13H (12 bytes 96 bits) correspond to 96 keys
;--------96-key key jump flag bit array Bits[12*8 bits]--------
KEYBUFF2 DATA 14H;14H~1FH (12 bytes 96 bits) correspond to 96 keys
;------------------------------------------------
KEYNUM DATA 30H;
HotPower_55H DATA 6EH
HotPower_AAH DATA 6FH
;---------------------------------------
SP_MIN DATA HotPower_AAH
;-------Main program starts----------------------
ORG 0000H
START:
LJMP MAINSTART;Main program starts
ORG 0003H
;-------Power-off protection interrupt INT0 service program--------
INT0_INTADDR:
RETI
ORG 000BH
;-------Timer T0 interrupt service program------------
;Work in 8-bit automatic loading mode, interrupt once every 208uS T0_INTADDR
:
LJMP T0INTPROC;Timer T0 interrupt service programRETI
ORG 0013H
;-------External interrupt INT1 service program------------
INT1_INTADDR: RETI
ORG 001BH
;-------Timer T1 interrupt service program------------
T1_INTADDR: LJMP T1INTPROC;Timer T1 interrupt service programRETI ; ORG 0023H
;-------Serial interrupt service program----------------
;
SINT_INTADDR:
; RETI
;-------------------------------------------
; ORG 002BH
;-------Timer T2 interrupt service program------------
; LJMP T2INTPROC;Execute interrupt service program
; RETI
;-------Execute keyboard command----------------------
;This program uses the scattered transfer recovery technology (pointer function)
; its biggest advantage is that the subroutine at the scattered transfer location can be used by it (function)
; it is much more "guerrilla" than the JMP @A+DPTR instruction, and is much more flexible and hidden
; it is "worse" than JMP @A+DPTR in dealing with "disassembly"
; HotPower would never use JMP @A+DPTR
KEYPROC:
;Entrance: DPTR scattered transfer address table
; ACC scattered transfer number CJNE A,#KEYCOUNT,$+3 JNC KEYPROC_EXIT; illegal keys (96~255) prevent program flying, no scattered transfer RL A; *2; address requires 2 bytes (like ARM big-endian mode) ADD A,DPL MOV DPL,A CLR A ADDC A,DPH MOV DPH,A MOV A,#01H; low 8 bits MOVC A,@A+DPTR; take the low 8 bits address PUSH ACC; push the low 8 bits address CLR of event processing A; MOVC A, @A+DPTR; Get the high 8-bit address PUSH ACC; Push the high 8-bit address of the event processing
KEYPROC_EXIT: RET; Execute the keyboard command (JMP @A+DPTR)
;-------Key press event processing address table--------------------
KEYJMPPROCTAB:
DW KEYPROC0;0 key press
DW KEYPROC1
DW KEYPROC2
;............................
DW KEYPROC95;95 key press
;-------Key release event processing address table--------------------
KEYJMPPROCTABX:
DW KEYPROC0X;0 key release
DW KEYPROC1X
DW KEYPROC2X
;............................
DW KEYPROC95X;95 key release
MAINSTART:
;----------P0 port initialization------------------
MOV P0,#11111111B
;-------P1 port initialization------------------
MOV P1,#11111111B
;-------P2 port initialization------------------
MOV P2,#11111111B
;-------P3 port initialization------------------
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;System initialization
MOV IE,#10001010B;Open interrupt
;-------Main loop-------------------------------
MAINLOOP:
ORL PCON,#10001101B;Standby
SJMP MAINLOOP;Dead loop
MAINNEXT:
MOV A,#LOW(MAINPROC)
PUSH ACC
MOV A,#HIGH(MAINPROC)
PUSH ACC
RETI
;-------Main program initialization------------------------
MAININIT:
;-------Interface initialization--------------------------
;-------Memory initialization-------------------------
MOV A,HotPower_55H
XRL A,HotPower_AAH
CPL A
JZ MAININITNEXT;Memory is not destroyed
MOV HotPower_55H,#055H
MOV HotPower_AAH,#0AAH
LCALL SYSTEMINIT;System initialization
MAININITNEXT:
;-------Run initialization---------------
LCALL SYSTEMSETUP;System setup
RET
SYSTEMINIT:
LCALL KEYBUFFINIT
RET
SYSTEMSETUP:
;-------System main frequency 12MHz---------------------------------
; MOV IP,#00100001B;Interrupt priority EX0>ET2>ET0>EX1>ES
MOV TMOD,#00010010B;T1=MODE1(16-bit timer),T0=MODE2(8-bit timer)
MOV TCON,#01010101B;Start timer TR1EQUTR0EQU1,IT1EQUIT0EQU1
;------------------------------------------------------
MOV TL0,#TIME208US;Set timer 0 time constant
MOV TH0,#TIME208US;Set timer 0 time constant
;------------------------------------------------------
; MOV TL1,#LOW(TIMEXMS);Set timer 1 time constant
; MOV TH1,#HIGH(TIMEXMS)
;-------
KEYBUFFINIT:
MOV KEYNUM,#00H
MOV R0,#KEYBUFF1
KEYBUFFINITLOOP:
MOV @R0,#00H
INC R0
CJNE R0,#KEYBUFF2+12,KEYBUFFINITLOOP
RET
;---------------------------------------------
INKEY:
;Every time T0 is interrupted, a key "scan" will be performed
LCALL TESTKEY;Keyboard test (no scanning but description)
;-------Keyboard soft simulation test point-----------------
;Here A=0 No key is pressed, A<>0 has a key pressed
; if debugging n keys, KEYCOUNT needs to be set to n. (KEYCOUNT=1~96)
;----------------------------------------
JNZ INKEY1; A key is pressed
INKEY0:
;-------No key is pressed------------------------
LCALL GETKEYBIT; Get key status
JZ INKEY01; The key status has not changed
LCALL CLRKEYBIT; Set the key release flag
LCALL SETKEYBITK; Set the jump flag (to prevent key release jitter)
RET
INKEY01:
LCALL GETKEYBITK; Get the key jump flag
JZ INKEY02; The key has not jumped (to prevent double event processing)
LCALL CLRKEYBITX; Set the reentry flag
MOV A,KEYNUM; Get the key number
MOV DPTR,#KEYJMPPROCTABX; Keyboard key release event processing table
LCALL KEYPROC; Execute keyboard key release event processing
INKEY02:
RET
INKEY1:
;-------A key is pressed------------------------
LCALL GETKEYBIT;Get key status
JNZ INKEY11;The key status has not changed (to prevent double event processing)
LCALL SETKEYBIT;Set key pressed flag
LCALL SETKEYBITK;Set transition flag (to prevent key pressed jitter)
RET
INKEY11:
LCALL GETKEYBITK;Get key transition flag
JZ INKEY12;The key has not transitioned
LCALL CLRKEYBITX;Set reentry flag
MOV A,KEYNUM;Get key number
MOV DPTR,#KEYJMPPROCTAB;Keyboard key pressed event processing table
LCALL KEYPROC;Execute keyboard key pressed event processing
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; Negate B
ANL A,B
XRL B,#0FFH; restore 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 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
;-------Key test subroutine----------------- ---------
TESTKEY:
;Key number KEYNUM=000 0000B~101 1111B(0~95)
;Entry None
;Exit ACC==0 No key pressed (key number KEYNUM)
; ACC<>0 A key is pressed (key number KEYNUM) MOV A,KEYNUM; get key number ANL A,#0FH; get line number (lower 4 bits of key number) ANL P3,#0F0H; clear line signal ORL P3,A; send line scan signal DCBA; P3.3~P3.0 MOV A,KEYNUM; get the key number ANL A,#01110000B; get the column number (the upper 3 bits of the key number) SWAP A; change to the lower 3 bits ADD
A,#TESTKEYTAB-TESTKEYTABOFF; get the table address
MOVC A,@A+PC; get the table value
TESTKEYTABOFF:
JZ TESTKEYEXIT; 6,7 illegal columns, it is considered that no key is pressed
PUSH B; protect the scene
MOV B,A; temporarily store
ANL A,P1; receive column values P1.7~P1.2, if a key is pressed, it is 0
XRL A,B; if a key is pressed, it is not 0
POP B; restore the scene
TESTKEYEXIT:
RET
TESTKEYTAB:
DB 00000100B; 0 column
DB 000010000B; 1 column
DB 00010000B; 2 column
DB 00100000B; 3 column
DB 01000000B; 4 column
DB 10000000B; 5 column
DB 00000000B; 6 column illegal
DB 00000000B;7 columns are illegal
;-------Timer T0 interrupt service program--------------------
;Each key is scanned once every 20ms, and the key pressing or releasing is automatically debounced
;This is an atypical example of a large-scale (96-key) keyboard guerrilla war
;Features:
;1. No key scanning is required. (The order of T0 interrupt is the key scan number)
;2. No key debounce is required. (The key is automatically debounced after 96 T0 interrupts)
;3. Separation of key pressing and releasing events (scattered transfer recovery technology)
;4. "Parallel processing" of user events (mS level time sharing)
T0INTPROC:
PUSH PSW
PUSH ACC
PUSH B
PUSH DPL
PUSH DPH
T0INTPROC_START:
LCALL INKEY;Key scan and execute key pressing and releasing event processing
INC KEYNUM;Prepare for the next key number (T0 interrupt count)
MOV A,KEYNUM
CJNE A,#KEYCOUNT,T0INTPROC_EXIT
MOV KEYNUM,#00H; Start the next round of key scan
T0INTPROC_EXIT:
POP DPH
POP DPL
POP B
POP ACC
POP PSW
RETI
;------Timer T1 interrupt service program------------
T1INTPROC:
RETI
;-------0 key press event processing---------------------
KEYPROC0:
;Add user key press event
hereRET
;-------1 key press event processing---------------------
KEYPROC1:
;Add user key press event
hereRET
;-------2 key press event processing---------------------
KEYPROC2:
;Add user key press event
hereRET
;-------95 key press event processing---------------------
KEYPROC95:
;Add user key press event
hereRET
;-------0 key release event processing---------------------
KEYPROC0X:
;Add user key release event hereRET
;
-------1 key release event processing---------------------
KEYPROC1X:
;Add user key release event here
RET
;-------2 key release event processing---------------------
KEYPROC2X:
;Add user key release event here
RET
;-------95 key release event processing---------------------
KEYPROC95X:
;Add user key release event here
RET
;-------All programs end--------------------------------------
END
|