大学毕设论文8255273实现六位简单计算器微机课程设计报告.docx
《大学毕设论文8255273实现六位简单计算器微机课程设计报告.docx》由会员分享,可在线阅读,更多相关《大学毕设论文8255273实现六位简单计算器微机课程设计报告.docx(33页珍藏版)》请在冰豆网上搜索。
大学毕设论文8255273实现六位简单计算器微机课程设计报告
课程设计报告
(2013—2014年度第一学期)
名称:
微机原理及应用
题目:
8255/273实现六位简单计算器
院系:
控计学院
班级:
创新自动化1101
学号:
1111190324
学生姓名:
杨扬
同组人:
谢伟戈,庄登祥,苏晴
指导教师:
杨国田
设计周数:
1周
成绩:
日期:
2014年1月3日
一、课程设计的目的与要求
目的:
在微机原理及应用课程中分别学过了微机原理各个基本组成模块的原理和编程技术的基础上,综合应用各部分知识,在实验室现有设备的情况下,设计一个具有一定功能的应用系统,达到对各部分知识加深理解、融会贯通的目的,并进一步锻炼学生的动手能力和综合分析能力,同时培养学生的团队精神。
要求每个同学独立完成自己分担的部分,整体方案可以组内同学讨论确定。
要求:
能完成六位十进制数的加、减、乘、除运算以及平方运算,操作过程与普通计算器相同,即先输入一个操作数,然后按下“+”“—”“×”“÷”键,再输入下一个操作数,按等号键开始运算并显示结果,若结果超过六位,则显示“E”。
要求尽量与真实计算器相似。
任务:
我负责的是软件整体构建,和对加法,减法,乘法,除法,平方,清零以及带小数运算程序的编写和调试。
二、设计正文
将可编程外围接口芯片8255A与键盘和七段LED连接,通过对8255A编程及对键盘的操作实现计算功能。
键盘码包括数字0~9、运算符号“+”“-”“*”“/”“=”和清零“CL”键。
首先利用程序不断扫描件键盘是否有输入,如果没有就一直扫描,如果有就停止扫描,完成输入。
通过键盘依次输入第一个运算数字、运算符号、第二个运算数字、“=”,在七段LED灯上显示运算结果,期间数字输入有误可按“C”键之后重新输入。
三、课程设计总结
1.本次课程设计选择了简易计算器设计的题目,不仅使我加深了对接口程序设计的认识,对可编程并行I/O接口芯片8255的工作原理也有了进一步的了解,更重要的是培养了我们发现问题,解决问题的能力。
2.根据微机原理课程所学相关知识及实验教程相关内容,在基于proteus平台,使用汇编语言,以8086为核心的情况下,配合可编程并行接口器件8255A,LED数码管等器件实现可进行简单六位数加减乘除法及清零扩展功能的十进制计算器。
在课程设计实践中,我们不仅锻炼了实际动手能力,培养了团队精神和严肃认真的工作态度,更增强了自己在实际的工程设计中查阅资料,撰写设计报告表达设计思想和结果的能力。
3.在编程过程中,需要很多细节的注意和推敲。
本来很简单的想法,到了实际的编程过程中,就发现并不是那么简单。
如减法的每次循环过程中的借位,时时刻刻都得注意,稍不留神就可能出错。
编程不仅使我们对微机有了更深的理解,也教会了我们不要眼高手低,得脚踏实地,帮我们养成了严谨的思想。
还有,本次课设中有各种新的知识不在课本中,就需要我们去查阅资料,上网搜索之类。
在这个过程中,不仅仅是反映在这几页报告中的知识,更多的也有如protues的作图,仿真过程中的各类问题的解决方法;以及键盘的各类知识。
有些东西,我们天天接触,但要是让我们亲自做一下的时候,可能就会暴露出我们更多的问题。
很感谢能有这样的机会去用已有的知识做一些我们力所能及的事。
四、参考文献
[1]《清华大学TPC-2003A实验指导书》,2006版
[2]李继灿,《新编16/32位微型计算机原理及应用》,清华大学出版社,第四版,2008年
[3]杨国田,高明明《微机原理实验指导书》校内待出版,第一版,2002年3月
附录
1.
软件设计流程图
2.硬件设计概要:
2.1.LED显示的功能及实现
七段LED显示器由七个发光段构成,每段均是一个LED二极管。
这七个发光段分别称为a,b,c,d,e,f,g,通过控制不同段的点亮和熄灭,以显示所要得到的数字。
七段LED的输出功能也是通过8255的并行输出实现。
LED显示数字编码表
0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,0FFH,0FFH,0FFH,0FFH,0FFH,86H,0BFH
显示的字符
H
G
F
E
D
C
B
A
编码
0
1
1
0
0
0
0
0
0
C0H
1
1
1
1
1
1
0
0
1
F9H
2
1
0
1
0
0
1
0
0
A4H
3
1
0
1
1
0
0
0
0
B0H
4
1
0
0
1
1
0
0
1
99H
5
1
0
0
1
0
0
1
0
92H
6
1
0
0
0
0
0
1
0
82H
7
1
1
1
1
1
0
0
0
F8H
8
1
0
0
0
0
0
0
0
80H
9
1
0
0
1
0
0
0
0
90H
-
1
0
1
1
1
1
1
1
BFH
2.2、8255工作原理
2.2.1.8255引脚功能说明:
D0~D7:
数据线,三态双向数8位缓冲器,8255与CPU数据传送的通道,当CPU执行输入输出指令时,通过它实现8位数据的读/写操作,控制字和状态信息也通过数据总线传送。
A0~A1:
地址线,用于选择端口,即用其来选择A口、B口、C口或寄存器控制口。
RD(低电平有效):
读信号线,当这个输入引脚为低电平时,允许8255通过数据总线向CPU发送数据或状态信息,即CPU从8255读取信息或数据。
WR(低电平有效):
写入信号,当这个输入引脚为低电平时,允许CPU将数据或控制字写8255。
CS(低电平有效):
片选信号线,当这个输入引脚为低电平时,表示芯片被选中,允许8255与CPU进行通讯。
RESET(高电平有效):
复位输入线,当该输入端外于高电平时,所有内部寄存器(包括控制寄存器)均被清除,所有I/O口均被置成输入方式。
PA0~PA7:
端口A输入输出线,8位数据输入锁存器和8位数据输出锁存器/缓冲器。
PB0~PB7:
端口B输入输出线,8位数据输入缓冲器和8位数据输出锁存器/缓冲器
PC0~PC7:
端口C输入输出线,端口B输入输出线,8位数据输入缓冲器和8位数据输出锁存器/缓冲器
实际使用时,可以把A口、B口、C口分成两个控制组,即A组和B组。
A组控制电路由端口A和端口C的高4位(PC4~PC7)组成,B组控制电路由端口B和端口才的低4位(PC0~PC3)组成。
2.2.2.8255的读写控制:
8255的读/写控制逻辑电路接受CPU发来的控制口号RD、WR、RESET和地址信号A1~A0。
然后根据命令端口,控制信号的要求,将端口的数据读出选信CPU或者将CPU送来的数据写入端口,各端口的工作状态。
通过用输出指令对8255A的控制字寄存器编程,写入设定工作方式的控制字,可以让3个数据口以不同的方式工作,端口A可工作于3种方式的任一种,端口B只能工作于方式0和方式1,端口C除了用于输入输出端口外,还能配合A口和B口工作,为这两个端口的输入输出操作提供联系信号。
2.2.3.数据总线缓冲器
它是一个双向三态的8位数据缓冲器,8255A正是通过它与系统数据总线相连,用于输入/输出数据以及传送由CPU发给8255A的控制字
2.2.4.定义工作方式控制字
工作方式0:
8255A中各端口的基本输入/输出方式。
2.3微处理器8086芯片
当引脚接高电平时,CPU工作于最小方式(单处理器系统方式,适合于较小规模的应用)。
此时,引脚功能如下:
(1)AD15~AD0:
分时复用的存储器或端口的地址和数据总线。
传送地址时为单向的三态输出,而传送数据时为双向三态输入/输出。
(2)IO/M存储器/输入、输出控制信号(输出、三态):
它用于区分CPU当前是访问存储器还是访问输入/输出端口。
高电表示访问存储器,说明当前要进行CPU与存储器之间的数据传送。
低电平表示访问输入/输出设备。
表示当前要进行CPU与I/O端口之间的数据传送。
在DMA时,它被置为浮空。
(3)WR/LOCK(输出,低电平有效,三态):
信号有效,即为低电平时,表示CPU正在执行存储器或I/O写操作,在写周期中,WR在T2、T2、Tw期间都有效。
在DMA时,WR被置为浮空。
(4)INTA:
可屏蔽中断响应信号,输出,低电平有效。
CPU通过信号对外设提出的可屏蔽中断请求做出响应。
为低电平时,表示CPU已经响应外设的中断请求,即将执行中断服务程序。
(5)ALE:
地址锁存允许信号,输出,高电平有效。
CPU利用ALE信号可以把AD15~AD0地址/数据、A19/S6~A16/S3地址/状态线上的地址信息锁存在地址锁存器中。
(5)DT:
数据发送/接收信号,输出,三态。
DT/信号用来控制数据传送的方向。
DT/为高电平时,CPU发送数据到存储器或I/O端口;DT/为低电平时,CPU接收来自存储器或I/O端口的数据。
(6)DEN:
数据允许控制信号,输出,三态,低电平有效。
信号用作总线收发器的选通控制信号。
当为低电平时,表明CPU进行数据的读/写操作。
(7)HOLD:
总线保持请求信号,输入,高电平有效。
在DMA数据传送方式中,由总线控制器8237A发出一个高电平有效的总线请求信号,通过HOLD引脚输入到CPU,请求CPU让出总线控制权。
(8)HLDA:
总线保持响应信号,输出,高电平有效。
HLDA是与HOLD配合使用的联络信号。
在HLDA有效期间,HLDA引脚输出一个高电平有效的响应信号,同时总线将处于浮空状态,CPU让出对总线的控制权,将其交付给申请使用总线的8237A控制器使用,总线使用完后,会使HOLD信号变为低电平,CPU又重新获得对总线的控制权。
(9)RD:
读控制信号,三态,输出。
当RD=0时,表示CPU执行存储器或I/O端口的读操作。
是对内存单元还是对I/O端口读取数据,取决于M/IO信号。
在执行DMA操作时,RD被浮空。
(10)READY:
“准备好”信号线,输入。
该引脚接受被寻址的内存或I/O端口发给CPU的响应信号,高电平时表示内存或I/O端口已准备就绪,CPU可以进行数据传输。
CPU在T3状态开始对READY信号采样。
若检测到READY为低电平,表示内存或I/O端口尚未准备就绪,则CPU在T3状态之后自动插入等待状态Tw,直到READY信号变为高电平,内存或I/O端口已准备就绪,CPU才可以进行数据传输。
2.4、74LS273锁存器
D0~D7:
出入;
Q0~Q7:
输出;
第一脚WR:
主清除端,低电平触发,即当为低电平时,芯片被清除,输出全为0(低电平);
CP(CLK):
触发端,上升沿触发,即当CP从低到高电平时,D0~D7的数据通过芯片,为0时将数据锁存,D0~D7的数据不变。
3.键盘输入输出模块:
键盘是常用信息输入元件,由一个个按钮组成。
下图是一个4*4键盘结构图,将4*4键盘的八个管脚接8255的PC口,因为进行键盘扫描一般要求有一部分的I/O口工作方式是输入,另一部分I/O是输出,具体到4*4键盘则要求四个I/O口输入,另外四个输出。
行信息连C口低四位,列信息连A口低四位。
当进行扫描时,扫描信号由列引脚输入键盘。
以0111、1011、1101和1110的顺序每次扫描不同的列,然后读取列引脚的信号就可以判断是哪个键被按下。
识别键盘上哪个键被压下的过程的扫描步骤:
1.检测是否所有键都都松开了,若没有则反复检测。
2.但所有键都松开了,再检测是否有键压下,若无键一下则反复检测。
3.如有键压下,要消除键抖动,确认有键压下。
4.对压下的键进行编码,将该键的行列信号转换成16进制码,由此确定哪个键被压下了。
如出现多键重按的情况,只有在其它键均释放后,仅剩一个键闭合时,才把此键当作本次压下的键。
5.该键释放后,再回到2
4.总原理图
3软件设计特点(主要任务):
首先设计程序用到的代码段,数据段,堆栈段。
根据题目要求,我设计10位内存存储运算结果,减小了计算溢出的可能性。
为程序设计初始化主程序,保证程序运行时避免出错。
同时在每个子程序操作时将一些重要寄存器ax,dx等压入堆栈,防止不必要的错误。
对于加减法我通过进位或借位标志进行控制。
对于乘法,我先将内存的数据转换成16进制(乘0ah),并且记录乘数的大小,用于被乘数的累加运算。
我之所以没在乘法中使用16进制的乘法指令是为了防止有一个数超过65536的情况发生,减小错误的几率,并且为我的程序增加了适用范围以及容错性。
对于除法,直接循环利用被除数减去除数即可,利用借位标志退出机制。
在完成加减乘除基本功能的程序后,我又增添了后续的小数功能,将小数与这4个子程序巧妙的联合起来,其中除了除法的功能弱一点,其他都相对完善。
同时我也添加了连续运算的功能,虽然并不能分清优先级别,但是对于简单计算机的性能已有很大的改善。
附图如下:
程序
CLEARMACRO
pushdx
pushcx
pushbx
pushax
movah,6
moval,0
movbh,01h
movcx,0
movdx,184fh
int10h
popdx
popcx
popbx
popax
ENDM
datasegment
shufdw0;当前数标志符
yunfdw0;运算符标志符
fssfdw0;小数点标志符
finfdw0;完成符标识符
fsf0dw0;小数1个数标志符
fsf1dw0;小数2个数标志符
fsfdw0
numb0fdb0;NUMB0清空标志
numb1fdb0;NUMB1清空标志
numb0db10dup(0);第一个运算数
numb1db10dup(0);第二个运算数
numb2db10dup(0);第三个运算数
numb3db10dup(0);小数
fkeydb"error重新输入...$"
dataends
stacksegmentstack
db100dup(0)
stackends
codesegment
assumeds:
data,,ss:
stack,cs:
code
start:
movax,data
movds,ax
;----------------------------------------------------------------------------------------
;各变量初始清0
movsi,0;清空两个运算数
movcx,10
movnumb0,0
movnumb1,0
ini:
movnumb0[si],0
movnumb1[si],0
movnumb2[si],0
incsi
loopini
movshuf,0;当前数置0,表示指向第一个数
movyunf,0;运算符置0,表示没有运算符
movfinf,0;完成符置0,表示没有完成
movfssf,0;置小数点符0,表示没有小数点
movfsf0,0;置小数个数符0,表示没有小数部分
movfsf1,0
movfsf,0
movnumb0f,1;第一个数清空标志置1,表示第一个数被清空
movnumb1f,1;第二个数清空标志置1,表示第二个数被清空
;-----------------------------------------------------------------------------------------
;---------------------------------------------------------------------------------------
ru:
movah,1
int21h
pushax
cmpal,'.';跳转小数部分
jzfskey
cmpal,'+'
jzaddkey;跳转至加法键部分
cmpal,'-'
jzsubkey;跳转至减法键部分
cmpal,'*'
jzmulkey;跳转至乘法键部分
cmpal,'/'
jzdivkey;跳转至除法键部分
cmpal,'c'
jzclrkey;跳转至清除键部分
cmpal,'9'
jbenumkey;跳转至数字键部分
jmpequkey
;-------------------------------------------------------------------------------------
;数字键部分
numkey:
subal,30h
save_numb1:
cmpyunf,0
jzsave_numb0;若没有运算符号则将输入数存入NUMB0
movshuf,1;当前符值1,指向第二个数
movsi,9
cmpnumb1[si],0;若最高位为空,则标志当先数没有存满六位,继续存入
jnzru;否则直接返回输入
cmpnumb1f,1;若数当前被清空过,则直接将输入数存入最低位
jzplace1
;参与运算的小数的总数
movcx,10;逐位前移
movsi,0
cmpfssf,1
jzxsd1
adjust1:
xchgal,numb1[si]
incsi
loopadjust1
movnumb1f,0;将NUMB1F置0,表示第二个数没有清零
jmpru
place1:
movnumb1[0],al
movnumb1f,0
jmpru
save_numb0:
movshuf,0
cmpfinf,0;若完成符为1,表示完成过一次运算,则清空NUMBO
jzsave_next
movsi,1;清空NUMB0
movcx,9
movnumb0,0
save_ini:
movnumb0[si],0
incsi
loopsave_ini
movnumb0f,1
movfinf,0
save_next:
movsi,9;
cmpnumb0[si],0
jnzru
cmpnumb0f,1
jzplace0
movcx,10
movsi,0
cmpfssf,1
jzxsd0
adjust0:
xchgal,numb0[si]
incsi
loopadjust0
movnumb0f,0
jmpru
place0:
movnumb0f,0
movnumb0[0],al
jmpru
xsd1:
addfsf1,1
jmpadjust1
xsd0:
addfsf0,1
jmpadjust0
;小数点部分
fskey:
movfssf,1
jmpru
;等号键部分
equkey:
callcalp
movfinf,1;按下等号则调用CALP运算子程序,
movyunf,0;运算后清空运算符
;置完成符
jmpru
;--------------------------------------------------------------------------------------
;运算符号键部分
addkey:
popax
movfssf,0
cmpyunf,0;若之前没有过运算符,则置运算符
jzplacef
callcalp;若之前有过运算符,则调用CALP进行运算
jmpplacef;运算结束后置当前运算符
subkey:
popax
movfssf,0
cmpyunf,0
jzplacef
callcalp
jmpplacef
mulkey:
popax
movfssf,0
cmpyunf,0
jzplacef
callcalp
jmpplacef
divkey:
popax
movfssf,0
cmpyunf,0
jzplacef
callcalp
jmpplacef
placef:
cmpal,'+'
jzaddf
cmpal,'-'
jzsubf
cmpal,'*'
jzmulf
cmpal,'/'
jzdivf
cmpal,'c'
jzclrkey
addf:
movyunf,1
jmpru;置运算符完毕后返回输入
subf:
movyunf,2
jmpru
mulf:
movyunf,3
jmpru
divf:
movyunf,4
jmpru
clrkey:
clear
movbh,0
movdh,0
movdl,0
movah,2
int10h
jmpstart;按下clear键后跳转至开头,全部清零
;---------------------------------------------------------------------------------------
;运算子程序CALP
calpproc
cmpyunf,0;若运算符为0,则直接转输入
jzyunf_over;否则跳转至结束处ret
cmpyunf,1;根据运算符调用运算子程序
jzaddcal
cmpyunf,2
jzsubcal
cmpyunf,3
jzmulcal
cmpyunf,4
jzdivcal
addcal:
calladdp
jmpyunf_over;调用相应计算子程序
subcal:
callsubp
jmpyunf_over
mulcal:
callmulp
jmpyunf_over
divcal:
calldivp
yunf_over:
ret
calpendp
;-----------------------------------------------------------------------------------------
;加法子程序(带小数)
addpproc
pushax
pushdx
clc
movdx,fsf0
movbx,fsf1;清除进位标志
cmpdx,bx
jnztia