彙編語言--鍵盤掃描及顯示實驗(含代碼解釋)

實驗題目

將8255單元與鍵盤及數碼管顯示單元連接,編寫實驗程序,掃描鍵盤輸入,並將掃描結果送數碼管顯示。鍵盤採用4X4鍵盤,每個數碼管顯示值可爲0-F共16個數。

實驗具體內容如下:
將鍵盤進行編號,記作0~F,當按下其中一一個按鍵時,將該按鍵對應的編號在一一個數碼管上顯示出來,當再按下一個按鍵時,便將這個按鍵的編號在下-一個數碼管上顯示出來,數碼管上可以顯示最近4次按下的按鍵編號。

電路圖

在這裏插入圖片描述

實驗代碼

;=======================================================
; 文件名: Keyscan.asm
; 功能描述: 鍵盤及數碼管顯示實驗,通過8255控制。
;     8255的 B口控制數碼管的段顯示,
;            A口控制鍵盤列掃描及數碼管的位驅動,
;            C口控制鍵盤的行掃描。
;     按下按鍵,該按鍵對應的位置將按順序顯示在數碼管上。
;=======================================================

IOY0         EQU   0600H          ;片選IOY0對應的端口始地址
MY8255_A     EQU   IOY0+00H*2     ;8255的A口地址
MY8255_B     EQU   IOY0+01H*2     ;8255的B口地址
MY8255_C     EQU   IOY0+02H*2     ;8255的C口地址
MY8255_CON   EQU   IOY0+03H*2     ;8255的控制寄存器地址

SSTACK	SEGMENT STACK
		DW 16 DUP(?)
SSTACK	ENDS		

DATA  	SEGMENT

; DATBLE是 將需要輸入按鍵的值對應需要給的顯示器的值
; 比如按鍵1表示的值是1 但是我們送給顯示器的是06H
; 該程序是通過判斷按鍵按下 獲取其代表的偏移量(相對於DTABLE)
; 比如按鍵1的偏移量是1 我們掃描按鍵 得出一個值 1
; 然後利用該值在DTABLE中找到需要輸出值的對應顯示代碼值
; 從B口送出去即可

DTABLE	DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H
		DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
DATA  	ENDS

CODE 	SEGMENT
      	ASSUME CS:CODE,DS:DATA
START:
		
		MOV AX,DATA
		MOV DS,AX
 		
 		; 把3000H--3005H中的值全部初始化爲00H
 		; 說明初始偏移量全爲0(3000H--3005H)
 		MOV SI,3000H
		MOV AL,00H
		
		MOV [SI],AL					;清顯示緩衝
		MOV [SI+1],AL
		MOV [SI+2],AL
		MOV [SI+3],AL
		MOV [SI+4],AL
		MOV [SI+5],AL
		
		
		MOV DI,3005H
		
		MOV DX,MY8255_CON			;8255控制字初始化
		MOV AL,81H					;1000 0001    A、B口輸出 C口輸入
		OUT DX,AL

BEGIN:	
		; 調用顯示子程序 
		CALL DIS			
		
		;清屏	
		CALL CLEAR					
		
		;掃描 看是否有鍵按下
		CALL CCSCAN					
		
		;有鍵按下 跳INK1
		JNZ INK1       
		
		JMP BEGIN

INK1:	
 		CALL DIS
		CALL DALLY
		CALL DALLY
		CALL CLEAR
		CALL CCSCAN
		
		; 若結果不爲0 ZF=0 則說明一定有鍵按下 則跳轉 判斷哪個鍵按下
		JNZ INK2					
		JMP BEGIN
		
		;確定按下鍵的位置
INK2:	
		MOV CH,0FEH 	; FEH=1111 1110(對應關係:PA7 PA6..PA1 PA0 ) 
                    	; PA5-PA0=1111 10 (這裏對應關係要弄明白)     
                    	;PA0對應的按鍵則是 從左到右第一列(這裏不會暈哦)                  
		MOV CL,00H      ; 初始對於行的偏移量 爲0 

		;列循環 即掃描列 從第一列開始
COLUM:	
		MOV AL,CH
		MOV DX,MY8255_A 
		OUT DX,AL   
		
		MOV DX,MY8255_C 
		IN AL,DX
L1:		TEST AL,01H         			;is L1?
		JNZ L2
		MOV AL,00H          			;L1
		JMP KCODE
L2:		TEST AL,02H         			;is L2?
		JNZ L3
		MOV AL,04H          			;L2
		JMP KCODE
L3:		TEST AL,04H         			;is L3?
		JNZ L4
		MOV AL,08H          			;L3
		JMP KCODE
L4:		TEST AL,08H         			;is L4?
		JNZ NEXT
		MOV AL,0CH          			;L4

; 找到按鍵後 此時AL存的的第一列每一行的初始值 0 4 8 C
; CL 存的是對應行的偏移量
; 假設 AL爲08H CL爲2 則表示的總偏移量爲 8+2=10H
; 說明在table中該數字的偏移量爲10H
; 輸出該數字 利用偏移量就行 因爲數字其實是存在table中的
KCODE:	ADD AL,CL
		CALL PUTBUF
		PUSH AX
KON: 	CALL DIS
		CALL CLEAR
		CALL CCSCAN
		JNZ KON
		POP AX
NEXT:	INC CL  ; CL相當於 行偏移量
		MOV AL,CH
		TEST AL,08H 	; 08H=0000 1000 當AL爲1111 0111 && 0000 1000 結果爲0 
		             	; ZF=1 說明行偏移量達到最大值 3
		JZ KERR 		;  4次列循環結束 跳KERR
		ROL AL,1
		MOV CH,AL
		JMP COLUM
KERR:	JMP BEGIN


; 鍵盤掃描子程序
; 原理是 先向全部列輸出低電平
; 然後從C口讀入 行電平
; 如果沒有按鍵按下 所有行應該均爲高電平 
; 反之 若有按鍵按下 則開始仔細判斷出到底是哪個按鍵按下 具體判斷方法是:
; 先向第一列輸出低電平(從左到右)
; 然後從C口讀入行電平 利用 AND 
; 判斷哪一行是否爲低電平即可(後面爲了計算方便取反了行電平)
; 若行全爲高 爲開始向下一列輸出低電平 循環4次即可
CCSCAN:	MOV AL,00H	 				
		MOV DX,MY8255_A  
		OUT DX,AL		; 向所有列輸出 低電平
		MOV DX,MY8255_C 
		IN  AL,DX       ;讀所有行電平
		
		;原來沒有任何鍵按下 4行全爲1
		;這裏取反 變成 0000 便於後面的判斷
		NOT AL
		
		; 假設沒有按鍵按下 
	 	; 0000&1111=0
		; 結果爲0 ZF=1 
		AND AL,0FH
		RET

;清屏子程序
;就是使得所有的燈熄滅 00H表示全不亮 瞬間 很快 
CLEAR:	MOV DX,MY8255_B 			
		MOV AL,00H
		OUT DX,AL
		RET


; 顯示子程序 (這裏稍微有點繞)
DIS:	PUSH AX					
		MOV SI,3000H
		
		; 0DFH=1101 1111 對應PA7 PA6 PA5...PA1 PA0
		; 由電路圖 得出 X1-PA0 X2-PA1.....
		; 6個顯示器 從左到右依次是 X1 X2 X3... X5 X6
		; 所以 對應的PA:          PA0 PA1 PA2...PA4 PA5
		; 這裏初始是0DFH   代表    1  1 1 1 1 0 
		; 意思是 第六個顯示 開始顯示數字
		; 哈哈 這裏其實是從X6到X1依次顯示的
		; 每個數字顯示間隔很快 我們會認爲是6個數字一起顯示 其實是逐個顯示
		MOV DL,0DFH
		MOV AL,DL

AGAIN:	PUSH DX
		; 把AL送給A口 覺得開放哪個燈 (這裏要看電路圖 A口也控制燈的開放)
		MOV DX,MY8255_A 
		OUT DX,AL
		
		
		MOV AL,[SI]  				; 把3000H--3005H中存的偏移量(相對)取出
		MOV BX,OFFSET DTABLE		; 獲取DTABLE的首地址
		AND AX,00FFH           		;因爲後面會有加法運算 先把ah清0 這樣ax就是						 
									; al的值,防止出錯
		ADD BX,AX                   ; 獲取需要的值的偏移量(這個是絕對偏移量)
		MOV AL,[BX]         		; 獲取顯示數字需要的值 例 顯示0需要3FH
	
		MOV DX,MY8255_B   			; 送往B口 顯示數字
		OUT DX,AL
	
		CALL DALLY 					;延時
		INC SI              		;移動SI 讀取下一個偏移量
		POP DX
		MOV AL,DL					; DL: 控制哪個燈的開放 開始是0DF 1101 1111
									; 取後6位(看電路圖 只連了6根線)即01 1111
									; 賦值給AL
		TEST AL,01H            		; 測試AL 看是否爲11 1110 
									; 6個燈 一次顯示需要循環6次
									; 這裏第六次結束是 AL=11 1110
									; 對於燈 就是x1燈顯示完(燈:X6->X1)
		JZ  OUT1 					; 6次循環完成後 跳出
		ROR AL,1					; 循環右移
									; 例 第一個燈亮 AL=01 1111 
									;  則 第二個燈亮 爲 10 1111
									;  所以需要循環右移
									;  反映在燈上 則是左移(不要繞進去了哦)
		MOV DL,AL
		JMP AGAIN           		; 跳回 繼續顯示 需循環6次
OUT1:	POP AX
		RET

; 子程序 延時作用 RET爲子程序結束標記
DALLY:	PUSH CX						
		MOV CX,0006H
T1:		MOV AX,009FH
T2:		DEC AX
		JNZ T2
		LOOP T1
		POP CX
		RET

; 將獲得的偏移量存入3000H--30005H中
; 便於後面的顯示 
; 顯示其實就是從3000H--3005H中讀取偏移量
; 然後在table中找到真正的值即可
PUTBUF:	MOV SI,DI					;存鍵盤值到相應位的緩衝中
		MOV [SI],AL  ;先存入地址3005H 再遞減 也就是下一個存入偏移量的是3004H
		DEC DI
		CMP DI,2FFFH
		JNZ GOBACK
		MOV DI,3005H
GOBACK:	RET

CODE	ENDS
		END START

更多

獲取更多資料、代碼,微信公衆號:海轟Pro
回覆 海轟 即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章