一.大作业简介
1.1大作业目的和要求
《汇编语言与接口技术》是计算机专业的一门重要的专业基础课程。是计算机系统知识中关于软件和硬件分界面相关知识比较集中的一门课程,通过本课程的教学,使学生较深入地掌握微型计算机原理、系统组成以及微型计算机与外界联系的硬件结构和系统技术,完整地了解与计算机硬件直接相关的一门汇编语言,熟悉相关的汇编指令及编程方法,掌握各种典型环境下接口硬件和软件设计方法与应用技术。为培养学生对计算机系统的分析、开发、使用和设计能力打下基础。
通过本课程的学习,学生所具备的素质、掌握的技能、知识和能力:
1. 熟悉微型计算机的硬件结构、工作原理和发展历史;
2. 掌握8086汇编语言的各类指令及编程、汇编、连接和程序调试方法;
3. 掌握8254、8255、8259、串行通信等计算机常用接口的原理和编程方法;
大作业在学习理论和实验两个环节知识的基础上,通过软硬件设计,使学生进一步提高编程调试和接口设计的能力,从而加强学生在面对问题时的分析和动手能力。
1.2 大作业内容
1.2.1题目: 倒计时系统设计
功能描述:
1. 用实验箱中8255、8254、数码管、发光二极管等器件设计相关电路;
2. 设计相关的汇编程序;
3. 实现一位十进制数倒计时显示并控制两个发光二极管交替显示。
编程提示:
1. 电路可部分参照实验电路;
2. 时间控制可以使用软件循环延时,也可以用8254芯片延时(推荐,通过 查询定时计数器输出端状态实现)。
二.设计原理
2.1 程序模块概览
本实验程序主要划分了七个模块,包括接口声明模块,数据预定义模块,LED数码管倒计时模块,指示灯闪烁模块,跳转判断模块,程序退出模块,延时模块。
2.2接口地址声明模块
该模块主要用于声明8255A芯片的硬件地址,便于后续调用。
IOY0 EQU 0E000H ;8255的CS引脚连接IOY0对应的端口始地址
MY8255_A EQU IOY0+00H*4 ; ;8255的端口A地址
MY8255_B EQU IOY0+01H*4 ;8255的端口B地址
MY8255_C EQU IOY0+02H*4 ;8255的端口C地址
MY8255_MODE EQU IOY0+03H*4 ;8255的控制寄存器地址
2.3 数据预定义模块
该模块主要用于缓存待输出的数据,其中BUF中存储偏移量,DSEG中存储待输出的数据,随着变址寄存器SI的变化,取出DSEG中不同偏移地址中的数据用于输出,达到倒计时目的。
DATA SEGMENT
BUF DB 0,1,2,3,4,5,6,7,8,9
DSEG DB 6FH,7FH,07H,7DH,6DH,66H,4FH,5BH,06H,3FH;
VAR1 DW 12H
DATA ENDS
2.4发光二极管控制模块(ATA与BTB)
该模块主要用于控制指示灯(发光二极管)的明灭情况(左边的一个红灯亮或者右边的一个绿灯亮),当每一轮倒计时结束时,将调用该模块,根据计数次数的奇偶性,选择进入子程序(ATA/BTB)
ATA:
MOV DX MY8255_C; 准备用C口输出来做一个指示灯来回闪烁控制
MOV AL 00001000B;
OUT DX,AL;
LEA BX,DSEG; 初始化指针指向的待输出数据为9
LEA SI,BUF
MOV DX,MY8255_A; 准备利用输出A口来控制LED显示内容 JMP AGAIN; 重新进入倒计时循环
BTB:
MOV DX MY8255_C; 准备用C口输出来做一个指示灯来回闪烁控制
MOV AL 00010000B;
OUT DX,AL;
LEA BX,DSEG; 初始化指针指向的待输出数据为9
LEA SI,BUF
MOV DX,MY8255_A 准备利用输出A口来控制LED显示内容
JMP AGAIN; 重新进入倒计时循环
2.5LED数码管倒计时模块(AGAIN)
该模块主要用于控制LED数码管的倒计时显示,主要是通过通用寄存器BX指向段表的首地址,再通过源变址寄存器SI指向缓冲器的首地址,这样通过INC SI 指向偏移地址中的数据,就可以遍历段表中的数据,并且依次取出需要显示的数字,组成倒计时,每次计时从9开始,到0结束,然后进入到跳转判断模块准备进行下一轮循环,倒计时显示过程中调用延时子程序使得倒计时在显示时更加均匀易看清。
AGAIN:
MOV AL,[SI]; 取出当前所要显示的内容
XLAT; 将显示的内容转化为段码即BUF中的内容 OUT DX,AL; 进行内容显示
MOV VAR1,CX 缓存CX的值,防止受其它子程序影响
CALL DELXAY; 呼叫延迟
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
INC VAR1
MOV CX,VAR1 归还CX的值,继续循环
CMP AL,3FH; (3FH代表0)
JE DISPAY; 判断是否倒计时到了0,是否要重新计
INC SI ; 否则就继续向下一个目标数据取数计数
LOOP AGAIN
2.6跳转判断模块:(DISPAY)
该模块主要负责判断要让哪一个指示灯亮起,原理是通过对循环计数器CX的数据进行奇偶性的判断,如果是奇数,那么进入ATA二极管控制模块(红灯亮),反之进入BTB控制模块(绿灯亮)。
DISPAY:
MOV AX,CX 这里是对循环计数器CX的奇偶性做出判断
AND AX,0001H; 原理:末位数位1必为奇数,反之偶数
JE ATA 根据奇偶性,进入ATA/二BTB极管控制模块
JMP BTB; //根据CX的奇偶性来让指示灯来回闪烁
LEA BX,DSEG; //初始化指针指向的待输出数据为9
LEA SI,BUF
MOV DX,MY8255_A; 准备利用输出A口来控制LED显示内容
2.7程序退出模块(QUIT)
该模块主要通过INT 21H 调用了系统中断MOV AX,4C00H其实起作用的就是 AH=4CH,意思就是调用 INT 21H 的 4CH 号中断,该中断就是安全退出程序。
QUIT:
MOV AX,4C00H; 退出程序
INT 21H
2.8延时模块(DELXAY)
该模块主要负责在倒计时过程中延长LED数字灯的显示时间,其原理是通过两个嵌套的循环结构,在循环过程中程序通过多次执行一些耗时的无效操作,例如入栈和出栈,来达到延时的目的。
DELXAY PROC NEAR
PUSH CX
PUSH BX
MOV CX,0FFFH
D1: MOV BX,0FFFH
D2: DEC BX
JNZ D2
LOOP D1
POP BX
POP CX
RET ; //返回到调用子程序的断点处
DELXAY ENDP
三.设计步骤
主要介绍了整个程序对应的实验线路,执行流程及设计思路。
3.1 实验线路(水印原图找不到了...,浅消一下)
![](https://i-blog.csdnimg.cn/blog_migrate/aeaf2133b98f1fab36f455f82317d39f.png)
图3.1.1 实验线路
3.2算法流程图
![](https://i-blog.csdnimg.cn/blog_migrate/3557af87007556b9e3fa83517b46b0d8.png)
图3.2.1 算法流程图
3.3设计思路
主要介绍七个主要程序模块的设计思路,及实现方式。具体的模块代码(配注释)在第二节已经具体展示,请老师批阅时注意向前参考翻阅,此处是对设计思路的概要描述。
①接口声明模块
参考硬件本身物理地址,为地址变量赋值,便于后续调用,数据由实验室提供,
8255的片选信号CS连接系统总线的IOY0,地址为0E000H,因实验系统为32位地址总线,地址宽度为4字节,所以IOY0的低字节应乘以4,不做过多赘述。
②数据预定义模块
参照实验室硬件对应的LED灯采用了共阴极接法,
![](https://i-blog.csdnimg.cn/blog_migrate/c5bfb33a7278728de313b208205904b4.png)
图3.3.1 LED灯引脚图
故欲想要输出对应的数字(9~0),需要取用对应的共阴极字形编码数据存放在DATA中
![](https://i-blog.csdnimg.cn/blog_migrate/460c3dff63263aadded07ca8778c62d6.png)
图3.3.2数据取用
为了在倒计时循环过程中,程序可以依次取用9~0十个数字,预设了BUF起到地址指针的作用,获取DSEG的数据偏移地址,来完成待数据取得。
③LED数码管倒计时模块
由于本次实验选用8255A芯片,其方式控制字对应
![](https://i-blog.csdnimg.cn/blog_migrate/27c953f89af5384af3be966611aa3318.png)
图3.3.3方式控制字原理图
为了能够控制1.指示灯的闪烁,2.LED灯管(1/6)六个中的一个亮,3.LED灯管显示数字,三个方面的控制,所以我选用了三个接口A,B,C作为输出,其中A口主要用于输出倒计时数字,B口用来控制LED灯管(1/6)六个中的一个亮,C口用来负责指示灯的闪烁,最终对应的方式控制字为80H(10000000B),然后,循环通过BX,和SI(每轮自加1),结合XLAT操作获取DATA中待输出的数字,在A口输出内容进行显示,完成倒计时模块基本设计。
④指示灯闪烁模块
为了在每次倒计时9~0结束后,指示灯变化一次(红→绿/绿→红),我分别设计了ATA与BTB,当倒计时结束后,CX为奇数则调用ATA(红亮绿灭)重修进入循环,CX为偶数,则调用BTB(绿灭红亮)重新进入循环,例如在ATA程序中,对接口C进行访存输出 (MOV DX MY8255_C; MOV AL 00010000B; OUT DX,AL;)这样就完成了红亮绿灭操作。
⑤跳转判断模块
由于CX的值在每轮循环之后都会自减1,故在本模块,我主要是想通过在前一个模块的循环计数器CX内的值的奇偶性来完成(ATA/BTB)指示灯闪烁操作的相互转换。奇偶判断由AND AX,H来完成,这是因为二进制数末尾如果是1,那么必定是奇数,所以这样就可以完成判断是让指示灯的红灯或者绿灯来亮。
⑥程序退出模块
通用的退出程序,在循环计数器CX值自减0时,结束整个程序
⑦延时模块
在实验过程中,发现硬件的响应速度极快,如果没有延时程序的设计,将无法得到倒计时效果(程序结束速度极快,LED不跳动(跳动极快,人眼看不清)),故我在程序中嵌套了两个循环,在循环内部多次执行一些无效的操作(例如push,pop)来达到延时目的。
响应速度快的原因:机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,一个机器周期就一般只需要1μs; 指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。一般执行一条指令一般只需1~2 微秒的时间,即程序执行速度很快。
四.实验结果及结果分析
4.1实验结果展示
具体的实验结果展示可以参考视频及图片
![](https://i-blog.csdnimg.cn/blog_migrate/5e186454b07106351a9ae5f6ebbd1eb4.png)
五.实验体会
本次大作业,对我来说是一次对汇编语言整个学习过程的整理,从变量定义到分支结构设计,再到逻辑结构的设置,每一步都需要略带巧思打磨才能设计出合理的汇编程序,这些都在过程中,又一次翻开书本进行复习和糅合,产生新的理解,本次大作业的程序设计过程中,为了避免逻辑结构混乱,我依照从高级语言学习到程序设计思想,对汇编语言采用了模块化的设计结构,具体划分了7个模块,分别负责不同的功能,通过彼此的衔接,共同完成目标任务,每一个模块的设计过程,我都会面临程序与硬件该如何结合的问题,硬件如何响应我的程序,譬如指示灯跳转模块,这一模块,一开始与跳转判断模块结合,试图通过CX的奇偶性来完成指示灯闪烁功能,一开始我才用了DIV命令,试图通过取CX除以2取余数的来完成这一判断,但是实验过程中发现,系统不兼容DIV 命令,一旦使用,程序即刻会退出,无法完成既定要求,在多方搜寻下,最终巧妙的通过AND命令,判断末尾是否为1来判断CX的奇偶性,最终完成了判断和条件转移功能,这样的问题在其它模块中也有遇见,但都在耐心细致的研究与向庄老师不断询问中得到了解决,非常感谢,总的来说,这次实验离不开个人不断的研究学习,和老师的耐心解答,最终能顺利完成本次实验,同时,对汇编语言这一面向机器的程序设计语言有了进一步的理解,丰富了知识储备,希望再接再厉。
六.参考文献
[1]吕宁.具有倒计时功能的单片机交通灯模拟控制系统设计[J].职业,2010(29):176.
[2]yzsorz.微机原理笔记(2)------8255A芯片.https://blog.csdn.net/sinat_36945592/article/details/85684680
七.附录(完整源代码)
IOY0 EQU 0E000H ;8255的CS引脚连接IOY0对应的端口始地址
MY8255_A EQU IOY0+00H*4 ; ;8255的端口A地址
MY8255_B EQU IOY0+01H*4 ;8255的端口B地址
MY8255_C EQU IOY0+02H*4 ;8255的端口C地址
MY8255_MODE EQU IOY0+03H*4 ;8255的控制寄存器地址
STACK1 SEGMENT STACK
DW 256 DP (?)
STACK1 ENDS
DATA SEGMENT
BUF DB 0,1,2,3,4,5,6,7,8,9
DSEG DB 6FH,7FH,07H,7DH,6DH,66H,4FH,5BH,06H,3FH;
VAR1 DW 12H
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
MOV DX,MY8255_MODE; 准备初始化8255A的工作方式
MOV AL,80H; 将ABC口均设为方式0输出
OUT DX,AL; 完成
MOV CX 1000; 希望循环预先设置为100次,用CX来计数
MOV DX,MY_8255_B; 用B口来控制是哪些个LED灯亮
MOV AL 00000001B; 希望仅仅使用LED0来输出
OUT DX,AL; 控制结束
ATA: MOV DX MY8255_C;准备用C口输出来做一个指示灯来回闪烁控制
MOV AL 00001000B;
OUT DX,AL;
LEA BX,DSEG; //初始化指针指向的待输出数据为9
LEA SI,BUF
MOV DX,MY8255_A; 准备利用输出A口来控制LED显示内容
JMP AGAIN;
BTB: MOV DX MY8255_C;准备用C口输出来做一个指示灯来回闪烁控制
MOV AL 00010000B;
OUT DX,AL;
LEA BX,DSEG; //初始化指针指向的待输出数据为9
LEA SI,BUF
MOV DX,MY8255_A; 准备利用输出A口来控制LED显示内容
JMP AGAIN;
DISPAY:
MOV AX,CX 这里是对循环计数器CX的奇偶性做出判断
AND AX,0001H
JE ATA
JMP BTB //根据CX的奇偶性来让指示灯来回闪烁 LEA BX,DSEG; //初始化指针指向的待输出数据为9 LEA SI,BUF MOV DX,MY8255_A; 准备利用输出A口来控制LED显示内容
AGAIN:
MOV AL,[SI]; 取出当前所要显示的内容
XLAT; 将显示的内容转化为段码即BUF中的内容 OUT DX,AL; 进行内容显示
MOV VAR1,CX
CALL DELXAY; 呼叫延迟
CALL DELXAY;
CALL DELXAY; 呼叫延迟
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
CALL DELXAY;
INC VAR1
MOV CX,VAR1
CMP AL,3FH; 判断是否倒计时到了0,是否要重新计数
JE DISPAY; 否则就继续向下一个目标数据取数计数
INC SI
LOOP AGAIN
QUIT: MOV AX,4C00H; 退出程序
INT 21H
DELXAY PROC NEAR
PUSH CX
PUSH BX
MOV CX,0FFFH
D1: MOV BX,0FFFH
D2: DEC BX
JNZ D2
LOOP D1
POP BX
POP CX
RET
DELXAY ENDP
CODE ENDS
END START
CODE ENDS
END START