Skip to content

[微机实验/TD-PITE] 键盘扫描及数码管显示实验

Published: at 15:58

ToC

实验内容

在数码管上显示键盘输入的内容,新输入的内容显示在数码管的最右侧。

当数码管显示空间已满时,删除最左侧的文本。

实验接线

这次的接线和上次是一样的。唯一的不同是不能不连 Y1-Y4 了(笑)

代码

A8255 EQU 0600H
B8255 EQU 0602H
C8255 EQU 0604H
CON8255 EQU 0606H
ROWOUT EQU 200H
SSEG SEGMENT STACK
DW 20 DUP(?)
SSEG ENDS
DATA SEGMENT
TBL:
DB 3FH ;; 0
DB 06H ;; 1
DB 5BH ;; 2
DB 4FH ;; 3
DB 66H ;; 4
DB 6DH ;; 5
DB 7DH ;; 6
DB 07H ;; 7
DB 7FH ;; 8
DB 6FH ;; 9
DB 77H ;; A
DB 7CH ;; B
DB 39H ;; C
DB 5EH ;; D
DB 79H ;; E
DB 71H ;; F
SEQ:
DB 00011111B ;; POS 0
DB 00101111B ;; POS 1
DB 00110111B ;; POS 2
DB 00111011B ;; POS 3
DB 00111101B ;; POS 4
DB 00111110B ;; POS 5
VAL:
DB 6 DUP(0)
VAL_USED:
DB 6 DUP(0)
VAL_HEAD DW 0005H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:SSEG
START PROC
MOV AX, DATA
MOV DS, AX
MOV AL, 81H ;;10001001B ;; A B OUT, C IN
MOV DX, CON8255
OUT DX, AL
MOV AX, 0000H
LO:
CALL VAL_DISPLAY
CALL SCAN
CMP AX, 10H
JE LO
CALL VAL_INSERT
WAIT_UP:
CALL VAL_DISPLAY
CALL KEY_PRESSED
CMP AX, 1
JE WAIT_UP
JMP LO
MOV AX, 4C00H
INT 21H
START ENDP
SCAN PROC
BEGIN:
CALL KEY_PRESSED ;; EXIT IF NOT PRESSED
CMP AX, 0
JE SCAN_NO_KEY
CALL DELAY
CALL KEY_PRESSED
CMP AX, 0
JE SCAN_NO_KEY
MOV CH, 0FEH
MOV CL, 0
COLUMN:
MOV AL, CH
MOV DX, A8255
OUT DX, AL
MOV DX, C8255
IN AL, DX
L1:
TEST AL, 1
JNZ L2
MOV AL, 00H
JMP KCODE
L2:
TEST AL, 2
JNZ L3
MOV AL, 04H
JMP KCODE
L3:
TEST AL, 4
JNZ L4
MOV AL, 08H
JMP KCODE
L4:
TEST AL, 8
JNZ NEXT
MOV AL, 0CH
KCODE:
ADD AL, CL
JMP SCAN_FIN
NEXT:
INC CL
MOV AL, CH
TEST AL, 08H
JE SCAN_NO_KEY
ROL AL, 1
MOV CH, AL
JMP COLUMN
SCAN_NO_KEY:
MOV AX, 10H
SCAN_FIN:
RET
SCAN ENDP
;; RETURN WHETHER KEY PRESSED IN AX
KEY_PRESSED PROC
MOV DX, A8255
MOV AL, 00H
OUT DX, AL ;; LINE OUTPUT 0000
MOV DX, C8255
IN AL, DX ;; GET LINE STATUS
AND AL, 0FH
CMP AL, 0FH
JE KP_NONE
MOV AX, 1 ;; KEY PRESSED
RET
KP_NONE:
MOV AX, 0
RET
KEY_PRESSED ENDP
;; INSERT AX TO VAL[VAL_HEAD]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INDEX: 0 1 2 3 4 5
;; VALUE: A B C D E F
;; HEAD: |
;; INPUT: 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INDEX: 0 1 2 3 4 5
;; VALUE: 0 B C D E F
;; HEAD: |
;; (-> 1 BYTE)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VAL_INSERT PROC
PUSH BX
LEA BX, VAL
MOV SI, VAL_HEAD
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; !!!CAUTION!!! ;;
;; MAKE SURE TO USE 8-BIT REGISTER ;;
;; IF YOU WANT TO MOVE BYTES ;;
;; BETWEEN MEMORY AND REGISTER!! ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV [BX+SI], AL ;; NUMBER BYTE
MOV DL, 1
MOV [BX+SI+6], DL ;; DISPLAY BYTE
INC SI
CMP SI, 5 ;; HEAD <= 5, SKIP
JLE VI_EXIT
SUB SI, 6 ;; MAKE HEAD IN [0, 5]
VI_EXIT:
MOV VAL_HEAD, SI
POP BX
RET
VAL_INSERT ENDP
;; DISPLAY VAL ARRAY
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INDEX: 0 1 2 3 4 5
;; VALUE: A B C D E F
;; HEAD: |
;; THIS IS THE SAME DIRECTION AS SCREEN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
VAL_DISPLAY PROC
PUSH CX
MOV CX, 6
LEA BX, VAL
MOV SI, VAL_HEAD
VD_LO:
PUSH CX
MOV AH, [BX+SI]
MOV AL, CL
DEC AL
MOV DH, [BX+SI+6]
CMP DH, 0
JE VD_SKIP_BIT
PUSH BX
PUSH SI
CALL PUT
CALL DELAY
POP SI
POP BX
VD_SKIP_BIT:
POP CX
;; CALCULATE NEXT SI
INC SI
CMP SI, 5 ;; HEAD <= 5, SKIP
JLE VD_SI_SKIP
SUB SI, 6
VD_SI_SKIP:
LOOP VD_LO
POP CX
RET
VAL_DISPLAY ENDP
;; NUM: AH
;; POS: AL
PUT PROC
PUSH AX
;; SELECT POS
LEA BX, SEQ
PUSH AX
MOV AH, 0
MOV SI, AX
;; OUTPUT POS
MOV DX, A8255
MOV AL, [BX+SI]
OUT DX, AL
POP AX
;; SELECT NUM
LEA BX, TBL
MOV AL, AH
MOV AH, 0
MOV SI, AX
;; OUTPUT DATA
MOV DX, B8255
MOV AL, [BX+SI]
OUT DX, AL
POP AX
RET
PUT ENDP
DELAY PROC
MOV CX, 0FFH
LOOP $
RET
DELAY ENDP
CODE ENDS
END START

选做实验

说明

通过键盘输入 0-E,将刚刚输入的一位数字显示在数码管上。

最开始数码管无显示。在输入新数字后,将输入的数字显示在数码管最右端。之后每次输入数字,数字的显示位置向左移动一格。

当显示的数字已经位于最左时,此时输入的数字并不立即向右移动,而是先在最左停顿一次,下一个输入的数字再向右移动。

到达最右时的处理和最左一致。

键盘输入 F 时程序退出。

效果

上面说的这段话简直就不是人话,还是看一下实际的效果吧(

代码

A8255 EQU 0600H
B8255 EQU 0602H
C8255 EQU 0604H
CON8255 EQU 0606H
ROWOUT EQU 200H
SSEG SEGMENT STACK
DW 20 DUP(?)
SSEG ENDS
DATA SEGMENT
TBL:
DB 3FH ;; 0
DB 06H ;; 1
DB 5BH ;; 2
DB 4FH ;; 3
DB 66H ;; 4
DB 6DH ;; 5
DB 7DH ;; 6
DB 07H ;; 7
DB 7FH ;; 8
DB 6FH ;; 9
DB 77H ;; A
DB 7CH ;; B
DB 39H ;; C
DB 5EH ;; D
DB 79H ;; E
DB 71H ;; F
DB 00H ;; CLR
SEQ:
DB 00011111B ;; POS 0
DB 00101111B ;; POS 1
DB 00110111B ;; POS 2
DB 00111011B ;; POS 3
DB 00111101B ;; POS 4
DB 00111110B ;; POS 5
VAL DB 00H
VAL_POS DB 00H
VAL_SHOW DB 00H
VAL_STEP DB 00H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE, DS:DATA, SS:SSEG
START PROC
MOV AX, DATA
MOV DS, AX
MOV AL, 81H ;;10001001B ;; A B OUT, C IN
MOV DX, CON8255
OUT DX, AL
MOV AX, 0000H
LO:
CALL NUM_DISPLAY
CALL SCAN
CMP AX, 10H
JE LO
CMP AX, 0FH
JE MA_EXIT
CALL NUM_SET
WAIT_UP:
CALL NUM_DISPLAY
CALL KEY_PRESSED
CMP AX, 1
JE WAIT_UP
JMP LO
MA_EXIT:
MOV AX, 1000H
CALL PUT
MOV AX, 4C00H
INT 21H
START ENDP
SCAN PROC
BEGIN:
CALL KEY_PRESSED ;; EXIT IF NOT PRESSED
CMP AX, 0
JE SCAN_NO_KEY
CALL DELAY
CALL KEY_PRESSED
CMP AX, 0
JE SCAN_NO_KEY
MOV CH, 0FEH
MOV CL, 0
COLUMN:
MOV AL, CH
MOV DX, A8255
OUT DX, AL
MOV DX, C8255
IN AL, DX
L1:
TEST AL, 1
JNZ L2
MOV AL, 00H
JMP KCODE
L2:
TEST AL, 2
JNZ L3
MOV AL, 04H
JMP KCODE
L3:
TEST AL, 4
JNZ L4
MOV AL, 08H
JMP KCODE
L4:
TEST AL, 8
JNZ NEXT
MOV AL, 0CH
KCODE:
ADD AL, CL
JMP SCAN_FIN
NEXT:
INC CL
MOV AL, CH
TEST AL, 08H
JE SCAN_NO_KEY
ROL AL, 1
MOV CH, AL
JMP COLUMN
SCAN_NO_KEY:
MOV AX, 10H
SCAN_FIN:
RET
SCAN ENDP
;; RETURN WHETHER KEY PRESSED IN AX
KEY_PRESSED PROC
MOV DX, A8255
MOV AL, 00H
OUT DX, AL ;; LINE OUTPUT 0000
MOV DX, C8255
IN AL, DX ;; GET LINE STATUS
AND AL, 0FH
CMP AL, 0FH
JE KP_NONE
MOV AX, 1 ;; KEY PRESSED
RET
KP_NONE:
MOV AX, 0
RET
KEY_PRESSED ENDP
;; SET AL TO VAL & MOVE POS
NUM_SET PROC
PUSH AX
MOV VAL, AL
MOV AL, VAL_POS
ADD AL, VAL_STEP
CMP VAL_STEP, 0 ;; REGULAR STATUS: STEP != 0
JNE NS_REG
CMP VAL_POS, 5
JE NS_LMOST
MOV VAL_STEP, 1 ;; POS == 0, RIGHT MOST
JMP NS_FIN
NS_LMOST: ;; POS == 5, LEFT MOST
MOV VAL_STEP, -1
JMP NS_FIN
NS_REG:
CMP AL, 5
JE NS_SET0
CMP AL, 0
JE NS_SET0
JMP NS_FIN
NS_SET0:
MOV VAL_STEP, 0
NS_FIN:
MOV VAL_SHOW, 1
MOV VAL_POS, AL
POP AX
RET
NUM_SET ENDP
;; DISPLAY VAL AT VAL_POS
NUM_DISPLAY PROC
;MOV AL, VAL_SHOW
CMP VAL_SHOW, 0
JE ND_SKIP
MOV AH, VAL
MOV AL, VAL_POS
CALL PUT
CALL DELAY
ND_SKIP:
RET
NUM_DISPLAY ENDP
;; NUM: AH
;; POS: AL
PUT PROC
PUSH AX
;; SELECT POS
LEA BX, SEQ
PUSH AX
MOV AH, 0
MOV SI, AX
;; OUTPUT POS
MOV DX, A8255
MOV AL, [BX+SI]
OUT DX, AL
POP AX
;; SELECT NUM
LEA BX, TBL
MOV AL, AH
MOV AH, 0
MOV SI, AX
;; OUTPUT DATA
MOV DX, B8255
MOV AL, [BX+SI]
OUT DX, AL
POP AX
RET
PUT ENDP
DELAY PROC
MOV CX, 0FFH
LOOP $
RET
DELAY ENDP
CODE ENDS
END START

Previous Post
[微机实验/TD-PITE] 数码管显示实验
Next Post
[微机实验/TD-PITE] 微机接口综合实验