96个key的零延时收集
HotPower 宣布于 2003-11-5 18:04 侃单片机 ←回来版面
;——-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
|