2016-03-29

微机系统与接口实验(三)—8259中断优先级实验

注:评论里面有更好的代码,我这里没有测试环境,大家可以看看那个代码!!

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
Share

You may also like...

18 Responses

  1. fishVD说道:

    你好,做实验时参考了你的程序,表示感谢。在做扩展题时,看你的程序,结果会是中断一直嵌套,不会跳回,我记得中断嵌套层数受系统栈大小影响,那表示你的程序会在中断嵌套多次后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

  2. 匿名说道:

    美女真6

  3. ;=说道:

    应某人邀约前面有个诡异的逗号,,

  4. 哈哈哈哈说道:

    代码很不错 用起来方便

  5. ICU寄存器说道:

    思考题中ICW4的设置,为什么缓冲方式选为非缓冲啊,这是干嘛的

  6. 说道:

    应某人邀约什么鬼

  7. Bing说道:

    66666667

  8. WJ说道:

    666666666

  9. AyiYo说道:

    要是多点解释就更好了=_=

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据