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;设置跳变标志(防止放键 |