注:评论里面有更好的代码,我这里没有测试环境,大家可以看看那个代码!!
1. 实验目的
- 掌握 8259 中断控制器的工作原理。
- 学习 8259 的应用编程方法。
- 掌握 8259 级联方式的使用方法实验内容
2. 实验内容
- 题目:编写中断试验程序:主程序通过8255的PB口输出0FFH,使数据灯D0~D7全亮;IR6中断服务程序使绿灯亮(红灯灭);延时一段时间后返回主程序;IR7中断服务程序使红灯亮(绿灯灭);延时一段时间后返回主程序。
- 要求:按单脉冲开关KK1+响应IR6中断请求;按单脉冲开关KK2+响应IR7中断请求。
3. 思考题
- 若要实现中断嵌套(即,在红灯亮时,按下KK1+,则立即便为绿灯亮,延时一段时间后回复红灯亮,再延时一段时间后回到全亮),应该如何修改程序?
4. 实验扩展
- 使用单脉冲开关KK1和KK2控制LED灯(D7~D0)的点亮(每个时刻只有一个数据灯点亮):
- 初始时D7点亮其余灯熄灭;
- 当点亮的LED灯位于最左侧或者正在向左移动,按下KK1,则点亮的LED灯向右逐位移动,到达最右侧时停止;
- 当点亮的LED灯位于最右侧或者正在向右移动,按下KK2,则点亮的LED灯向左逐位移动,到达最右侧时停止;
5. 主实验解答
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | CODE SEGMENT ASSUME CS:CODE START: MOV AX, 0000H MOV DS, AX ;手动指定用户程序区的起始位置,可以不指定,默认为0000H MOV DX, 0646H ;8255控制端口地址,与选取的IOY端口有关,详见实验一 MOV AL, 90H ;8255控制字,90H=10010000B,表示A口输入,B口输出。 OUT DX, AL ;将上述控制字写入控制端口 MOV DX, 0642H ;8255B口地址 MOV AL,0FFH OUT DX,AL ;输出FFH=11111111B,将D7-D0点亮 MOV AX, OFFSET MIR6 ;取中断服务程序的偏移地址 MOV SI, 0038H ;中断号6的向量起始地址,见实验讲义P48 MOV [SI], AX ;将服务程序地址填入中断向量(占两个字节) MOV AX, CS ;取段地址 MOV SI, 003AH ;中断向量后移两个字节等待存入段地址 MOV [SI], AX ;将段地址存入中断向量(占两个字节) ;中断向量共四个字节大小,分别存服务程序入口地址和段地址 MOV AX, OFFSET MIR7 MOV SI, 003CH MOV [SI], AX MOV AX, CS MOV SI, 003EH MOV [SI], AX ;填入MIR7的中断向量,同上 CLI ;屏蔽所有可屏蔽中断,准备写入命令字 MOV AL, 11H ;主片8255端口地址详见实验讲义P44 OUT 20H, AL ;命令字ICW1,11H=00010001B MOV AL, 08H OUT 21H, AL ;命令字ICW2,08H=00001000B MOV AL, 04H OUT 21H, AL ;命令字ICW3,04H=00000100B MOV AL, 01H OUT 21H, AL ;命令字ICW4,01H=00000001B MOV AL, 3FH OUT 21H, AL ;命令字OCW1,3FH=00111111B STI ;控制字写入完成,允许中断,结束CLI ;OCW1命令字表示除IR6,IR7中断外其余中断均被屏蔽 ;其余命令字含义请对照实验讲义P45-P48 AA1: MOV DX, 0642H MOV AL, 0FFH OUT DX, AL JMP AA1 ;相当于主程序,表示循环点亮D7-D0 MIR6: MOV DX, 0642H MOV AL, 0F0H OUT DX, AL ;按下KK1+进入MIR6中断,只点亮绿灯 MOV AL, 20H ;命令字OCW2,20H=00100000B,表示结束中断 OUT 20H, AL ;写入OCW2,结束中断 MOV CX,0FFFFH ;CX为计数寄存器,确定循环次数 L1: LOOP L1 MOV CX,0FFFFH L2: LOOP L2 MOV CX,0FFFFH L3: LOOP L3 MOV CX,0FFFFH L4: LOOP L4 ;L1-L4为空循环,作用为延迟时间,改为多层循环或子程序更好 IRET ;中断返回指令,回到主程序发生中断的位置 MIR7: MOV DX, 0642H MOV AL,0FH OUT DX,AL MOV AL,20H OUT 20H,AL MOV CX,0FFFFH L5: LOOP L5 MOV CX,0FFFFH L6: LOOP L6 MOV CX,0FFFFH L7: LOOP L7 MOV CX,0FFFFH L8: LOOP L8 IRET ;按下KK2+进入MIR7中断,只点亮红灯,其余同上 CODE ENDS END START |
6. 思考题解答
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | CODE SEGMENT ASSUME CS:CODE START: MOV AX, 0000H MOV DS, AX MOV DX, 0646H MOV AL, 90H OUT DX, AL MOV DX, 0642H MOV AL,0FFH OUT DX,AL ;输出FFH=11111111B,将D7-D0点亮 MOV AX, OFFSET MIR6 MOV SI, 0038H MOV [SI], AX MOV AX, CS MOV SI, 003AH MOV [SI], AX ;填入MIR6的中断向量 MOV AX, OFFSET MIR7 MOV SI, 003CH MOV [SI], AX MOV AX, CS MOV SI, 003EH MOV [SI], AX ;填入MIR7的中断向量 CLI MOV AL, 11H OUT 20H, AL MOV AL, 08H OUT 21H, AL MOV AL, 04H OUT 21H, AL MOV AL, 05H OUT 21H, AL MOV AL, 3FH OUT 21H, AL STI ;ICW4命令字改为05H=00000101B,讲道理其实第三次程序所有的实验都应该是这个 ;其余命令字含义请对照实验讲义P45-P48 AA1: MOV DX, 0642H MOV AL, 0FFH OUT DX, AL JMP AA1 MIR6: STI MOV DX, 0642H MOV AL, 0F0H OUT DX, AL MOV CX,0FFFFH L1: MOV AL, 0F0H OUT DX, AL LOOP L1 MOV CX,0FFFFH L2: MOV AL, 0F0H OUT DX, AL LOOP L2 MOV CX,0FFFFH L3: MOV AL, 0F0H OUT DX, AL LOOP L3 MOV CX,0FFFFH L4: MOV AL, 0F0H OUT DX, AL LOOP L4 ;这里考虑到中断嵌套所以把延时改为一直输出灯的状态,以免看不到现象 MOV AL, 20H OUT 20H, AL IRET MIR7: CLI MOV DX, 0642H MOV AL,0FH OUT DX,AL MOV CX,0FFFFH L5: MOV AL,0FH OUT DX,AL LOOP L5 MOV CX,0FFFFH L6: MOV AL,0FH OUT DX,AL LOOP L6 MOV CX,0FFFFH L7: MOV AL,0FH OUT DX,AL LOOP L7 MOV CX,0FFFFH L8: MOV AL,0FH OUT DX,AL LOOP L8 MOV CX,0FFFFH L9: MOV AL,0FH OUT DX,AL LOOP L9 MOV CX,0FFFFH L10: MOV AL,0FH OUT DX,AL LOOP L10 MOV CX,0FFFFH L11: MOV AL,0FH OUT DX,AL LOOP L11 MOV CX,0FFFFH L12: MOV AL,0FH OUT DX,AL LOOP L12 ;同上将延时改为不断输出灯的状态 ;考虑到IR7的时候可以响应IR6中断,所以延时稍微长一些显现比较明显,当然不加长也是没有问题的 MOV AL,20H OUT 20H,AL IRET CODE ENDS END START |
- 推荐进入中断时保存现场,这样可以避免出现诡异的问题。
7. 实验扩展解答
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | CODE SEGMENT ASSUME CS:CODE START: MOV AX, 0000H MOV DS, AX MOV DX, 0646H MOV AL, 90H OUT DX, AL MOV DX, 0642H MOV AL,80H OUT DX,AL ;将D7点,D6-D0熄灭 MOV AX, OFFSET MIR6 MOV SI, 0038H MOV [SI], AX MOV AX, CS MOV SI, 003AH MOV [SI], AX MOV AX, OFFSET MIR7 MOV SI, 003CH MOV [SI], AX MOV AX, CS MOV SI, 003EH MOV [SI], AX CLI MOV AL, 11H OUT 20H, AL MOV AL, 08H OUT 21H, AL MOV AL, 04H OUT 21H, AL MOV AL, 01H OUT 21H, AL MOV AL, 3FH OUT 21H, AL STI ;与主实验相同部分此处不再赘述 ;下面的AA1与AA2相当于两个主程序,控制灯的右移和左移 AA1: MOV DX, 0642H IN AL,DX ;读入当前灯的状态 CMP AL,01H JE AA1 ;判断灯是否是最右侧亮,如果是则不变,不是则继续移动 ROR AL,1 ;将AL循环右移1位 MOV CX,0FFFFH L1: LOOP L1 MOV CX,0FFFFH L2: LOOP L2 MOV CX,0FFFFH L3: LOOP L3 MOV CX,0FFFFH L4: LOOP L4 ;延时 OUT DX,AL ;从8255B口输出右移后的灯的状态 JMP AA1 AA2: MOV DX, 0642H IN AL,DX CMP AL,80H JE AA2 ;判断灯是否是最左侧亮,如果是则不变,不是则继续移动 ROL AL,1 ;将AL循环左移1位 MOV CX,0FFFFH L5: LOOP L5 MOV CX,0FFFFH L6: LOOP L6 MOV CX,0FFFFH L7: LOOP L7 MOV CX,0FFFFH L8: LOOP L8 ;延时 OUT DX,AL ;从8255B口输出右移后的灯的状态 JMP AA2 MIR6: STI MOV AL,20H OUT 20H,AL JMP AA1 ;按下KK1+,灯右移,跳转到AA1 IRET MIR7: STI MOV AL,20H OUT 20H,AL JMP AA2 ;按下KK2+,灯左移,跳转到AA2 IRET CODE ENDS END START |
- 上述代码可以达到要求的实验效果,但是由于在IRET之前跳转导致没有执行IRET,推荐新开一个变量,在中断中对变量进行赋值,在主程序中根据变量值判断该进行左移还是右移,应某人邀约,部分代码如下。
- 下述代码受限于环境未经过测试,实际上机时可能需要调试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | DATA SEGMENT SIGN DB 00H ;通过在中断中改变该变量的值控制移动方向 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA START: MOV AX, 0000H MOV DS, AX MOV DX, 0646H MOV AL, 90H OUT DX, AL MOV DX, 0642H MOV AL,80H OUT DX,AL ;将D7点,D6-D0熄灭 MOV AX, OFFSET MIR6 MOV SI, 0038H MOV [SI], AX MOV AX, CS MOV SI, 003AH MOV [SI], AX MOV AX, OFFSET MIR7 MOV SI, 003CH MOV [SI], AX MOV AX, CS MOV SI, 003EH MOV [SI], AX CLI MOV AL, 11H OUT 20H, AL MOV AL, 08H OUT 21H, AL MOV AL, 04H OUT 21H, AL MOV AL, 01H OUT 21H, AL MOV AL, 3FH OUT 21H, AL STI ;与主实验相同部分此处不再赘述 ;下面的AA1与AA2相当于两个主程序,控制灯的右移和左移 MI: CMP SIGN 01H JE AA2 AA1: MOV DX, 0642H IN AL,DX ;读入当前灯的状态 CMP AL,01H JE MI ;判断灯是否是最右侧亮,如果是则不变,不是则继续移动 ROR AL,1 ;将AL循环右移1位 MOV CX,0FFFFH L1: LOOP L1 MOV CX,0FFFFH L2: LOOP L2 MOV CX,0FFFFH L3: LOOP L3 MOV CX,0FFFFH L4: LOOP L4 ;延时 OUT DX,AL ;从8255B口输出右移后的灯的状态 JMP MI AA2: MOV DX, 0642H IN AL,DX CMP AL,80H JE MI ;判断灯是否是最左侧亮,如果是则不变,不是则继续移动 ROL AL,1 ;将AL循环左移1位 MOV CX,0FFFFH L5: LOOP L5 MOV CX,0FFFFH L6: LOOP L6 MOV CX,0FFFFH L7: LOOP L7 MOV CX,0FFFFH L8: LOOP L8 ;延时 OUT DX,AL ;从8255B口输出右移后的灯的状态 JMP MI MIR6: STI MOV SIGN,00H ;按下KK1+,灯右移,跳转到AA1 MOV AL,20H OUT 20H,AL IRET MIR7: STI MOV SIGN,01H ;按下KK2+,灯左移,跳转到AA2 MOV AL,20H OUT 20H,AL IRET CODE ENDS END START |
你好,做实验时参考了你的程序,表示感谢。在做扩展题时,看你的程序,结果会是中断一直嵌套,不会跳回,我记得中断嵌套层数受系统栈大小影响,那表示你的程序会在中断嵌套多次后gg(没有测试),所以我就改了一下。再次感谢你。
以下代码经过测试。
CS0 EQU 0640H
P8255_PA EQU CS0 + 00H
P8255_PB EQU CS0 + 02H
P8255_PC EQU CS0 + 04H
P8255_CONTROL EQU CS0 + 06H
P8255_MODE EQU 90H
P8255_INIT EQU 0FFH
P8259_ICW1 EQU 13H
P8259_ICW2 EQU 10H
P8259_ICW3 EQU 04H
P8259_ICW4 EQU 01H
P8259_OCW1 EQU 3FH
P8259_OCW2 EQU 20H
CS_8259 EQU 20H
CODE SEGMENT
ASSUME CS:CODE
MAIN PROC NEAR
;设置8255
MOV DX,P8255_CONTROL
MOV AL,P8255_MODE
OUT DX,AL
MOV DX,P8255_PB
MOV AL,80H
OUT DX,AL
;主程序
LOP:
NOP
JMP LOP
;设置中断向量
CLI
MOV AX,OFFSET INT_IR6
MOV SI,0058H
MOV [SI],AX
MOV AX,CS
MOV SI,005AH
MOV [SI],AX
MOV AX,OFFSET INT_IR7
MOV SI,005CH
MOV [SI],AX
MOV AX,CS
MOV SI,005EH
MOV [SI],AX
STI
;初始化8259
CLI
MOV AL,P8259_ICW1
OUT 20H,AL
MOV AL,P8259_ICW2
OUT 21H,AL
MOV AL,P8259_ICW4
OUT 21H,AL
MOV AL,P8259_OCW1
OUT 21H,AL
MOV AL,P8259_OCW2
OUT 20H,AL
STI
MAIN ENDP
;MIR7中断处理程序
INT_IR7 PROC FAR
STI
MOV BX,0H
MOV DX,P8255_PB
IN AL,DX
CMP AL,80H
JE END1
SHIFT1:
CMP BX,1H
JE END1
CMP AL,80H
JE END1
ROL AL,1H
OUT DX,AL
CALL DELAY
JMP SHIFT1
END1:
MOV BX,1H
IRET
INT_IR7 ENDP
;MIR6中断处理程序
INT_IR6 PROC FAR
STI
MOV BX,0H
MOV DX,P8255_PB
IN AL,DX
CMP AL,1H
JE END2
SHIFT2:
CMP BX,1H
JE END2
CMP AL,80H
JE END2
ROR AL,1H
OUT DX,AL
CALL DELAY
JMP SHIFT2
END2:
MOV BX,1H
IRET
INT_IR6 ENDP
;延时子程序
DELAY PROC NEAR
MOV CX,0FFH
LOOP $
RET
DELAY EDNP
CODE ENDS
END MIAN
6666
可以的!!
把显示和左右移动放在主程序段里,中断程序只负责更改标志变量的值会不会好点
美女真6
应某人邀约前面有个诡异的逗号,,
改啦
代码很不错 用起来方便
把我u盘找回来别忘了
思考题中ICW4的设置,为什么缓冲方式选为非缓冲啊,这是干嘛的
详见百度
应某人邀约什么鬼
不要在意这些细节????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
66666667
666666666
要是多点解释就更好了=_=
加啦