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