0x00前言

今天微机原理接口结课了,好不容易整理出实验报告

顺便以博客的形式记录一下本学期7个微机实验


2020.6.19

刚刚考完微机实验,运气好,实验很简单

文章最后记录一下实验过程


0x01 8255

1.8255输入、输出实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,28BH ;初始化8255
MOV AL,10001001B
OUT DX,AL

TEST0:
MOV DX,28AH ;C口读入开关状态
IN AL,DX
MOV DX,289H ;B口输出
OUT DX,AL
JMP TEST0 ;继续循环

CODE ENDS
END START

2.利用8255设计跑马灯(软延时)

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
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,28BH ;初始化8255
MOV AL,10001001B;控制字
OUT DX,AL
MOV AH,01H ;暂存01位置的灯

TEST0:
MOV DX,28AH ;从C口读入开关状态
IN AL,DX
CMP AL,80H ;如果不是K7开关,则循环等待
JNZ TEST0

TEST1:
MOV AL,AH
MOV DX,289H ;B口输出
OUT DX,AL
ROL AL,1 ;左移一位
MOV BX,150H ;两层嵌套循环,软延时

CIRCLE:
MOV CX,65535

DELAY:
LOOP DELAY
DEC BX
JNZ CIRCLE
MOV AH,AL ;暂存灯的状态
JMP TEST0;继续循环

CODE ENDS
END START

0x02 8253

1.8253定时实验,利用8253完成2秒的延时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
CODE SEGMENT
ASSUME CS:CODE
START:
;第一级通道2,方式2,先写低字节,后写高字节
MOV AL ,00110101B
MOV DX ,28BH
OUT DX,AL
MOV AL,00H;计数初值5000
MOV DX ,28AH
OUT DX,AL
MOV AL,50H
OUT DX,AL
;第二级通道0,方式3,先写低字节,再写高字节
MOV AL,01110111B
MOV DX,28BH
OUT DX,AL
MOV AL,00H;初值800
MOV DX,288H
OUT DX,AL
MOV AL,08H
OUT DX,AL
CODE ENDS
END START

2.利用8253硬件延时控制跑马灯运行。

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
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,2ABH;初始化8255
MOV AL,10001011B
OUT DX,AL
MOV AL,01H;暂存第一个灯,保证起始第一个灯亮
MOV BL,AL

TEST0:
MOV DX,2AAH;判断是否是开关1
IN AL,DX
TEST AL,01H
JZ TEST0

TEST1:
;第一级通道0,方式2,先写低字节,后写高字节
MOV AL ,00110101B
MOV DX ,28BH
OUT DX,AL
MOV AL,00H;计数初值5000
MOV DX ,28AH
OUT DX,AL
MOV AL,50H
OUT DX,AL
;第二级通道1,方式3,先写低字节,再写高字节
MOV AL,01110111B
MOV DX,28BH
OUT DX,AL
MOV AL,00H;初值800
MOV DX,288H
OUT DX,AL
MOV AL,08H
OUT DX,AL
;脉冲2MHz,周期2s
T3:
MOV AL,BL
MOV DX,2A8H
OUT DX,AL;输出到A口
ROL AL,1;左移一位
MOV BL,AL;暂存当前灯的位置

T4:
MOV DX,2A9H;读取两次OUT1状态,判断翻转
IN AL,DX
MOV CL,AL
IN AL,DX
CMP AL,CL ;没翻转,继续循环
JZ T4
JMP TEST1

CODE ENDS
END START

0x03 A/D转换

1.利用0809完成1个通道的模拟量采集,并利用8255输出二进制码。

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
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,283H;初始化8255
MOV AL,10010000B
OUT DX,AL

NEXT:
MOV DX,29CH ;虚写,启动一次转换
OUT DX,AL

TEST0:
MOV DX,280H
IN AL,DX ;A口读入EOC状态
CMP AL,01H ;检查AL的D0是否等于1,若是则转换已经结束
JNZ TEST0 ;如果不是,继续检查

MOV DX,29CH
IN AL,DX ;读入转换后的数据
MOV DX,282H
OUT DX,AL ;C口输出
JMP NEXT

CODE ENDS
END START

2.利用0832产生三角波输出,并在直流电机上观察结果。

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
CODE SEGMENT
ASSUME CS:CODE
BEGIN:
MOV AL,1AH ;下限电压

UP:
MOV DX,290H
OUT DX,AL
MOV DX,291H
OUT DX,AL
MOV BX,20H;两层嵌套循环,软延时
INC AL;自增

DELAY0:
MOV CX,65535

DELAY1:
LOOP DELAY1
DEC BX
JNZ DELAY0

CMP AL,100 ;比较是否达到上限值
JNZ UP ;没到继续上升

DEC AL
DOWN:
MOV DX,290H
OUT DX,AL
MOV DX,291H
OUT DX,AL
MOV BX,20H ;软延时
DEC AL;自减

DELAY2:
MOV CX,65535

DELAY3:
LOOP DELAY3
DEC BX
JNZ DELAY2

CMP AL,19H ;比较是否下降到下限值
JNZ DOWN; 没到继续下降

JMP BEGIN
CODE ENDS
END BEGIN

0x04 键盘

实现扫描键盘上的按键,并在数码管上显示

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
PORT_A EQU 280H
PORT_B EQU 281H
PORT_C EQU 282H
PORT_CTL EQU 283H

DATA SEGMENT
TABLE DB 77H,7BH,7DH,7EH,0B7H,0BBH,0BDH,0BEH,0D7H,0DBH,0DDH,0DEH,0E7H,0EBH,0EDH,0EEH
;TABLE1 DB 40H,79H,24H,30H,19H,12H,02H,78H,00H,18H,08H,03H,46H,21H,06H,0EH;共阴
TABLE1 DB 0BFH,86H,0DBH,0CFH,0E6H,0EDH,0FDH,87H,0FFH,0E7H,0F7H,0FCH,0B9H, 0DEH,0F9H,0F1H
;共阳
DATA ENDS;数据段

STACK SEGMENT STACK;堆栈段
DW 50 DUP(0)
TOP_STACK LABEL WORD;TOP_STACK定义为字类型,偏移地址100
STACK ENDS

CODE SEGMENT;代码段

ASSUME CS:CODE,DS:DATA,SS:STACK
START:
MOV AX,STACK
MOV SS,AX
LEA SP,TOP_STACK
MOV AX,DATA
MOV DS,AX
;初始化8255,B口输入,A,C口输出
MOV DX,PORT_CTL
MOV AL,10000010B
OUT DX,AL
INIT:
MOV DX,PORT_A;A端口输出低电平
MOV AL,00H
OUT DX,AL
MOV DX,PORT_B

WAIT_OPEN:
IN AL,DX;判断按键是否都松开
AND AL,0FH;取低四位(列值)
CMP AL,0FH
JNZ WAIT_OPEN;若有键没有松开,就循环检查

WAIT_PRES:
IN AL,DX;判断是否有键按下
AND AL,0FH;取低四位列值
CMP AL,0FH
JE WAIT_PRES;若没有键按下,则循环检查

MOV CX,16EAH;消除键抖动,延时20ms
DELAY:LOOP DELAY

IN AL,DX;再次检查,看键是否仍被压着
AND AL,0FH
CMP AL,0FH
JE WAIT_PRES

MOV AL,0FEH;先使D0=0
MOV CL,AL;CL=1111 1110B

NEXT_ROW:
MOV DX,PORT_A
OUT DX,AL ;A口第一行输出低电平
MOV DX,PORT_B
IN AL,DX ;B口读取状态
AND AL,0FH;取低四位列值
CMP AL,0FH
JNE ENCODE;不为零表示有键按下,转到ENCODE
ROL CL,01;若无键按下,循环左移,使下一行输出低电平
MOV AL,CL
JMP NEXT_ROW

ENCODE:MOV BX,000FH;从下标F开始
IN AL,DX
NEXT_TRY:CMP AL,TABLE[BX];在表中寻找与读入的状态相等的值
JE DONE;若找到则跳转DONE
DEC BX;没找到,指向下一个地址
JNS NEXT_TRY;没有减到0,则循环检查
MOV AH,01
JMP EXIT;小于零则,报错退出
DONE:
MOV AL,TABLE1[BX];在数码管表中找到相应数字
AND AL,7FH;消除小数点
MOV DX,PORT_C
OUT DX,AL;C口输出,显示在数码管上
JMP INIT;重新循环,读入下一个按键
EXIT:HLT
CODE ENDS
END

进阶区

0x10 来自热心同学小张

​ 要求:当0809 采集数据超过4.5V 时,由 8253 提供 0.5 秒控制 8255 输出8个发光二极管中的红灯闪烁。当低于4.5V时输出正常的二进制值。
​ 0809 地址为 298H~29FH,8253 0 通道地址 2A8H, 8255 控制口地址 293H, 8253 通道 1 工作方式 2,8253 通道 0 工作方式 3。

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
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,293H ;写入8255控制口
MOV AL,10011001B ;控制字,AC输入B输出
OUT DX,AL ;写入控制字
L1: MOV DX,298H ;0809控制
OUT DX,AL ;虚写
L2: MOV DX,292H ;8255 C口,读入0809状态
IN AL,DX
TEST AL,01H
JZ L2 ;测试是否准备好

MOV DX,298H ;
IN AL,DX ;

CMP AL,0E6H ;与4.5V比较 ,小于4.5 跳到 OUT2 转换二进制
JB OUT2
;8253
MOV DX,2ABH ;8235控制口
MOV AL,01110101B ;控制字
OUT DX,AL ;读入控制字
MOV AL,00H ;初值
MOV DX,2A9H ;1 通道 1
OUT DX,AL
MOV AL,10H ;初值
MOV DX,2A9H ;1通道1
OUT DX,AL
MOV DX,2ABH ;控制口
MOV AL,00110111B;控制字
OUT DX,AL
MOV AL,00H ;初值
MOV DX,2A8H ;0 通道 2
OUT DX,AL
MOV AL,10H ;初值
MOV DX,2A8H ; 0通道 2
OUT DX,AL

OUTO:
MOV DX,291H ;8255B口输出
MOV AL,10011100B ;红灯亮
OUT DX,AL

;硬延时判断
MOV DX,290H ;A口读取8253状态
LOOP1:
IN AL,DX
TEST AL,00000001B ;测试高低电频变化
JZ LOOP1

LOOP2:
IN AL,DX
TEST AL,00000001B ;测试高低电频变化
JNZ LOOP2

MOV AL,00H ;灯暗
MOV DX,291H
OUT DX,AL
;硬延时
MOV DX,290H
LOOP3:
IN AL,DX
TEST AL,00000001B ;测试高低电频
JZ LOOP3


LOOP4:
IN AL,DX
TEST AL,00000001B ;测试高低电频变化
JNZ LOOP4

MOV BX,200H
JMP L1 ;跳回,测试0809数值

OUT2:
MOV DX,291H ;直接输出二进制
OUT DX,AL

JMP L1 ;跳回
CODE ENDS
END START


0x02 来自一叶飘零学长

利用0809采集数据,转换后用IN5打到数码管上

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
PORT_A EQU 290H		;8255A口地址
PORT_B EQU 291H ;8255B口地址
PORT_C EQU 292H ;8255C口地址
PORT_CTL EQU 293H ;8255控制口地址
DATA SEGMENT
;数码管表,共阳(实验是共阴,所以要取反)
; 0 1 2 3 4 5 6 7
TUBE DB 40H,79H,24H,30H,19H,12H,02H,78H
; 8 9 A B C D E F
DB 00H,10H,08H,03H,46H,21H,06H,0EH
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DX,AX
MOV DX,PORT_CTL ;初始化8255
MOV AL,10010001B ;A口输入,读值,B口输出,打到数码管,C口输入,PC0接EOC判断用
OUT DX,AL
NEXT: MOV DX,280H ;指向ADC通道0
OUT DX,AL ;启动转换
MOV DX,PORT_C ;指向8255的C口
POLL:
IN AL,DX ;读C口值
TEST AL,01H ;测试PC0是否为1
JZ POLL ;是0,转换未结束,继续等待
MOV AL,10000000B
MOV DX,PORT_C
OUT DX,AL
MOV DX,280H ;是1,转换结束,指向ADC通道0
IN AL,DX ;读取转换后数据
AND AL,0FH ;取低4位
MOV BX,OFFSET TUBE ;指向数码管表
XLAT
NOT AL ;取反
MOV DX,PORT_B ;指向8255的B口
OUT DX,AL ;将低4位值显示在数码管上
MOV BX,15
DELAY: ;双重延时
MOV CX,0FFFFH
DELAY1:
LOOP DELAY1
DEC BX
JNZ DELAY
MOV AL,01000000B
MOV DX,PORT_C
OUT DX,AL
MOV DX,280H ;延时结束后,再指回ADC的通道0
IN AL,DX ;再读一次数据
AND AL,0F0H ;取高4位
MOV CL,4
ROR AL,CL
MOV BX,OFFSET TUBE ;指向数码管表
XLAT
NOT AL ;取反
MOV DX,PORT_B ;指向8255的B口
OUT DX,AL ;将高4位值显示在数码管上
MOV BX,15
DELAY2: ;再次双重延时
MOV CX,0FFFFH
DELAY3:
LOOP DELAY3
DEC BX
JNZ DELAY2
JMP NEXT ;延时结束,跳回NEXT,进行一下轮实现
CODE ENDS
END START

0x03 实现左右轮循环跑马灯

利用8253提供定时时间(2秒),8255输出至发光二极管,显示要求为:从左向右移位显示一次循环,然后从右向左移位显示一次循环。8253控制口地址283H,8255控制口地址293H。

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
ORT_A EQU 290H			;8255A口地址
PORT_B EQU 291H ;8255B口地址
PORT_C EQU 292H ;8255C口地址
PORT_CTL EQU 293H ;8255控制口地址

PORT_1 EQU 280H
PORT_2 EQU 281H
PORT_3 EQU 282H
PORT_CTL2 EQU 283H

STACK SEGMENT STACK
DB 50 DUP(?)
TOP_S LABEL WORD
STACK ENDS

CODE SEGMENT
ASSUME CS:CODE,SS:STACK

START:
MOV AX,STACK
MOV SS,AX
LEA SP,TOP_S

MOV AL,00110101B ;8253的通道0,先送低字节,再送高字节,方式2,BCD码
MOV DX,PORT_CTL2
OUT DX,AL ;8253初始化
MOV AL,00H ;向8253的通道0,N0赋5000
MOV DX,PORT_1
OUT DX,AL
MOV AL,50H
MOV DX,PORT_1
OUT DX,AL

MOV AL,01110111B ;8253的通道1,先送低字节,再送高字节,方式3,BCD码
MOV DX,PORT_CTL2
OUT DX,AL ;8253初始化
MOV AL,00H ;向8253的通道1,N1赋800
MOV DX,PORT_2
OUT DX,AL
MOV AL,08H
MOV DX,PORT_2
OUT DX,AL

MOV DX,PORT_CTL ;8255初始化
MOV AL,10011001B ;B端口输出,A端口控制输入,C端口延时输入
OUT DX,AL
MOV AL,10000000B ;先亮最左边的灯
PUSH AX ;压栈

TEST1:
MOV DX,PORT_B ;B口输出
POP AX ;AL出栈
OUT DX,AL
PUSH AX ;将此时的AL再压栈

cmp AL,00000001B ;看有没有到右边
JZ TEST2 ;到右边了即跳到test2

DELAY1: ;延时
MOV DX,PORT_C
IN AL,DX
AND AL,00000001B ;取PC0
CMP AL,00000001B
JZ DELAY1 ;低电平跳出
DELAY2:
IN AL,DX
AND AL,00000001B ;取PC0
CMP AL,00000001B
JNZ DELAY2 ;高电平跳出


POP AX ;AL出栈
ROR AL,01 ;循环右移
PUSH AX ;AL再压栈
JMP TEST1 ;返回TEST1

TEST2:
MOV DX,PORT_B
POP AX ;此时AL=00000001B
OUT DX,AL ;亮最右边的灯
PUSH AX
CMP AL,10000000B ;看是否亮到了最左边的灯
JZ TEST1 ;是,跳回TEST1

DELAY3:
MOV DX,PORT_C
IN AL,DX
AND AL,00000001B ;取PC0
CMP AL,00000001B
JZ DELAY3 ;低电平跳出
DELAY4:
IN AL,DX
AND AL,00000001B ;取PC0
CMP AL,00000001B
JNZ DELAY4 ;高电平跳出


POP AX
ROL AL,01 ;循环左移
PUSH AX
JMP TEST2

CODE ENDS
END START

0x04记微机实验考试

要求:利用8253提供定时时间(1秒),8255输出为跑马灯形式至发光二极管。显示要求为从左向右每次移2位循环4次,然后以8253以2秒延时从右向左每次移1位循环5次后灯全
亮后停止。控制跑马灯暂停键为K4键,当K4键位时暂停。
8253 控制口地址 2A3H,8255A 口地址 2B0H。

拿到题目的一瞬间全组狂喜,

很简单,8255、8253两个芯片,两个硬延时就可以了

但是一个看似三十分钟程序却做了将近一个半小时,事情是这样的

在写完第一个延时后,本想先测试一下效果,但正常测试几次后LED灯突然就不亮了

???疑惑,研究了好久,写了程序测试小灯、换线,最后直接5v接上,还是不行

而且小灯的迷惑行为止不亮这么简单,它的亮灭随机的,不断调整线的位置并且分析灯的亮灭规律我们断定——箱子坏了

没办法,找老师,老师瞄了一眼,“线有问题,换线就好……”

心态崩了,明知道换线行不通,又不好意思让老师来帮忙找问题,没办法自己来吧

就这样估计半个小时过去了,突然萄萄调线的时候动了一下电源插头

!!!!灯亮了,竟然没想过是电源接触的问题

打扰了,问题解决后

接着很快代码完成,应该是第一组完成

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
CODE SEGMENT
ASSUME CS:CODE
START:
MOV DX,2B3H ;初始化8255
MOV AL,10010010B
OUT DX,AL
MOV AL,80H ;暂存第8个灯,保证起始灯亮
MOV AH,AL
MOV BX,4
TEST1:
;第一级通道0,方式2,先写低字节,后写高字节
MOV AL ,00110101B
MOV DX ,2A3H
OUT DX,AL
MOV AL,00H;计数初值5000
MOV DX ,2A0H
OUT DX,AL
MOV AL,50H
OUT DX,AL
;第二级通道1,方式3,先写低字节,再写高字节
MOV AL,01110111B
MOV DX,2A3H
OUT DX,AL
MOV AL,00H;初值400
MOV DX,2A1H
OUT DX,AL
MOV AL,08H
OUT DX,AL
;脉冲2MHz,周期2s
TEST0:
MOV DX,2B1H ;判断是否是开关K4
IN AL,DX
TEST AL,10H
JZ TEST0
T3:
MOV AL,AH
MOV DX,2B2H
OUT DX,AL;输出到C口
ROR AL,2;右移两位
MOV AH,AL;暂存当前灯的位置
T4:
MOV DX,2B0H ;延时
IN AL,DX
TEST AL,01H
JNZ T4
DEC BX
JNZ TEST1

MOV BX,5
TESTA:
;第一级通道0,方式2,先写低字节,后写高字节
MOV AL ,00110101B
MOV DX ,2A3H
OUT DX,AL
MOV AL,00H;计数初值5000
MOV DX ,2A0H
OUT DX,AL
MOV AL,50H
OUT DX,AL
;第二级通道1,方式3,先写低字节,再写高字节
MOV AL,01110111B
MOV DX,2A3H
OUT DX,AL
MOV AL,00H;初值400
MOV DX,2A1H
OUT DX,AL
MOV AL,16H
OUT DX,AL
;脉冲2MHz,周期4s

TESTB:
MOV DX,2B1H ;判断是否是开关K4
IN AL,DX
TEST AL,10H
JZ TESTB
MOV AL,AH
MOV DX,2B2H
OUT DX,AL;输出到C口
ROL AL,1;左移一位
MOV AH,AL;暂存当前灯的位置
TC:
MOV DX,2B0H ;延时
IN AL,DX
TEST AL,01H
JNZ TC
DEC BX
JNZ TESTA
LOOP1:
MOV AL,0FFH
MOV DX,2B2H
OUT DX,AL;输出到C口
JMP LOOP1

CODE ENDS
END START

遗憾的是老师竟然没问我什么问题,

总的来说考试还算顺利,收拾书包走人…

0x05 小结

从第一次接触汇编到现在也算有点收获,虽然只是一些皮毛

但学习二进制以后还会经常和汇编打交道,现在混个脸熟,将来慢慢深入了解也不迟

暂时告别芯片和箱子,我会想你的,ノBye~