96個(gè)key的零延時(shí)采集
HotPower 發(fā)表于 2003-11-5 18:04 侃單片機(jī) ←返回版面 ;-------96鍵演示程序------------------------- ;這是1個(gè)回復(fù)題中的應(yīng)用示例,已通過(guò)軟仿真“驗(yàn)證” ;這只是鍵掃描技術(shù)的1個(gè)“縮影”,方法實(shí)在太多. ;有“難看之處”,敬請(qǐng)高手們批評(píng)指教. ;HotPower將虛心接受,堅(jiān)決改正.重新做人. ;發(fā)表目的: 在21IC中壯大游擊隊(duì). ;---------------------------------------------------- ;由于2051資源問(wèn)題,本程序只取多任務(wù)鍵盤(pán)的壓放鍵2個(gè)事件 ;廢除長(zhǎng)壓鍵(壓鍵1段時(shí)間后才激活)事件 ;廢除長(zhǎng)放鍵(放鍵1段時(shí)間后才激活)事件 ;廢除雙擊鍵事件 ;廢除任意組合鍵事件 ;----------常數(shù)定義------------------------------ TIME208US EQU -208;20mS/96=208uS TIME50MS EQU -5000;50000uS ;KEYCOUNT EQU 1;鍵盤(pán)鍵個(gè)數(shù)(軟仿真時(shí)用) ;------------------------------------------------ KEYCOUNT EQU 96;鍵盤(pán)鍵個(gè)數(shù)(實(shí)際應(yīng)用) ;----------RAM地址定義---------------------------- ;--------96鍵鍵狀態(tài)標(biāo)志位數(shù)組Bits[12*8位]-------- KEYBUFF1 DATA 08H;08H~13H(12個(gè)字節(jié)96位)對(duì)應(yīng)96鍵 ;--------96鍵鍵跳變標(biāo)志位數(shù)組Bits[12*8位]-------- KEYBUFF2 DATA 14H;14H~1FH(12個(gè)字節(jié)96位)對(duì)應(yīng)96鍵 ;------------------------------------------------ KEYNUM DATA 30H; HotPower_55H DATA 6EH HotPower_AAH DATA 6FH ;--------------------------------------- SP_MIN DATA HotPower_AAH ;-------主程序開(kāi)始---------------------- ORG 0000H START: LJMP MAINSTART;主程序開(kāi)始 ORG 0003H ;-------掉電保護(hù)中斷INT0服務(wù)程序-------- INT0_INTADDR: RETI ORG 000BH ;-------定時(shí)器T0中斷服務(wù)程序------------ ;工作在8位自動(dòng)裝載方式,每208uS中斷一次 T0_INTADDR: LJMP T0INTPROC;定時(shí)器T0中斷服務(wù)程序 RETI ORG 0013H ;-------外部中斷INT1服務(wù)程序------------ INT1_INTADDR: RETI ORG 001BH ;-------定時(shí)器T1中斷服務(wù)程序------------ T1_INTADDR: LJMP T1INTPROC;定時(shí)器T1中斷服務(wù)程序 RETI ; ORG 0023H ;-------串行中斷服務(wù)程序---------------- ;SINT_INTADDR: ; RETI ;------------------------------------------- ; ORG 002BH ;-------定時(shí)器T2中斷服務(wù)程序------------ ; LJMP T2INTPROC;執(zhí)行中斷服務(wù)程序 ; RETI ;-------執(zhí)行鍵盤(pán)命令---------------------- ;本程序利用散轉(zhuǎn)回收技術(shù)(指針函數(shù)) ;它的最大優(yōu)點(diǎn)是散轉(zhuǎn)處的子程序可被它用(函數(shù)) ;它比JMP @A+DPTR指令要“游擊”很多,靈活和隱蔽了許多 ;它在對(duì)付“反匯編”方面,比JMP @A+DPTR更“壞” ;HotPower打死也不用JMP @A+DPTR KEYPROC: ;入口: DPTR散轉(zhuǎn)地址表 ; ACC 散轉(zhuǎn)號(hào) CJNE A,#KEYCOUNT,$+3 JNC KEYPROC_EXIT;非法鍵(96~255)防止程序飛,不散轉(zhuǎn) RL A;*2;地址需要2字節(jié)(像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;執(zhí)行鍵盤(pán)命令(散轉(zhuǎn)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;系統(tǒng)初始化 MOV IE,#10001010B;開(kāi)中斷 ;-------主循環(huán)------------------------------- MAINLOOP: ORL PCON,#10001101B;待機(jī) SJMP MAINLOOP;死循環(huán) MAINNEXT: MOV A,#LOW(MAINPROC) PUSH ACC MOV A,#HIGH(MAINPROC) PUSH ACC RETI ;-------主程序初始化------------------------ MAININIT: ;-------接口初始化-------------------------- ;-------內(nèi)存初始化------------------------- MOV A,HotPower_55H XRL A,HotPower_AAH CPL A JZ MAININITNEXT;內(nèi)存未破壞 MOV HotPower_55H,#055H MOV HotPower_AAH,#0AAH LCALL SYSTEMINIT;系統(tǒng)初始化 MAININITNEXT: ;-------運(yùn)行初始化--------------- LCALL SYSTEMSETUP;系統(tǒng)設(shè)置 RET SYSTEMINIT: LCALL KEYBUFFINIT RET SYSTEMSETUP: ;-------系統(tǒng)主頻12MHz--------------------------------- ; MOV IP,#00100001B;中斷優(yōu)先級(jí)EX0>ET2>ET0>EX1>ES MOV TMOD,#00010010B;T1=MODE1(16位定時(shí)器),T0=MODE2(8位定時(shí)器) MOV TCON,#01010101B;啟動(dòng)定時(shí)器TR1EQUTR0EQU1,IT1EQUIT0EQU1 ;------------------------------------------------------ MOV TL0,#TIME208US;設(shè)置定時(shí)器0時(shí)間常數(shù) MOV TH0,#TIME208US;設(shè)置定時(shí)器0時(shí)間常數(shù) ;------------------------------------------------------ ; MOV TL1,#LOW(TIMEXMS);設(shè)置定時(shí)器1時(shí)間常數(shù) ; 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次,將進(jìn)行1次鍵"掃描" LCALL TESTKEY;鍵盤(pán)測(cè)試(不掃但描) ;-------鍵盤(pán)軟仿真測(cè)試點(diǎn)----------------- ;在此 A=0 無(wú)鍵壓下,A<>0有鍵壓下 ;若調(diào)試n個(gè)鍵,需將KEYCOUNT設(shè)置為n.(KEYCOUNT=1~96) ;---------------------------------------- JNZ INKEY1;有鍵壓下 INKEY0: ;-------無(wú)鍵壓下------------------------ LCALL GETKEYBIT;取鍵狀態(tài) JZ INKEY01;鍵狀態(tài)未發(fā)生變化 LCALL CLRKEYBIT;設(shè)置放鍵標(biāo)志 LCALL SETKEYBITK;設(shè)置跳變標(biāo)志(防止放鍵抖動(dòng)) RET INKEY01: LCALL GETKEYBITK;取鍵跳變標(biāo)志 JZ INKEY02;鍵未發(fā)生跳變(防止2次事件處理) LCALL CLRKEYBITX;設(shè)置重入標(biāo)志 MOV A,KEYNUM;取鍵號(hào) MOV DPTR,#KEYJMPPROCTABX;鍵盤(pán)放鍵事件處理表 LCALL KEYPROC;執(zhí)行鍵盤(pán)放鍵事件處理 INKEY02: RET INKEY1: ;-------有鍵壓下------------------------ LCALL GETKEYBIT;取鍵狀態(tài) JNZ INKEY11;鍵狀態(tài)未發(fā)生變化(防止2次事件處理) LCALL SETKEYBIT;設(shè)置壓鍵標(biāo)志 LCALL SETKEYBITK;設(shè)置跳變標(biāo)志(防止壓鍵抖動(dòng)) RET INKEY11: LCALL GETKEYBITK;取鍵跳變標(biāo)志 JZ INKEY12;鍵未發(fā)生跳變 LCALL CLRKEYBITX;設(shè)置重入標(biāo)志 MOV A,KEYNUM;取鍵號(hào) MOV DPTR,#KEYJMPPROCTAB;鍵盤(pán)壓鍵事件處理表 LCALL KEYPROC;執(zhí)行鍵盤(pán)壓鍵事件處理 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 ;-------鍵測(cè)試子程序-------------------------- TESTKEY: ;鍵號(hào)KEYNUM=000 0000B~101 1111B(0~95) ;入口 無(wú) ;出口 ACC==0 無(wú)鍵壓下(鍵號(hào)KEYNUM) ; ACC<>0 有鍵壓下(鍵號(hào)KEYNUM) MOV A,KEYNUM;取鍵號(hào) ANL A,#0FH;取行號(hào)(鍵號(hào)低4位) ANL P3,#0F0H;清行信號(hào) ORL P3,A;發(fā)送行掃描信號(hào)DCBA;P3.3~P3.0 MOV A,KEYNUM;取鍵號(hào) ANL A,#01110000B;取列號(hào)(鍵號(hào)高3位) SWAP A;變換到低3位 ADD A,#TESTKEYTAB-TESTKEYTABOFF;得到表地址 MOVC A,@A+PC;取列表值 TESTKEYTABOFF: JZ TESTKEYEXIT;6,7非法列,認(rèn)為無(wú)鍵壓下 PUSH B;保護(hù)現(xiàn)場(chǎng) MOV B,A;暫存 ANL A,P1;接收列值P1.7~P1.2,有鍵壓下為0 XRL A,B;有鍵壓下非0 POP B;恢復(fù)現(xiàn)場(chǎng) 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列非法 ;-------定時(shí)器T0中斷服務(wù)程序-------------------- ;每個(gè)鍵20mS掃描1次,并自動(dòng)進(jìn)行壓鍵或放鍵消抖處理 ;這是1個(gè)大規(guī)模(96鍵)的鍵盤(pán)游擊戰(zhàn)的非典戰(zhàn)例 ;特點(diǎn): ;1.不需鍵掃描.(T0中斷的次序即為鍵掃描號(hào)) ;2.不需鍵消抖.(在T0中斷96次后自動(dòng)消抖) ;3.壓鍵放鍵事件分離(散轉(zhuǎn)回收技術(shù)) ;4.用戶事件"并行處理"(mS級(jí)分時(shí)) T0INTPROC: PUSH PSW PUSH ACC PUSH B PUSH DPL PUSH DPH T0INTPROC_START: LCALL INKEY;鍵掃描并執(zhí)行壓放鍵事件處理 INC KEYNUM;準(zhǔn)備下一鍵號(hào)(T0中斷計(jì)數(shù)) MOV A,KEYNUM CJNE A,#KEYCOUNT,T0INTPROC_EXIT MOV KEYNUM,#00H;開(kāi)始下1輪鍵掃描 T0INTPROC_EXIT: POP DPH POP DPL POP B POP ACC POP PSW RETI ;-------定時(shí)器T1中斷服務(wù)程序------------ 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 ;-------全部程序結(jié)束-------------------------------------- END
|
評(píng)論