新聞中心

按鍵的C51源程序

作者: 時(shí)間:2016-11-22 來(lái)源:網(wǎng)絡(luò) 收藏
8條口線24按鍵C51源程序

//鍵盤(pán)掃描處理,無(wú)按鍵返回0,有按鍵返回鍵值,鍵值對(duì)應(yīng)于keycode[]下標(biāo)值。8條(以P2為例)口線24按鍵
//鍵盤(pán)碼也可定義為局部數(shù)組變量
unsigned char code keycode[]=
{0x00,0xee,0xde,0xbe,0xed,0xdd,0xbd,0xeb,0xdb,0xbb,0xd7,0xe7,0xb7,0x7b,0x7d,0x7e,0x77,

本文引用地址:http://butianyuan.cn/article/201611/319618.htm

0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0x7f,0xbf};

unsigned char keyread(void)
{ unsigned char i,j,x,k1,k2;
P2=0xff;
if(P2!=0xff)
{k1=P2;
delay();
P2=0xff;
if(P2!=0xff)
{for(P2=0xff;P2!=0xff;P2=0xff)
x=k1;}
}
else{x=0;
}
//以上判斷接地按鍵
//以下判斷交叉按鍵(反轉(zhuǎn)法)
if(x==0)
{P2=0x0f;
if(P2!=0x0f)
{delay();
P2=0x0f;
if(P2!=0x0f)
{k1=P2;
P2=0xf0;
if(P2!=0xf0)
{k2=P2;
for(P2=0xf0;P2!=0xf0;P2=0xf0)
x=k1^k2;}
}
}
else{x=0;} }
if(x==0){i=0;}
else{i=j=0xff;
do{i++;j++;
if(keycode[i]==x){j=24;}
else if(j==24){i=0;}else{;} }

while(j!=24);}

return(i);
}

void delay()//延時(shí)
{ unsigned char b;
for (b=0;b<=0xff;b++)
{
for (b=0;b<=0xff;b++)
{;}
}
}



96個(gè)key的零延時(shí)采集
Juliet發(fā)表評(píng)論于2006-5-10 11:35:00

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



按鍵掃描驅(qū)動(dòng)程序
Juliet發(fā)表評(píng)論于2006-5-10 11:35:00

按鍵掃描驅(qū)動(dòng)程序


//按鍵掃描驅(qū)動(dòng)程序

unsigned char key,key_h,kpush;
unsigned int key_l;

//按鍵連接到p1.0、p1.1、p1.2

void int_t0(void) interrupt 1 {
unsigned char dd,i;
TL0=TL0+30;TH0=0xfb; //800

if ((P1&0x7)==0x7) {
if ((key_l>30)&&(key_l<800)&&(key_h>30)) { //釋放按鍵,如果之前按鍵時(shí)間少于1秒,讀入鍵值
key=kpush;
}
if ((++key_h)>200) key_h=200;
key_l=0;
if (key>=0x80) key=0; //如果之前的按鍵為長(zhǎng)按1秒,清除鍵值
} else {
kpush=P1&0x7;
key_l++;
if ((key_l>800)&&(key_h>30)) { //如果按鍵超過(guò)1秒,鍵值加0x80標(biāo)志長(zhǎng)按鍵
key=kpush|0x80;
key_h=0;
key_l=0;
}
}
}
void main(void) {
TMOD=0x1;TR0=1;ET0=1;EA=1;
while (1) {
while (!key) {}
switch (key) {
case 1:break;
case 2:break;
}
}
}




關(guān)鍵詞: 按鍵C51源程

評(píng)論


技術(shù)專區(qū)

關(guān)閉