实验内容
在数码管上显示键盘输入的内容,新输入的内容显示在数码管的最右侧。
当数码管显示空间已满时,删除最左侧的文本。
实验接线
这次的接线和上次是一样的。唯一的不同是不能不连 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