有简易计算器到复杂计算器的设计说明.docx
《有简易计算器到复杂计算器的设计说明.docx》由会员分享,可在线阅读,更多相关《有简易计算器到复杂计算器的设计说明.docx(33页珍藏版)》请在冰豆网上搜索。
有简易计算器到复杂计算器的设计说明
微机原理实验报告
1.设计任务:
根据微机原理课程所学相关知识及实验教程相关内容,在基于proteus平台,使用汇编语言,以8086为核心的情况下,配合可编程并行接口器件8255A,LED数码管等器件实现可进行简单四位数加减乘除法及清零、乘方、对数、二进制转换等扩展功能的十进制计算器。
2.需求分析:
操控核心为微处理器8086芯片,可编程并行接口芯片8255A
对输入扫描的矩阵按键,显示模块LED数码管,其他辅助器件如74LS138译码器、74LS373等。
3.总体方案(选择与论证)
流程:
第一步,确定键盘是否有输入(使用程序不断进行扫描)。
第二步,如果有输入就调用子程序进行判断,是数值则进行存储并同时进行显示,是运算符号等就调用相应的子程序进行操作。
第三步,继续扫描键盘是否有输入,从而实现4位十进制数以内的加减乘除法或者扩展功能运算。
第四步,运算完成后将运算的结果储存并显示到LED显示器上。
4.硬件设计
实验中根据需求需以下器件:
微处理器8086芯片
当引脚接高电平时,CPU工作于最小模式。
此时,引脚信号24~31的含义及其功能如下:
(1)IO/M/(memoryI/Oselect):
存储器、I/O端口选择控制信号。
信号指明当前CPU是选择访问存储器还是访问I/O端口。
为高电平时访问存储器,表示当前要进行CPU与存储器之间的数据传送。
为低电平时,访问I/O端口,表示当前要进行CPU与I/O端口之间的数据传送。
(2)WR/(write):
写信号,输出,低电平有效。
信号有效时,表明CPU正在执行写总线周期,同时由信号决定是对存储器还是对I/O端口执行写操作。
(3)INTA/(interruptacknowledge):
可屏蔽中断响应信号,输出,低电平有效。
CPU通过信号对外设提出的可屏蔽中断请求做出响应。
为低电平时,表示CPU已经响应外设的中断请求,即将执行中断服务程序。
(4)ALE(addresslockenable):
地址锁存允许信号,输出,高电平有效。
CPU利用ALE信号可以把AD15~AD0地址/数据、A19/S6~A16/S3地址/状态线上的地址信息锁存在地址锁存器中。
(5)DT/(datatransmitorreceive):
数据发送/接收信号,输出,三态。
DT/信号用来控制数据传送的方向。
DT/为高电平时,CPU发送数据到存储器或I/O端口;DT/为低电平时,CPU接收来自存储器或I/O端口的数据。
(6)DEN/(dataenable):
数据允许控制信号,输出,三态,低电平有效。
信号用作总线收发器的选通控制信号。
当为低电平时,表明CPU进行数据的读/写操作。
(7)HOLD(busholdrequest):
总线保持请求信号,输入,高电平有效。
在DMA数据传送方式中,由总线控制器8237A发出一个高电平有效的总线请求信号,通过HOLD引脚输入到CPU,请求CPU让出总线控制权。
(8)HLDA(holdacknowledge):
总线保持响应信号,输出,高电平有效。
HLDA是与HOLD配合使用的联络信号。
在HLDA有效期间,HLDA引脚输出一个高电平有效的响应信号,同时总线将处于浮空状态,CPU让出对总线的控制权,将其交付给申请使用总线的8237A控制器使用,总线使用完后,会使HOLD信号变为低电平,CPU又重新获得对总线的控制权。
可编程并行接口芯片8255A
微机系统的信息交换有两种方式:
并行通信接口方式和串行通信接口方式。
接口电路在CPU和I/O设备之间起着信号的变换和传输的作用。
8255A可为86系列CPU与外部设备之间提供并行输入/输出的通道。
由于它是可编程的,可以通过软件来设置芯片的工作方式,因此,用8255A连接外部设备时,通常不用再附加外部电路,使用教方便。
并行接口是在多根数据线上,以数据字节/字与I/O设备交换信息。
在输入过程中,输入设备把数据送给接口,并且使状态线“输入准备好”有效。
接口把数据存放在“输入缓冲寄存器”中,同时使“输入回答”线有效,作为对外设的响应。
外设在收到这个回答信号后,就撤消数据和“输入准备好”信号。
数据到达接口中后,接口会在“状态寄存器”中设置输入准备好标志,或者向CPU发一个中断请求。
CPU可用查询方式或中断方式从接口中读取数据。
接口中的数据被读取后,接口会自动清除状态寄存器中的标志,且撤消对CPU的中断请求。
在输出过程中,每当输出寄存器可以接收数据,接口就会将状态寄存器中“输出准备好”状态置1或向CPU发一个中断请求,CPU可用查询或中断方式向接口输出数据。
当CPU输出的数据到达接口后,接口会清除“输出准备好”状态,把数据送往外设,并向外设发一个“数据输出准备好”信号。
外设受到驱动后,便接收数据,并向接口电路发一个“输出回答”信号,接口收到该回答信号后,又将状态寄存器中“输出准备好”置位,以便CPU输出下一个数据。
定义工作方式控制字:
LED数码管
LED为发光二极管构成的显示器件,亦称数码管。
由7个字符段和一个小数点段组成,每段对应一个发光二极管,当发光二极管点亮时,相应的字符段点亮。
LED有共阴极和共阳极两种供应状态。
共阴极显示时,将LED显示的COM接地,将八个字符段端a、b、c、d、e、f、g、dp依次与一个8位I/O口的最低到最高位连接,当I/O给LED的哪个字符段送入一个高电平时,该段就被点亮,从而可从这7个字符段中被点亮的构成相应的字符显示出来。
同理,COM阳极即将COM端接Vcc,其显示原理与COM阴极的基本相同,但I/O口送入低电平是相应的段才被点亮。
5.软件设计
程序流程图:
(1)总程序流程图:
(2)键盘扫描程序流程图:
6.具体代码实现
DATASEGMENT
XDB?
?
?
?
;存放数据的每一位
X1DW?
;存放第一个数据值
X2DW?
;存放第二个数据值
YDW?
;存放运算结果
SDB?
;存放运算符号值
EDB?
;按下等号键标记
CCDB?
;存放运算数据位数
HDB0;存放按键行号
LDB0;存放按键列号
Z1DB?
Z2DB?
Z3DB?
Z4DB?
DISCODEDB3FH,06H,5BH,4FH,66H,6DH,7DH,07H,7FH,6FH,77H,7CH,39H,5EH,79H,71H;段码表
DATAENDS
CODESEGMENT
ASSUMECS:
CODE,DS:
DATA
START:
MOVAX,DATA
MOVDS,AX
MOVAL,90H;设置为A口输入,B口输出,C口输出
OUT46H,AL
MOVDI,OFFSETX+3;DI指向X的高位
KKK:
CALLKEY;扫描按键
JMPKKK
;以下为按键扫描子程序,程序返回后,在变量H和L中存放当前按键的行列号
KEYPROC
CHECK:
CALLDISP;等待按键按下的同时进行显示
MOVAL,0F0H;所有行输出低电平
OUT44H,AL
INAL,40H
CMPAL,0FFH;读列值
JZCHECK;若都为高电平则无键按下,等待
MOVCX,100
LOOP$;延时消抖
INAL,DX;重读列值
CMPAL,0FFH
JZCHECK;无键按下一直等待
MOVH,0;有键按下,先把行列号变量清0
MOVL,0
MOVBL,01H
MOVBH,0FEH;扫描法读键值:
从第一行开始测试,即PC0输出低电平
NEXT:
MOVAL,BH
OUT44H,AL
NEXTH:
INAL,40H;读列值,判断是第几列有键按下
TESTAL,BL;从第一列开始判断
JZWAIT0
ROLBL,1
CMPBL,80H;当前行状态下没有任何列有键按下,则转为对下一行的测试
JZNEXTL
INCH;每判断一列,列号加1
JMPNEXTH;再对下一列进行判断
NEXTL:
MOVH,0
MOVBL,01H
ROLBH,1;对下一行测试,让下一个PC口输出低电平
CMPBH,0EFH
JZEXIT
INCL
JMPNEXT
WAIT0:
INAL,40H;若有键按下,则等该按键松开后再计算键值
CMPAL,0FFH
JNZWAIT0
MOVCX,100
LOOP$;延时消抖
INAL,40H
CMPAL,0FFH
JNZWAIT0
CALLKEYVALUE;调计算键值子程序
EXIT:
RET
KEYENDP
;以下为计算键值子程序,通过行列号计算键值(键值=列号*4+行号)
;键值存放在DL寄存器中
KEYVALUEPROC
MOVDL,L
MOVDH,H
SHLDL,1
SHLDL,1;列号乘4
ADDDL,DH
CMPDL,9;按下的是数字键
JNGNUM_CALL
CMPDL,16
JLCONT_CALL;按下的是运算键
CMPDL,16
JZOUTP_CALL;按下的是等于键
CMPDL,17
JZCLR_CALL;按下的是清除键
NUM_CALL:
CALLNUMBER;调数字键处理子程序
JMPEXIT1
CONT_CALL:
MOVS,DL;存放运算键的键值
MOVE,0
CALLCOUNT;调运算键处理子程序,计算第一个加数
JMPEXIT1
OUTP_CALL:
CALLOUTP;调等号键处理子程序
JMPEXIT1
CLR_CALL:
CALLCLEAR;调清除键处理子程序
EXIT1:
RET
KEYVALUEENDP
;以下为清除键处理子程序,按下清除键后,X变量全部清0
CLEARPROC
MOVX[3],0
MOVX[2],0
MOVX[1],0
MOVX[0],0
CALLBITP
RET
CLEARENDP
;以下为等号键处理子程序,该子程序负责将第二个运算数据的数值计算出来存入X2变量
;并根据运算符号,调用相应的运算子程序
OUTPPROC
PUSHAX
PUSHDX
PUSHBX
INCE
CALLCOUNT;调运算键处理子程序,计算第二个运算数据
CMPS,10
JZADD_CALL;运算符为加号,则调用加法子程序
CMPS,11
JZLOG_CALL;运算符为对数,则调用对数子程序
CMPS,12
JZJCE_CALL;运算符为阶乘号,则调用阶乘子程序
CMPS,13
JZDIVP_CALL;运算符为除号,则调用除法子程序
CMPS,14
JZK_CALL
CMPS,15
CALLER
JMPSTORE1
ADD_CALL:
CALLADDP
JMPSTORE1
LOG_CALL:
CALLLOG
JMPSTORE1
JCE_CALL:
CALLJCE
JMPSTORE1
DIVP_CALL:
CALLDIVP
JMPSTORE1
K_CALL:
CALLK
STORE1:
MOVAX,Y;以下程序将各运算子程序返回的运算结果,按位分解,送入X变量
MOVDX,0
MOVBX,1000
DIVBX
MOVX[0],AL
MOVAX,DX
MOVBL,100
DIVBL
MOVX[1],AL
MOVAL,AH
MOVAH,0
MOVBL,10
DIVBL
MOVX[2],AL
MOVX[3],AH
POPBX
POPDX
POPAX
RET
OUTPENDP
;以下为运算键处理子程序,该程序将第一个运算数据的数值计算出来并存入X1变量
;或者将第二个运算数据的数值计算出来并存入X2变量
;将运算符的值存入S变量
COUNTPROC
PUSHAX
PUSHBX
PUSHDX
MOVDX,0
CALLBITP;测试X中的数据是多少位
CMPCC,4;输入的数据是4位数?
JZC4
CMPCC,3;输入的数据是3位数?
JZC3
CMPCC,2;输入的数据是2位数?
JZC2
JMPC1;输入的数据是1位数?
C4:
MOVAX,0
MOVAL,X[0]
MOVBX,1000
MULBX
MOVDX,AX
C3:
MOVAL,X[1]
MOVBL,100
MULBL
ADDDX,AX
C2:
MOVAL,X[2]
MOVBL,10
MULBL
ADDDX,AX
C1:
MOVAL,X[3]
MOVAH,0
ADDDX,AX
CMPE,1
JNZX1_S
MOVX2,DX;按下的是等号,则将第二个运算数据的值存入X2变量
JMPEXIT3
X1_S:
MOVX1,DX;按下的是运算符号,则将第一个运算数据的值存X1变量
MOVX[3],0;清空X变量
MOVX[2],0
MOVX[1],0
MOVX[0],0
EXIT3:
POPDX
POPBX
POPAX
RET
COUNTENDP
;以下为数字键处理子程序
;该程序,将输入的数据按位存放在X变量中,并由CC记录数据的位数
NUMBERPROC
CMPE,1
JNZCONTINUE
MOVE,0
CALLCLEAR
CONTINUE:
CMPCC,0;目前数据为0位,即没有数据,则转到SSS
JZSSS
;若已有数据,以下程序将X左移8位。
;例如:
先输入“1”,当再输入2时,
;先要将“1”从个位移到十位,然后再将“2”存放到个位
PUSHAX
PUSHDX
MOVAL,X[3]
MOVAH,X[2]
MOVDL,X[1]
MOVDH,X[0]
MOVCX,8
LL:
SHLAX,1
RCLDX,1
LOOPLL
MOVX[3],AL
MOVX[2],AH
MOVZ3,AH
MOVX[1],DL
MOVZ2,DL
MOVX[0],DH
MOVZ1,DH
POPDX
POPAX
SSS:
MOV[DI],DL;将当前键入的数据存放到X的最低位
MOVZ4,DL
INCCC;数据位数加1
CMPCC,4;判断数据位数
JNGEXIT2
MOVCC,0;如果数据超过4位,重新从最低位开始存放
MOVX[2],0
MOVX[1],0
MOVX[0],0
EXIT2:
CALLDISP;调显示子程序,显示输入的数据
RET
NUMBERENDP
;加法子程序
ADDPPROC
PUSHAX
MOVAX,X1
ADDAX,X2
MOVY,AX
POPAX
RET
ADDPENDP
;对数子程序
LOGPROC
PUSHAX
PUSHBX
PUSHCX
PUSHDX
MOVAX,X1
MOVBX,0
MOVCX,2
MOVDX,0
LO:
DIVCX
CMPAX,0
JZG2
INCBX
JMPLO
G2:
MOVY,BX
POPDX
POPCX
POPBX
POPAX
RET
LOGENDP
;阶乘子程序
JCEPROC
PUSHAX
PUSHBX
PUSHCX
PUSHDX
MOVAX,X1
MOVDX,AX
SUBDX,1
MOVCX,DX
MOVBX,DX
CHENG:
MULDX
DECBX
MOVDX,BX
LOOPCHENG
MOVY,AX
POPDX
POPCX
POPBX
POPAX
RET
JCEENDP
;除法子程序
DIVPPROC
PUSHAX
PUSHBX
PUSHDX
MOVDX,0
MOVAX,X1
MOVBX,X2
DIVBX
MOVY,AX
POPDX
POPBX
POPAX
RET
DIVPENDP
;次方子程序
KPROC
PUSHAX
PUSHDX
PUSHCX
MOVAX,X1
MOVDX,AX
MOVCX,X2
DECCX
N:
MULDX
MOVDX,X1
LOOPN
MOVY,AX
POPCX
POPDX
POPAX
RET
KENDP
;二进制转换成十进制子程序
ERPROC
PUSHAX
PUSHBX
PUSHCX
MOVBL,8
MOVAL,Z1
MULBL
MOVCX,AX
MOVBL,4
MOVAL,Z2
MULBL
ADDCX,AX
MOVBL,2
MOVAL,Z3
MULBL
ADDCX,AX
MOVAL,Z4
MOVBL,1
MULBL
ADDCX,AX
MOVY,CX
POPCX
POPBX
POPAX
RET
ERENDP
;显示子程序,将X中的数值按位显示出来
DISPPROC
PUSHBX
PUSHAX
MOVBH,0
LEASI,DISCODE
CALLBITP;测试X位数
CMPCC,4
JZQIAN
CMPCC,3
JZBAI
CMPCC,2
JZSHI
CMPCC,1
JMPG
JMPNONE
QIAN:
MOVAH,11100000B;从第4位开始显示
MOVAL,AH
OUT44H,AL
MOVBL,X[0]
MOVAL,[SI+BX]
OUT42H,AL
CALLDELY
MOVAL,0
OUT42H,AL
BAI:
MOVAH,11010000B;从第3位开始显示
MOVAL,AH
OUT44H,AL
MOVBL,X[1]
MOVAL,[SI+BX]
OUT42H,AL
CALLDELY
MOVAL,0
OUT42H,AL
SHI:
MOVAH,10110000B;从第2位开始显示
MOVAL,AH
OUT44H,AL
MOVBL,X[2]
MOVAL,[SI+BX]
OUT42H,AL
CALLDELY
MOVAL,0
OUT42H,AL
G:
MOVAH,01110000B;从第1位开始显示
MOVAL,AH
OUT44H,AL
MOVBL,X[3]
MOVAL,[SI+BX]
OUT42H,AL
CALLDELY
JMPEXIT4
NONE:
MOVAL,0;X中没有数据,不显示
OUT42H,AL
EXIT4:
POPAX
POPBX
RET
DISPENDP
;分析数据位数子程序
BITPPROC
CMPX[0],0;如果X[0]不为0,则数据为4位数
JNZFOURBIT
CMPX[1],0;如果X[1]不为0,则数据为3位数
JNZTHREEBIT
CMPX[2],0;如果X[2]不为0,则数据为2位数
JNZTOWBIT
CMPX[3],0;如果X[3]不为0,则数据为1位数
JNZONEBIT
JMPZER0BIT;否则,没有数据
FOURBIT:
MOVCC,4
JMPEXIT5
THREEBIT:
MOVCC,3
JMPEXIT5
TOWBIT:
MOVCC,2
JMPEXIT5
ONEBIT:
MOVCC,1
JMPEXIT5
ZER0BIT:
MOVCC,0
EXIT5:
RET
BITPENDP
;延时子程序
DELYPROC
PUSHCX
MOVCX,100
LOOP$
POPCX
RET
DELYENDP
CODEENDS
ENDSTART
7.调试与测试
第一步,进行数码管显示的仿真。
编写一段直接赋值送到数码管显示的程序,进行数码管显示的仿真。
编写程序,输入使数码管显示“HELO”的程序,进行仿真,通过多次修改,最终可得结果如图:
第二步,进行键盘扫描的仿真。
编写代码,将扫描到的键值送到数码管显示。
编写程序,使数码管显示所扫描到的键值,进行仿真,通过多次修改可得结果。
测试步骤为:
首先选取任意keypad键盘,连接好电路,按下键盘上数字的8,如图可见,电路线的颜色变化说明产生了脉冲。
松开鼠标后,此时数码管显示为所扫描到的键值:
再换其他案件,并使数码管显示相应扫描到的键值。
第三步,在数码管显示和键盘扫描程序都正确的基础上,逐步增加代码,增加功能,逐步实现按键值的存储与显示、清零、加法、减法、乘法、除法等功能的仿真。
第四步,在确立好了之前的计算器基础应有程序都正确后,又加入了几个扩展模块,再次模拟仿真,将调试不通过的扩展部分删去,只留下可执行的模块。
1.实现二进制与十进制转换功能:
输入二进制111b:
按下二进制转换键:
再按下=号键,可见数码管显示转换后的十进制数:
2.实现求阶乘功能:
1.按下要求的数,数码管开始显示:
2.按下求阶乘按键,可见产生了脉冲:
3.再按下=号键,可见数码管显示结果:
计算器扩展后还有其他扩展功能,在此不作赘述。
8.关键技术
一、键盘扫描
根据如上键盘及电路,可以先扫描列,再扫描行,先给出PC0为低电平,PC1、PC2、PC3均为高电平。
若不按键盘,则PA0、PA1、PA2、PA3、PA4、PA5均为高电平,然后转入下一行测试,给下一行提供低电平、依次类推。
若其中有键按下,则其对应位应显示低电平。
这样,就把按下的键给定位了。
根据以上键盘,通过计算按键的值来定位该位按键。
键值=行*4+列,而行、列值可通过循环来实现。
二、数据存储与显示
首先定义X[0]、X[1]、X[2]、X[3]四个变量,分别存放按下数据的每一位的值,若为数字键,首先按下的数字存放在X[3]中,然后可以通过移位将输入的数据依次存放于X