沒人幫忙解決嘛,自己想辦法解決了一些問題,不會顯示亂碼了,也去掉了用二極管顯示行列狀態(tài)的部分,不過又遇到了新的問題,就是硬件仿真執(zhí)行程序的時候只能連續(xù)按下4到5個鍵并正常顯示,之后再按其他鍵就沒反應(yīng)了,好像死了似的,想不通,現(xiàn)將程序貼出來,希望有人幫忙分析,謝謝!
;*****************************************************
;矩陣鍵盤的識別,檢測是否有按鍵按下,并將其
;鍵號通過LED數(shù)碼管顯示出來
;*****************************************************
ORG 0000H
AJMP MAIN
ORG 0100H
MAIN : MOV 31H,#00H
MOV 30H,#00H
ACALL KEY ;調(diào)用鍵盤掃描子程序
ACALL SHOW0;調(diào)用判斷按鍵鍵號即數(shù)碼管顯示子程序
AJMP MAIN
;************************************************************
;按鍵掃描子程序KEY
;************************************************************
KEY: MOV P1,#0FH; P1口低四位作輸入端,置1,高四位清0
MOV A,P1 ; 讀P1口到累加器A
ANL A,#0FH ; 屏蔽高四位
XRL A,#0FH ; (A)與0FH相異或
JNZ HKEY; 判斷是否有按鍵按下,有,轉(zhuǎn)到按鍵去抖子程序
AJMP KEY ; 沒有,返回繼續(xù)掃描
HKEY : LCALL DELAY10ms;調(diào)用延時10ms子程序
MOV A,P1 ; 再讀P1口
ANL A,#0FH ; 屏蔽高四位
MOV 30H,A ; 將行線狀態(tài)放30H單元低四位寄存
XRL A,#0FH ; (A)與0FH相異或
JNZ WKEY ; 判斷是否真的有鍵按下,若是,轉(zhuǎn)到判斷哪個按鍵按下子程序
AJMP KEY ; 若不是,則返回繼續(xù)掃描
WKEY : ; 判斷列線狀態(tài)
MOV P1,#0F0H ; P1口高四位作輸入端,置1,低四位清0
MOV A,P1 ; 讀P1口到累加器A
ANL A,#0F0H ; 屏蔽低四位
MOV 31H,A ; 將列線狀態(tài)放入31H暫存
XRL A,#0F0H ;
JZ KEY ; 再次判斷按鍵狀態(tài),增強識別的可*性
MOV A,31H ; 將列線狀態(tài)送回A
ORL A,30H ; 將行列狀態(tài)合并
MOV 30H,A ; 放入30H
ACALL DELAY10ms; 調(diào)用延時10ms子程序
RE: MOV A,P1 ; 再讀入P1口狀態(tài)
CJNE A,#0F0H,RE; 判斷按鍵是否釋放了,沒有,則等待釋放
RET ; 若釋放了,則返回
;到這邊為止經(jīng)過測試是沒有問題的,讀出的行列狀態(tài)即30H中的內(nèi)容是正確的,就是執(zhí)行后面的程序不知道為什么會出問題。。。!
;***************************************************************
;判斷按鍵的鍵號及數(shù)碼管顯示子程序SHOW0
;**************************************************************
SHOW0:
L1: MOV A,30H ;將檢測到得按鍵行列狀態(tài)送到A
XRL A,#77H ;(A)與77H(01110111)相異或
JNZ L2 ;判斷是否是第16個鍵按下,若不是,轉(zhuǎn)到L2判斷是否是第15個鍵按下
MOV A,#0FH ;若是,則將鍵號送入A
ACALL SHOW0_1;調(diào)用數(shù)碼管顯示子程序
L2: MOV A,30H ;...............................
XRL A,#0B7H ;..............................
JNZ L3
MOV A,#0EH
ACALL SHOW0_1
L3: MOV A,30H
XRL A,#0D7H
JNZ L4
MOV A,#0DH
ACALL SHOW0_1
L4: MOV A,30H
XRL A,#0E7H
JNZ L5
MOV A,#0CH
ACALL SHOW0_1
L5: MOV A,30H
XRL A,#7BH
JNZ L6
MOV A,#0BH
ACALL SHOW0_1
L6: MOV A,30H
XRL A,#0BBH
JNZ L7
MOV A,#0AH
ACALL SHOW0_1
L7: MOV A,30H
XRL A,#0DBH
JNZ L8
MOV A,#09H
ACALL SHOW0_1
L8: MOV A,30H
XRL A,#0EBH
JNZ L9
MOV A,#08H
ACALL SHOW0_1
L9: MOV A,30H
XRL A,#7DH
JNZ L10
MOV A,#07H
ACALL SHOW0_1
L10: MOV A,30H
XRL A,#0BDH
JNZ L11
MOV A,#06H
ACALL SHOW0_1
L11: MOV A,30H
XRL A,#0DDH
JNZ L12
MOV A,#05H
ACALL SHOW0_1
L12: MOV A,30H
XRL A,#0EDH
JNZ L13
MOV A,#04H
ACALL SHOW0_1
L13:
MOV A,30H
XRL A,#7EH
JNZ L14
MOV A,#03H
ACALL SHOW0_1
L14: MOV A,30H
XRL A,#0BEH
JNZ L15
MOV A,#02H
ACALL SHOW0_1
L15: MOV A,30H
XRL A,#0DEH
JNZ L16
MOV A,#01H
ACALL SHOW0_1
L16: MOV A,30H
XRL A,#0EEH
JNZ L17 ;若檢測到均不是以上鍵號對應(yīng)的按鍵按下,則轉(zhuǎn)到L17返回主程序重新檢測
MOV A,#00H
ACALL SHOW0_1 ;.....................
L17:
AJMP MAIN
;********************************************************************************
;鍵號送數(shù)碼管顯示
;********************************************************************************
SHOW0_1: CLR P2.0
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
RET
DELAY10ms: MOV R6,#20 ;延時10ms子程序
LX0: MOV R7,#248h
DJNZ R7,$
DJNZ R6,LX0
RET
TAB: DB 0C0H,0F9H,0A4H,0B0H
DB 99H,92H,82H,0F8H
DB 80H,90H,88H,83H
DB 0C6H,0A1H,86H,8EH
END
哈哈,真慘,自己的問題還是要自己回答啊,問題已解決了,主要有兩個問題:
1、沒有關(guān)閉ADC、DAC時鐘通道數(shù)據(jù)寄存器。這是因為對自己實驗板還沒有完全學(xué)習(xí)掌握完,所以這是賣家?guī)椭鉀Q的,很欽佩賣家的服務(wù)態(tài)度!解決方法就是將其關(guān)閉唄:
ORG 0000H
AJMP MAIN1
ORG 0100H
MAIN1: CLR P2.2 ;關(guān)閉時鐘芯片
CLR P3.7;關(guān)閉數(shù)碼管以外的其他通道
SETB P2.2
MAIN : MOV 31H,#00H
MOV 30H,#00H
LCALL KEY ;調(diào)用鍵盤掃描子程序
LCALL SHOW0;調(diào)用判斷按鍵鍵號即數(shù)碼管顯示子程序
AJMP MAIN
……………
但僅僅這樣問題依然存在,下一個問題是什么呢?
2、子程序設(shè)計與堆棧技術(shù):在調(diào)用子程序的時候我沒有按照子程序的原則,最后一定以返回指令RET結(jié)束,而是用的AJMP指令,一種解決方法就是如賣家的建議,按子程序設(shè)計的原則來,以RET 結(jié)束,鍵盤掃描子程序無需修改,修改如下;
……………… …………
;****************************************************************
;判斷按鍵的鍵號及數(shù)碼管顯示子程序SHOW0
;**************************************************************
SHOW0:
L1: MOV A,30H ;將檢測到得按鍵行列狀態(tài)送到A
XRL A,#77H ;(A)與77H(01110111)相異或
JNZ L2 ;判斷是否是第16個鍵按下,若不是,轉(zhuǎn)到L2判斷是否是第15個鍵按下
MOV A,#0FH ;若是,則將鍵號送入A
ACALL SHOW0_1;調(diào)用數(shù)碼管顯示子程序
RET
L2: MOV A,30H ;...............................
XRL A,#0B7H ;..............................
JNZ L3
MOV A,#0EH
ACALL SHOW0_1
RET
L3: MOV A,30H
XRL A,#0D7H
JNZ L4
MOV A,#0DH
ACALL SHOW0_1
RET
L4: MOV A,30H
XRL A,#0E7H
JNZ L5
MOV A,#0CH
ACALL SHOW0_1
RET
L5: MOV A,30H
XRL A,#7BH
JNZ L6
MOV A,#0BH
ACALL SHOW0_1
RET
L6: MOV A,30H
XRL A,#0BBH
JNZ L7
MOV A,#0AH
ACALL SHOW0_1
RET
L7: MOV A,30H
XRL A,#0DBH
JNZ L8
MOV A,#09H
ACALL SHOW0_1
RET
L8: MOV A,30H
XRL A,#0EBH
JNZ L9
MOV A,#08H
ACALL SHOW0_1
RET
L9: MOV A,30H
XRL A,#7DH
JNZ L10
MOV A,#07H
ACALL SHOW0_1
RET
L10: MOV A,30H
XRL A,#0BDH
JNZ L11
MOV A,#06H
ACALL SHOW0_1
RET
L11: MOV A,30H
XRL A,#0DDH
JNZ L12
MOV A,#05H
ACALL SHOW0_1
RET
L12: MOV A,30H
XRL A,#0EDH
JNZ L13
MOV A,#04H
ACALL SHOW0_1
RET
L13: MOV A,30H
XRL A,#7EH
JNZ L14
MOV A,#03H
ACALL SHOW0_1
RET
L14: MOV A,30H
XRL A,#0BEH
JNZ L15
MOV A,#02H
ACALL SHOW0_1
RET
L15: MOV A,30H
XRL A,#0DEH
JNZ L16
MOV A,#01H
ACALL SHOW0_1
RET
L16: MOV A,30H
XRL A,#0EEH
JNZ L17 ;若檢測到均不是以上鍵號對應(yīng)的按鍵按下,則轉(zhuǎn)到L17返回主程序重新檢測
MOV A,#00H
ACALL SHOW0_1;.....................
L17: RET
;********************************************************************************
;鍵號送數(shù)碼管顯示
;********************************************************************************
SHOW0_1: CLR P2.0
MOV DPTR,#TAB
MOVC A,@A+DPTR
MOV P0,A
RET
DELAY10ms: MOV R6,#20 ;延時10ms子程序
LX0: MOV R7,#248
DJNZ R7,$
DJNZ R6,LX0
RET
TAB: DB 0C0H,0F9H,0A4H,0B0H
DB 99H,92H,82H,0F8H
DB 80H,90H,88H,83H
DB 0C6H,0A1H,86H,8EH
END
但究其原因,我為什么要用RET結(jié)束呢?總得有原因的吧,通過看書,思考,我認(rèn)為這應(yīng)該是堆棧的問題,因為在執(zhí)行調(diào)用子程序的指令時,也執(zhí)行了PUSH(壓入堆棧)指令,將數(shù)據(jù)壓入堆棧,而在子程序執(zhí)行完后,我用的AJMP指令,程序就直接跳到AJMP指定的地址去了,而壓入堆棧的數(shù)據(jù)還在堆棧中,與使用RET指令相比,少了一個POP(出棧)過程,所以每執(zhí)行一次調(diào)用子程序指令,就會往堆棧中壓入數(shù)據(jù),而堆棧SP是一個8為寄存器,在反復(fù)執(zhí)行幾次調(diào)用指令后,SP指針就到棧頂了,相當(dāng)于堆棧已壓經(jīng)滿了數(shù)據(jù),后面再執(zhí)行調(diào)用指令時,數(shù)據(jù)無法壓入堆棧,也就導(dǎo)致程序無法繼續(xù)執(zhí)行了,這就是為什么之后無論怎么按鍵都沒反應(yīng)的原因了,到這里,我想何不“將錯就錯”,直接在主程序中加一條設(shè)置堆棧的指令,當(dāng)然最好在每個子程序執(zhí)行完后設(shè)置一下堆棧,于是做出如下修改(紅色和綠色為修改的部分):
;*****************************************************
;矩陣鍵盤的識別,檢測是否有按鍵按下,并將其
;鍵號通過LED數(shù)碼管顯示出來
;*****************************************************
ORG 0000H
AJMP MAIN
ORG 0100H
MAIN : CLR P2.2;
clr p3.7;
SETB P2.2
MAIN1: mov sp,#07h
MOV 31H,#00H
MOV 30H,#00H
LCALL KEY ;調(diào)用鍵盤掃描子程序
LCALL SHOW0;調(diào)用判斷按鍵鍵號即數(shù)碼管顯示子程序
AJMP MAIN1
上述兩種修改方法均經(jīng)過實驗板調(diào)試,可以正常運行!但不知道我的解釋有沒有問題,還是希望有高人指點,謝謝!
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |