單片機鍵盤掃描程序(匯編)
;鍵盤掃描程序;此程序比較復雜,不過如果你堅持的理解下去的話,還是能夠理解的,比較經典
;最終是按鍵的值輸出到數碼管中(接在P2口)
ORG0000H
START:MOVR0,#00H;初始化程序,開始的延時是為了使硬件能夠準備好
DJNZR0,$
LOOP: MOVSP,#60H
CALLKEY
DISPLAY:
MOV A,R4
MOV DPTR,#TABLE ;定義字形表的起始地址
MOVC A,@A+DPTR ;TABLE為表的起始地址
MOV P2,A
SJMPLOOP
;子程序內容,P1口的第四位為行線,高四位為列線
KEY: PUSHPSW
PUSHACC
MOVP1,#0F0H ;令所有的行為低電平,全掃描字-P1.0-P1.3,列為輸入方式
;這一段只是驗證有鍵按下,并不能判斷是哪一行
MOVR7,#0FFH;設置計數常數,作為延時
KEY1:DJNZR7,KEY1
MOVA,P1;讀取P1口的列值
ANLA,#0F0H;判別有鍵值按下嗎(當有鍵按下時,P1口的高四位就不全為1了,底四位還是都為0的)
;這個地方進行相或的原因,是因為要把底四位的0000變成1111,以便下一步進行求反
ORLA,#0FH //這個地方原版上沒有,這是又加了,如果不加的的話,是不對的********
CPLA;求反后,有高電平就有鍵按下
JZEKEY;累加器為0則轉移(意為求反后本來全為0的,如果有鍵按下時,求反后高四位就有1了),退出
LCALLDEL20ms ;有鍵按下,進行處理
;下面進行行行掃描,1行1行掃
SKEY:MOVA,#00H
MOVR0,A ;R0作為行計數器,開始初值為0
MOVR1,A ;R1作為列計數器,開始初值為0
MOVR2,#0FEH ;R2作為掃描暫存字,開始初值為1111 1110,(第四位作為行掃描字)
SKEY2:MOVA,R2
MOVP1,A ;輸出行掃描字,1111 1110
NOP
NOP
NOP ;3個NOP操作使P1口輸出穩(wěn)定
MOVA,P1 ;讀列值(和開始一樣)
MOVR1,A ;暫存列值(第一次為**** 1110,既高四位有一位"可能"會為0)
ANLA,#0F0H ;取高四位,
ORLA,#0FH ;使第四位全部置1
CPLA
BIAOZHI:JNZSKEY3;累加器為非0則轉移指令(意思是判斷到按鍵在這一行),轉去處理
INCR0;如果按鍵沒在這一行,行計數器加1
SETBC;進位標志位加1,為了在左移的時候開始的低位0不在出現在低(循環(huán)一圈后)
MOVA,R2
RLCA;帶進位左移1位(形成下一行掃描字,再次掃描)
MOVR2,A
MOVA,R0
;把加1后的行計數器R0和總共掃描次數(4次比較)
CJNEA,#04H,SKEY2 ;(掃描完了么)書本上這個地方也有錯誤,書本上寫的是:SKEY1
AJMPEKEY ;如果沒有的話,退出
;有鍵按下后行掃描過后,此為確列行
SKEY3:MOVA,R1 ;
JNBACC.4,SKEY5 ;直接尋址位為0咋轉移指令
JNBACC.5,SKEY6
JNBACC.6,SKEY7
JNBACC.7,SKEY8
AJMPEKEY //我自己感覺到這命令沒有用處
SKEY5:MOVA,#00H ;存0列號
MOVR3,A
AJMPDKEY
SKEY6:MOVA,#01H ;存1列號
MOVR3,A
AJMPDKEY
SKEY7:MOVA,#02H ;存2列號
MOVR3,A
AJMPDKEY
SKEY8:MOVA,#03H ;存3列號
MOVR3,A
AJMPDKEY
;取出具體的行號,再加上列號,最終確認按鍵的號碼
DKEY://MOVR4,#00H
MOVA,R0
MOVB,#04H
MULAB;讓行號*4,第四位放在A中(總共就4行,相乘后一定<16,也就是只有第四位有值)
ADDA,R3;讓行號和列號相加,最終確認任按鍵的具體號
MOVR4,A
EKEY:POPACC
POPPSW
RET ;按鍵掃描處理函數
DEL20ms:
MOVR7,#2
DL2: MOVR6,#18
DL1: MOVR5,#255
DJNZR5,$
DJNZR6,DL1
DJNZR7,DL2
RET
;此為共陰極數碼管的數字表
TABLE: DB 3FH ;0
DB 06H ;1
DB 5BH ;2
DB 4FH ;3
DB 66H ;4
DB 6DH ;5
DB 7DH ;6
DB 27H ;7
DB 7FH ;8
DB 6FH ;9
DB77H
DB7CH
DB39H
DB5EH
DB79H
DB71H
END
評論