339 lines
9.9 KiB
NASM
Executable File
339 lines
9.9 KiB
NASM
Executable File
DATA SEGMENT
|
||
A8255A EQU 280H
|
||
A8255B EQU 281H
|
||
A8255C EQU 282H
|
||
A8255COM EQU 283H
|
||
|
||
A8254A EQU 288H
|
||
A8254B EQU 289H
|
||
A8254COM EQU 28BH
|
||
|
||
OLD_OFF DW 0
|
||
OLD_SEG DW 0
|
||
|
||
TMP1 DB 0
|
||
TMP2 DB 0
|
||
LED DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H, 7FH, 6FH, 77H, 7CH, 39H, 5EH, 79H, 71H
|
||
WAITING DB 40H ; 等待状态的字节码
|
||
FAULT DB 71H ; 违规状态的字节码
|
||
SUCCESS DB 6DH ; 抢答成功状态的字节码
|
||
ZERO DB 3FH ; 数码管显示0的字节码
|
||
DATA ENDS
|
||
|
||
CODE SEGMENT
|
||
ASSUME DS:DATA, CS:CODE
|
||
|
||
; 1. 程序逻辑
|
||
; 1.1. 当K7为0时,K0-6都必须为0,否则为1的违规,数码管显示违规选手 && 扬声器鸣叫
|
||
; 1.2. 当K7为1时,当K0-6中有一个为1时,停止检测,为1的按键对应的选手抢答成功,数码管显示抢答成功选手
|
||
; 2. 程序设计
|
||
; 2.1. 2个PROC
|
||
; 2.1.1. PROC1扫描到 K7为0 && K0-6中存在1的按键时进入,K0-6全为0时退出
|
||
; 进入PROC1后蜂鸣器响起,不断扫描K0-7,数码管显示违规选手。
|
||
; 当全为0时蜂鸣器关闭,退出PROC1
|
||
; 2.1.2. PROC2扫描到K7为1时进入,K7为0时退出
|
||
; 进入PROC2后循环扫描K0-7,K0-6存在1后数码管显示抢答成功选手
|
||
; 继续循环扫描,但只看K7,K7为0时退出
|
||
; 进入PROC2后进行计时,4秒后若无变化,触发中断,退出PROC
|
||
; 2.2. 主程序 循环扫描K0-7
|
||
; 2.2.1. K7为0 && K0-6按键全0时不变,继续循环
|
||
; 2.2.2. K7为0 && K0-6中存在1的按键时进入PROC1
|
||
; 2.2.2. K7为1时进入PROC2
|
||
|
||
START:
|
||
MOV AX, DATA
|
||
MOV DS, AX
|
||
|
||
CLI ; 关中断,防止中断干扰
|
||
; 保存旧的中断向量
|
||
MOV AX, 350BH
|
||
INT 21H
|
||
MOV OLD_OFF, BX
|
||
MOV BX, ES
|
||
MOV OLD_SEG, BX
|
||
|
||
; 设置新的中断向量
|
||
MOV AX, 250BH
|
||
MOV DX, SEG TIMEOUT
|
||
MOV DS, DX
|
||
MOV DX, OFFSET TIMEOUT
|
||
INT 21H
|
||
STI
|
||
|
||
; 恢复数据段
|
||
MOV AX, DATA
|
||
MOV DS, AX
|
||
|
||
; 初始化8255
|
||
MOV AX, 10001001B ; A口输出段码,B口输出位码,C口输入拨动开关
|
||
MOV DX, A8255COM
|
||
OUT DX, AL
|
||
|
||
; 使用8254 A口将1MHz降频为1kHz,为8254 B口提供时钟源
|
||
MOV DX, A8254COM
|
||
MOV AL, 00110110B
|
||
OUT DX, AL
|
||
MOV DX, A8254A
|
||
MOV AL, 11101000B
|
||
OUT DX, AL
|
||
MOV AL, 00000011B
|
||
OUT DX, AL
|
||
|
||
; 主程序
|
||
MAIN:
|
||
MOV DX, A8255C
|
||
IN AL, DX
|
||
|
||
MOV SI, 0 ; 中断标志位
|
||
|
||
; K7为0 && K0-6按键全0时不变,继续循环
|
||
CMP AL, 0 ; 比较AL寄存器的值与0
|
||
JE MAIN ; 如果相等,则跳转到MAIN
|
||
|
||
; K7为0 && K0-6中存在1的按键时进入PROC1
|
||
AND AL, 10000000B ; 将AL寄存器的值与10000000B进行按位与操作
|
||
CMP AL, 0 ; 比较AL寄存器的值与0,即判断第7位是否为0
|
||
JNE P2 ; 如果不相等,则跳转到P2
|
||
CALL PROC1 ; 调用PROC1子程序
|
||
|
||
; K7为1时进入PROC2
|
||
P2:
|
||
CALL PROC2 ; 调用PROC2子程序
|
||
JMP MAIN ; 无条件跳转到MAIN
|
||
|
||
FINISH:
|
||
CLI ; 关中断,防止中断干扰
|
||
MOV AX, 250BH ; 恢复原来的中断向量
|
||
MOV DX, OLD_OFF
|
||
MOV DS, DX
|
||
MOV DS, OLD_SEG
|
||
INT 21H
|
||
|
||
MOV AX, 4C00H
|
||
INT 21H
|
||
|
||
PROC1 PROC NEAR
|
||
|
||
; K7为0 && K0-6中存在1的按键时进入,K0-6全为0时退出
|
||
; 进入PROC1后蜂鸣器响起,不断扫描K0-7,数码管显示违规选手。
|
||
; 当全为0时,蜂鸣器关闭,退出PROC1
|
||
|
||
PUSH DX
|
||
PUSH CX
|
||
|
||
LOOP1:
|
||
MOV DX, A8255C
|
||
IN AL, DX
|
||
MOV TMP1, AL
|
||
|
||
CMP AL, 0
|
||
JE RETURN1
|
||
|
||
MOV CX, 8
|
||
MOV TMP2, 10000000B ; 位码
|
||
LOOP2:
|
||
ROR TMP2, 1
|
||
JMP OUTPUT1
|
||
BACK1:
|
||
LOOP LOOP2
|
||
JMP LOOP1
|
||
|
||
; 在数码管上输出
|
||
OUTPUT1:
|
||
CALL CLEAR
|
||
MOV AL, TMP1
|
||
AND AL, TMP2
|
||
CMP AL, TMP2
|
||
JE FAULT1
|
||
MOV AL, WAITING
|
||
JMP DISPLAY1
|
||
FAULT1:
|
||
MOV AL, FAULT
|
||
DISPLAY1:
|
||
MOV DX, A8255A
|
||
OUT DX, AL
|
||
MOV DX, A8255B
|
||
MOV AL, TMP2
|
||
OUT DX, AL
|
||
CALL DELAY
|
||
JMP BACK1
|
||
|
||
RETURN1:
|
||
CALL CLEAR
|
||
POP CX
|
||
POP DX
|
||
RET
|
||
PROC1 ENDP
|
||
|
||
PROC2 PROC NEAR
|
||
|
||
; 进入PROC2后循环扫描K0-7,K0-6存在1后数码管显示抢答成功选手
|
||
; 继续循环扫描,但只看K7,K7为0时退出PROC2
|
||
|
||
PUSH DX
|
||
PUSH CX
|
||
|
||
MOV SI, 0 ; 时间到退出抢答标志
|
||
|
||
; 开始计时,1000Hz * 4000 = 4s后输出低电平,取反后用于触发中断
|
||
MOV DX, A8254COM
|
||
MOV AL, 10111000B
|
||
OUT DX, AL
|
||
MOV DX, A8254B
|
||
MOV AL, 10100000B
|
||
OUT DX, AL
|
||
MOV AL, 00001111B
|
||
OUT DX, AL
|
||
|
||
; 设置中断屏蔽
|
||
CLI
|
||
IN AL, 21H
|
||
AND AL, 11110111B
|
||
OUT 21H, AL
|
||
STI
|
||
|
||
LOOP3:
|
||
CMP SI, 1
|
||
JE RETURN2
|
||
|
||
MOV DX, A8255C
|
||
IN AL, DX
|
||
MOV TMP1, AL
|
||
AND AL, 10000000B ; 位码
|
||
CMP AL, 0
|
||
JE RETURN2
|
||
|
||
MOV AL, TMP1
|
||
AND AL, 01111111B
|
||
MOV TMP1, AL
|
||
CMP AL, 0
|
||
JE LOOP3
|
||
|
||
; 检测到有变化,恢复中断屏蔽,取消中断
|
||
CLI
|
||
IN AL, 21H
|
||
OR AL, 00001000B
|
||
OUT 21H, AL
|
||
STI
|
||
|
||
LOOP4:
|
||
MOV DX, A8255C
|
||
IN AL, DX
|
||
AND AL, 10000000B
|
||
CMP AL, 0
|
||
JE RETURN2
|
||
|
||
MOV CX, 7
|
||
MOV TMP2, 10000000B ; 位码
|
||
LOOP5:
|
||
ROR TMP2, 1
|
||
JMP OUTPUT2
|
||
BACK2:
|
||
LOOP LOOP5
|
||
JMP LOOP4
|
||
|
||
OUTPUT2:
|
||
CALL CLEAR
|
||
MOV AL, TMP1
|
||
AND AL, TMP2
|
||
CMP AL, TMP2
|
||
JE SUCCESS2
|
||
MOV AL, WAITING
|
||
JMP DISPLAY2
|
||
SUCCESS2:
|
||
MOV AL, SUCCESS
|
||
DISPLAY2:
|
||
MOV DX, A8255A
|
||
OUT DX, AL
|
||
MOV DX, A8255B
|
||
MOV AL, TMP2
|
||
OUT DX, AL
|
||
CALL DELAY
|
||
JMP BACK2
|
||
|
||
RETURN2:
|
||
CALL CLEAR
|
||
; 恢复中断屏蔽
|
||
CLI
|
||
IN AL, 21H
|
||
OR AL, 00001000B
|
||
OUT 21H, AL
|
||
STI
|
||
POP CX
|
||
POP DX
|
||
RET
|
||
PROC2 ENDP
|
||
|
||
TIMEOUT PROC FAR
|
||
CLI
|
||
PUSH CX
|
||
PUSH BX
|
||
MOV SI, 1
|
||
|
||
CALL CLEAR
|
||
MOV BX, 0FH
|
||
LOOP6:
|
||
MOV CX, 8
|
||
MOV TMP1, 00000001B ; 位码
|
||
LOOP7:
|
||
ROR TMP1, 1
|
||
JMP OUTPUT3
|
||
BACK3:
|
||
LOOP LOOP7
|
||
DEC BX
|
||
JZ RETURN3
|
||
JMP LOOP6
|
||
|
||
OUTPUT3:
|
||
MOV AL, ZERO
|
||
MOV DX, A8255A
|
||
OUT DX, AL
|
||
MOV DX, A8255B
|
||
MOV AL, TMP1
|
||
OUT DX, AL
|
||
CALL DELAY
|
||
JMP BACK3
|
||
|
||
RETURN3:
|
||
MOV AL, 20H ; 发送EOI指令
|
||
OUT 20H, AL
|
||
POP BX
|
||
POP CX
|
||
STI
|
||
IRET
|
||
TIMEOUT ENDP
|
||
|
||
CLEAR PROC NEAR
|
||
PUSH DX
|
||
PUSH AX
|
||
|
||
MOV DX, A8255A
|
||
MOV AL, 00000000B
|
||
OUT DX, AL
|
||
MOV DX, A8255B
|
||
MOV AL, 0
|
||
OUT DX, AL
|
||
|
||
POP AX
|
||
POP DX
|
||
RET
|
||
CLEAR ENDP
|
||
|
||
DELAY PROC NEAR
|
||
PUSH CX
|
||
PUSH BX
|
||
MOV CX, 0FFFFH
|
||
LOOP8:
|
||
MOV BX, 2
|
||
LOOP9:
|
||
DEC BX
|
||
JNZ LOOP9
|
||
DEC CX
|
||
JNZ LOOP8
|
||
POP BX
|
||
POP CX
|
||
RET
|
||
DELAY ENDP
|
||
|
||
END START
|
||
CODE ENDS |