ToC
实验内容
实现一个以秒为单位的计时器。
使用 1MHz
的时钟源和 8254
、8259
构成周期为 1
秒的计时中断时钟。
通过键盘 0-9
输入计时的分钟数,A
控制计时过程的开始和结束,B
控制暂停和继续,C
退出程序。
具体功能如下:
- 初始状态:无显示。此时通过
0-9
输入计时初值,范围为1-99
分钟,显示在数码管3
和4
上。 A
键(启动/取消):初值设置完成后按A
键,从计数初值开始倒计时。数码管1
和2
显示分,3
和4
显示秒;计时过程中按A
键,停止倒计时,回到初始状态。B
键(暂停/继续):计时过程中按B
键,暂停倒计时,显示停止时间;再次按B
键,从停止时间继续倒计时。- 计时结束:倒计时至
0000
时,闪烁三次后回到初始状态。 C
键(退出):任何时刻按C
键,熄灭数码管,程序退出。
实验接线
正常连接 8254
和 8255
即可。在本实现中,8254
接 IOY0
,8255
接 IOY1
。
代码
A8255 EQU 0640HB8255 EQU 0642HC8255 EQU 0644HCON8255 EQU 0646H
C008254 EQU 0600HC018254 EQU 0602HC028254 EQU 0604HCON8254 EQU 0606H
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 CNT_STARTED DB 00H CNT_PAUSED DB 00H VAL_MIN: DB 2 DUP(10H) VAL_SEC: DB 2 DUP(0) MIR_COUNTER DB 00HDATA ENDS
CODE SEGMENTASSUME CS:CODE, DS:DATA
START PROC MOV AX, 0 MOV DS, AX
;; INIT 8255 MOV AL, 81H ;;10001001B ;; A B OUT, C IN MOV DX, CON8255 OUT DX, AL
;; MIR6 MOV AX, OFFSET MIR6 MOV SI, 38H MOV [SI], AX MOV AX, CS MOV SI, 3AH MOV [SI], AX
;; -------------------------------------------------- ;; INIT 8259 CLI MOV AL, 11H OUT 20H, AL MOV AL, 08H OUT 21H, AL MOV AL, 04H OUT 21H, AL MOV AL, 07H OUT 21H, AL MOV AL, 2FH OUT 21H, AL STI ;; --------------------------------------------------
;; -------------------------------------------------- ;; INIT 8254 MOV AL, 00110110B MOV DX, CON8254 OUT DX, AL
MOV DX, C008254 MOV AL, 24H ;; LOWER 8 BYTES OUT DX, AL
MOV AL, 0F4H ;; HIGHER 8 BYTES OUT DX, AL ;; --------------------------------------------------
MOV AX, DATA MOV DS, AXLO: CALL NUM_DISPLAY CALL SCAN CMP AX, 10H JE LO CMP AX, 0AH ;; PRESS A TO START/STOP JNE LO_NB ;;;;;; CMP CNT_STARTED, 00H JE COUNTER_START;; COUNTER_STOP MOV CNT_STARTED, 0 CALL CLR_TIME LEA BX, VAL_MIN MOV [BX], 1010H JMP WAIT_UPCOUNTER_START: MOV CNT_STARTED, 1 MOV CNT_PAUSED, 0 JMP WAIT_UP ;;;;;;LO_NB: CMP AX, 0BH ;; PRESS B TO PAUSE/RESUME JNE LO_NC XOR CNT_PAUSED, 1 JMP WAIT_UPLO_NC: CMP AX, 0CH ;; PRESS C TO EXIT JE MA_EXIT
CMP AX, 0AH JGE WAIT_UP CALL MIN_SETWAIT_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 21HSTART ENDP
MIN_SET PROC CMP CNT_STARTED, 1 JE MS_EXIT
LEA BX, VAL_MIN MOV AH, [BX] CMP AH, 10H JE MS_SW MOV AH, [BX+1] CMP AH, 10H JE MS_GW JMP MS_EXITMS_SW: MOV [BX], AL JMP MS_EXITMS_GW: MOV [BX+1], ALMS_EXIT: RETMIN_SET ENDP
TIMER_RESET PROC MOV CNT_STARTED, 0 CALL CLR_TIME MOV CX, 3TR_LO: PUSH CX CALL ZERO_BLINK CALL DELAY
CALL NUM_DISPLAY_CLS CALL DELAY_LONG POP CX LOOP TR_LO
CALL CLR_TIME RETTIMER_RESET ENDP
CLR_TIME PROC LEA BX, VAL_MIN MOV AH, 10H MOV [BX], AH MOV [BX+1], AH LEA BX, VAL_SEC MOV AH, 00H MOV [BX], AH MOV [BX+1], AH RETCLR_TIME ENDP
ZERO_BLINK PROC PUSH CX MOV CX, 0FFHZB: PUSH CX MOV AX, 0005H CALL PUT CALL DELAY
MOV AX, 0004H CALL PUT CALL DELAY
MOV AX, 0003H CALL PUT CALL DELAY
MOV AX, 0002H CALL PUT CALL DELAY POP CX LOOP ZB POP CX RETZERO_BLINK ENDP
NUM_DISPLAY PROC CMP CNT_STARTED, 1 JE ND_TIMER ;; INPUT MODE LEA BX, VAL_MIN MOV SI, 0
MOV AH, [BX+SI] MOV AL, 03H CALL PUT CALL DELAY
LEA BX, VAL_MIN MOV SI, 0 MOV AH, [BX+SI+1] MOV AL, 02H CALL PUT CALL DELAY RET
ND_TIMER: ;; TIMER MODE LEA BX, VAL_MIN MOV SI, 0 MOV AH, [BX+SI] MOV AL, 05H CALL PUT CALL DELAY
LEA BX, VAL_MIN MOV SI, 0 MOV AH, [BX+SI+1] MOV AL, 04H CALL PUT CALL DELAY
LEA BX, VAL_SEC MOV SI, 0 MOV AH, [BX+SI] MOV AL, 03H CALL PUT CALL DELAY
LEA BX, VAL_SEC MOV SI, 0 MOV AH, [BX+SI+1] MOV AL, 02H CALL PUT CALL DELAY RETNUM_DISPLAY ENDP
NUM_DISPLAY_CLS PROC MOV CX, 5ND_CLS: MOV AH, 10H MOV AL, AL CALL PUT LOOP ND_CLS RETNUM_DISPLAY_CLS ENDP
;; DECREASE SECOND & MIN WHEN NECESSARYDEC_SEC PROC CMP CNT_STARTED, 0 ;; NOT STARTED JE DEC_EXIT
CMP CNT_PAUSED, 1 ;; PAUSED JE DEC_EXIT
LEA BX, VAL_SEC MOV AH, [BX+1] CMP AH, 0 JE DS_JW_S DEC AH MOV [BX+1], AH JMP DEC_EXITDS_JW_S: MOV AH, 9 MOV [BX+1], AH MOV AH, [BX] CMP AH, 0 JE DS_JW_MG DEC AH MOV [BX], AH JMP DEC_EXITDS_JW_MG: MOV AH, 5 MOV [BX], AH LEA BX, VAL_MIN MOV AH, [BX+1] CMP AH, 0 JE DS_JW_MS DEC AH MOV [BX+1], AH JMP DEC_EXITDS_JW_MS: MOV AH, 9 MOV [BX+1], AH MOV AH, [BX] CMP AH, 0 JE DS_FIN DEC AH MOV [BX], AH JMP DEC_EXITDS_FIN: CALL TIMER_RESETDEC_EXIT: RETDEC_SEC ENDP
MIR6 PROC STI INC MIR_COUNTER CMP MIR_COUNTER, 10H JNE MIR6_FIN MOV MIR_COUNTER, 0 CALL DEC_SECMIR6_FIN: IRETMIR6 ENDP
SCAN PROCBEGIN: 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, 0COLUMN: MOV AL, CH MOV DX, A8255 OUT DX, AL MOV DX, C8255 IN AL, DXL1: TEST AL, 1 JNZ L2 MOV AL, 00H JMP KCODEL2: TEST AL, 2 JNZ L3 MOV AL, 04H JMP KCODEL3: TEST AL, 4 JNZ L4 MOV AL, 08H JMP KCODEL4: TEST AL, 8 JNZ NEXT MOV AL, 0CHKCODE: ADD AL, CL JMP SCAN_FINNEXT: 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, 10HSCAN_FIN: RETSCAN ENDP
;; RETURN WHETHER KEY PRESSED IN AXKEY_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 RETKP_NONE: MOV AX, 0 RETKEY_PRESSED ENDP
;; NUM: AH;; POS: ALPUT 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 RETPUT ENDP
DELAY PROC MOV CX, 0FFH LOOP $ RETDELAY ENDP
DELAY_LONG PROC MOV CX, 0FFFFH LOOP $ RETDELAY_LONG ENDP
CODE ENDSEND START