微机原理加法计算器设计及显示.docx
《微机原理加法计算器设计及显示.docx》由会员分享,可在线阅读,更多相关《微机原理加法计算器设计及显示.docx(17页珍藏版)》请在冰豆网上搜索。
微机原理加法计算器设计及显示
微机原理-加法计算器设计及显示
实验报告
课程名称:
微机原理实验指导老师:
成绩:
实验名称:
加法计算器及显示实验类型:
同组学生姓名:
一、实验目的和要求(必填)二、实验内容和原理(必填)
三、主要仪器设备(必填)四、操作方法和实验步骤
五、实验数据记录和处理六、实验结果与分析(必填)
七、讨论、心得
一、实验目的和要求
1.掌握基于状态机的编程方法
2.实现数字运算、键盘输入、LED显示的多任务协调编程
二、实验内容和原理
1.编写程序,输入两个两位十进制数并显示,按确认键后显示运算结果
2.基本功能:
能够输入输入数字(非数字无效)并显示结果
3.附加功能:
光标指示功能(通过LED闪烁实现)以及退格功能
三、程序代码
ORG0000H
START:
MOV78H,#0;初始化:
78H放0的段码,其余放熄灭码
MOV79H,#10
MOV7AH,#10
MOV7BH,#10
MOV7CH,#10
MOVR5,#0;R5是按键次数,初始置0
MOVR6,#0;将0置入R6中
MOVR7,#0;将0置入R7中
MOV30H,#0;30H是功能键存放单元,置为0
MOV31H,#0;31H单元初始置为0
MOV40H,#0;40H单元初始置为0
MOV41H,#0;41H单元初始置为0
LOOP:
LCALLDIR;调用显示子程序
LCALLKEY;调用键盘检测程序
INCR5;按键次数加1
S1:
CJNEA,#10,S2;不是"+"键,跳到S2
LJMPFUN;是"+"键,跳到FUN
S2:
CJNEA,#11,S3;不是"-"键,跳到S3
LJMPFUN;是"-"键,跳到FUN
S3:
CJNEA,#12,S4;不是"*"键,跳到S4
LJMPFUN;是"*"键,跳到FUN
S4:
CJNEA,#13,S5;不是"/"键,跳到S5
LJMPFUN;是"/"键,跳到FUN
S5:
CJNEA,#14,S6;不是"="键,跳到S6
LJMPFUN;是"="键,跳到FUN
S6:
CJNEA,#15,N1;不是"CL"键,跳到N1
LJMPSTART;是"CL"键,跳到START
N1:
CJNER5,#1,N2;若按键次数不等于1,跳到N2
LJMPD11;跳到D11
N2:
CJNER5,#2,START;若按键次数不等于2,跳到START
LJMPT1;跳到T1
D11:
MOVR4,A;将A写入R4
MOV78H,A;输入值送显示个位缓存
MOV79H,#10;将10送到79H单元
LJMPLOOP;跳转到循环
T1:
MOV53H,A;将A写入53H
MOVB,#10;将10置入B
MOVA,R4;将上一次输入的R4写进A
MULAB;A乘以10
ADDA,53H;53H里面的值与A相加
MOVR4,A;将新的值置入到R4
MOV79H,78H;个位到十位
MOV78H,53H;新数为个位
LJMPLOOP;跳转到循环
FUN:
MOV78H,#10;将10置入到78H
MOV79H,#10;将10置入到79H
MOVR0,30H;与上次功能键交换
MOV30H,A
MOVA,R0
CJNEA,#10,FUN1;判断功能键
LJMPADDY;"+"
FUN1:
CJNEA,#11,FUN2
LJMPSUBT;"-"
FUN2:
CJNEA,#12,FUN3
LJMPMULT;"*"
FUN3:
CJNEA,#13,FUN4
LJMPDIVI;"/"
FUN4:
CJNEA,#14,FUN5;首次按功能键,即A=#0
LJMPEQUA;"="
FUN5:
MOV40H,R4;保存第一个数
MOVR5,#0;按键次数清零
LJMPBCD;将其拆为BCD码,以便后来将其显示
OF:
LJMPSTART;跳转回开始
ADDY:
MOVA,40H;加法,第一个数送累加器
ADDA,R4;第一个数加第二个数
MOV40H,A;存本次结果
MOVR5,#0;按键次数清零
LJMPBCD;跳转到BCD程序
SUBT:
MOVA,40H;减法,第一个数送累加器
CLRC;借位清零
SUBBA,R4;带借位的减法,第一个数减第二个数
JBCY,BCD2;借位为1,跳转到BCD2
MOV40H,A;将减的结果送40H
MOVR5,#0;按键次数清零
LJMPBCD;跳转到BCD
MULT:
MOVA,40H;乘法,第一个数送累加器
MOVB,A;将A送B
MOVA,R4;将第二个数送累加器
MULAB;第一个数乘以第二个数
MOVR5,#0;按键次数清零
JBOV,BCD1;若乘法结果溢出,则跳转到BCD1
MOV40H,A;将A送40H
LJMPBCD;跳转到BCD
DIVI:
MOVA,R4;除法,第二个数送累加器
MOVB,A;将第二个数送B
MOVA,40H;将第一个数送A
DIVAB;A除以B
JBOV,OF;当B为0时跳到OF
MOV40H,A;将A送40H
MOVR5,#0;按键次数清零
LJMPBCD;跳转到BCD
EQUA:
MOVR5,#0;按键次数清零
MOV31H,A;将A送31H
LJMPBCD;跳转到BCD
;----乘法溢出时的处理程序
BCD1:
;乘法溢出时的处理程序
MOV78H,B;将高8位送78H
MOV79H,A;将低8位送79H
LCALLHEX2BCD;调用子程序把78H、79H中的数字,转换成BCD码,送到7AH7BH7CH
MOVA,7CH;下面,把万千百十个位,分别存入7CH7BH7AH79H78H
MOVB,#16
DIVAB;除以16,目的是分离出高、低四位
MOV79H,A;存放十位
MOV78H,B;存放个位
MOVA,7AH
MOV7CH,A;存放万位
MOVA,7BH
MOVB,#16
DIVAB
MOV7BH,A
MOV7AH,B
LJMPLOOP
HEX2BCD:
;子程序:
把78H、79H中的数字,转换成BCD码,送到7AH7BH7CH
CLRA
MOV7AH,A;先清零
MOV7BH,A
MOV7CH,A
MOVR6,#16;共转换十六位数
LOOPP:
CLRC
MOVA,79H;从待转换数的高端移出一位到Cy
RLCA
MOV79H,A
MOVA,78H
RLCA
MOV78H,A
MOVA,7CH;送到BCD码的低端
ADDCA,7CH;带进位加。
自身相加,相当于左移一位
DAA;十进制调整,变成BCD码
MOV7CH,A
MOVA,7BH
ADDCA,7BH
DAA
MOV7BH,A
MOVA,7AH
ADDCA,7AH
MOV7AH,A
DJNZR6,LOOPP;共转换十六位数
RET
BCD2:
MOVA,#100;减法第七位有借位时的处理程序
CLRC;借位清零
SUBBA,R4;100-被减数
MOVR4,A;将结果存在R4中
MOVA,40H;将减数给A
ADDA,R4;减数+(100-被减数)
MOVR4,A;将结果给R4
MOVA,#100;将100给A
CLRC;将CY清零
SUBBA,R4;100-(减数+(100-被减数))
MOVB,#10;将10给B
DIVAB;A除以10
MOV7AH,#11;将11给7AH,以便显示符号
MOV79H,A;将A给79H
MOV78H,B;将B给78H
LJMPLOOP;跳转到LOOP
;----拆为BCD码的程序
BCD:
MOVB,#10;将10给B
MOVA,40H;结果送累加器
DIVAB;结果除10
MOV41H,A;41H暂存"商"
MOVA,B;取余数
MOV78H,A;余数送78H
MOVB,#10;将10送B
MOVA,41H;将商送A
DIVAB;A除以10
CJNEA,#0,PANDUAN1;若A不等于0,则跳转到PANDUAN1
MOV79H,B;若A等于0,则将B送79H
LJMPRETURN;跳转到RETURN
PANDUAN1:
MOV7AH,A;A送7AH
MOV79H,B;B送79H
RETURN:
LJMPLOOP;跳转到LOOP
;----动态显示子程序
DIR:
MOVDPTR,#TAB;数码管译码表首址
MOVR0,#78H;待显缓冲区个位地址
CJNER5,#1,ANJIAN2;判断按键次数是否为1,不是则跳转到ANJIAN2
ANJIAN1:
MOVA,@R0;将显示区的个位地址给A
MOVCA,@A+DPTR;查表
CLRP2.3;点亮P2.3
MOVP3,A;字段码送P3口
LCALLDELAY1ms;调延时1ms子程序
SETBP2.3;关闭P2.3
MOVP3,#0FFH;将P3口熄灭
LCALLDELAY1ms;调用延时1ms子程序
;----按键1次时光标闪烁功能
INCR6;将R6加1
CJNER6,#70,SHANSHUO1;若R6不等于70,则跳转到SHANSHUO1
SETBP2.2;将P2.2关闭
MOVP3,#0FFH;将P2口熄灭
LCALLDELAY1ms;调用延时1ms子程序
DECR6;R6就减1
INCR7;R7加1
CJNER7,#70,FANHUI;判断R7是否等于70,若不等于70,则跳转到FANHUI
MOVR6,#0;将R6置0
MOVR7,#0;将R7置0
FANHUI:
RET;子程序返回
SHANSHUO1:
CLRP2.2;打开P2.2
MOVP3,#0EFH;显示“-”
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.2;关闭P2.2
MOVP3,#0FFH;熄灭P3
RET;返回
;----按键次数为2显示
ANJIAN2:
CJNER5,#2,ANJIANDENG;如果R5不等于0,则跳转到ANJIANDENG
MOVA,@R0;将显示区的个位地址给A
MOVCA,@A+DPTR;查表
CLRP2.3;点亮P2.3
MOVP3,A;将个位显示
LCALLDELAY1ms;调用延时1ms
SETBP2.3;关闭P2.3
MOVP3,#0FFH;关闭显示
INCR0;R0加1
MOVA,@R0;将显示区的十位地址给A
MOVCA,@A+DPTR;查表
CLRP2.2;打开P2.2
MOVP3,A;将十位送P3显示
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.2;关闭P2.2
MOVP3,#0FFH;关闭显示
;----按键两次时光标闪烁功能
INCR6;R6加1
CJNER6,#70,SHANSHUO2;判断R6是否为70,若否跳转到SHANSHUO2
SETBP2.1;将P2.1关闭
MOVP3,#0FFH;关闭显示
LCALLDELAY1ms;调用延时1ms子程序
DECR6;R6减1
INCR7;R7加1
CJNER7,#70,FANHUI2;若R7不等于70,则跳转到FANHUI2
MOVR6,#0;将0送R6
MOVR7,#0;将R7置0
FANHUI2:
RET;子程序返回
SHANSHUO2:
CLRP2.1;打开P2.1
MOVP3,#0EFH;显示“-”
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.1;关闭P2.1
MOVP3,#0FFH;关闭显示
RET;返回
;----按“=”键后的显示
ANJIANDENG:
MOVA,31H;将31H送A
CJNEA,#0,ANJIAN0;A不等于0时跳转到ANJIAN0
MOVA,@R0;将个位的地址送A
MOVCA,@A+DPTR;查表
CLRP2.3;打开P2.3
MOVP3,A;显示个位
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.3;关闭P2.3
MOVP3,#0FFH;关闭显示
INCR0;R0加1
MOVA,@R0;将十位的地址送A
MOVCA,@A+DPTR;查表
CLRP2.2;打开P2.2
MOVP3,A;显示十位
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.2;关闭P2.2
MOVP3,#0FFH;关闭显示
INCR0;R0加1
MOVA,@R0;将百位地址送A
MOVCA,@A+DPTR;查表
CLRP2.1;打开P2.1
MOVP3,A;显示百位
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.1;关闭P2.1
MOVP3,#0FFH;关闭显示
INCR0;R0加1
MOVA,@R0;将千位的地址送A
MOVCA,@A+DPTR;查表
CLRP2.0;打开P2.0
MOVP3,A;显示千位
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.0;关闭P2.0
MOVP3,#0FFH;关闭显示
RET;返回
;----没按键时的显示
ANJIAN0:
MOVA,@R0;将R0的地址送A
MOVCA,@A+DPTR;查表
CLRP2.3;打开P2.3
MOVP3,A;显示
LCALLDELAY1ms;调用延时1ms子程序
SETBP2.3;关闭P2.3
MOVP3,#0FFH;关闭显示
RET;返回
TAB:
DB28H,7EH,0A2H,62H,74H,61H,21H,7AH,20H,60H,0FFH,0F7H;共阳极译码表
DELAY1ms:
MOV50H,#2;延时1ms子程序
LOOP1:
MOV53H,#248
NOP
LOOP2:
DJNZ53H,LOOP2
DJNZ50H,LOOP1
RET
DELAY1:
MOV51H,#5;延时子程序DELAY1
DELAY3:
DJNZ51H,DELAY3
RET
;----键盘子程序
KEY:
LCALLKS;调用检测按键子程序
JNZK1;有键按下继续
LCALLDELAY2;无键按调用延时去抖
ACALLDIR;调用动态显示
AJMPKEY;返回继续检测按键
K1:
LCALLDELAY2;有键按下延时去抖动
LCALLKS;再调用检测按腱子程序
JNZK2;确认有按键进行下一步
ACALLDIR;调用动态显示
AJMPKEY;无键按下返回继续检测
K2:
MOVR2,#0EFH;将扫描值送入R2暂存
MOVR3,#00H;将第一列值送入R3暂存
K3:
MOVP1,R2;将R2值送入P1口
L0:
JBP1.0,L1;P1.0等于1跳转到L1
MOVA,#00H;将第一行值送入ACC
AJMPLK;跳转到键值处理程序
L1:
JBP1.1,L2;P1.1等于1跳转到L2
MOVA,#04H;将第二行的行值送入ACC
AJMPLK;跳转到键值处理程序
L2:
JBP1.2,L3;P1.2等于1跳转到L3
MOVA,#08H;将第三行行值送入ACC
AJMPLK;跳转到键值处理程序
L3:
JBP1.3,NEXT;P1.3等于1跳转到NEXT处
MOVA,#0CH;将第四行行值送入ACC
LK:
ADDA,R3;行值与列值相加后的键值送入A
PUSHACC;将A中的值送入堆栈暂存
K4:
LCALLDELAY2;调用延时去抖程序
LCALLKS;调用按键检测程序
JNZK4;按键没有松开继续返回检测
POPACC;将堆栈值送入ACC
MOVDPTR,#KEYTAB
MOVCA,@A+DPTR
RET
NEXT:
INCR3;列值加一
MOVA,R2;R2值送入A
JNBACC.7,KEY;扫描完至KEY处进行下一扫描
RLA;扫描未完将值左移一位进行下一列扫描
MOVR2,A;将ACC值送入R2暂存
AJMPK3;跳转到K3继续
KS:
MOVP1,#0FH;将P1口高四位置0低四位置1
MOVA,P1;读P1口
XRLA,#0FH;将A中的值与A中的值相异或
RET;子程序返回
KEYTAB:
DB1,2,3,10,4,5,6,11,7,8,9,12,15,0,14,13;键值表
DELAY2:
MOV52H,#2H;延时去抖动子程序
LP1:
MOV53H,#0FAH
LP2:
DJNZ53H,LP2
DJNZ52H,LP1
RET
END
四、讨论、心得
本次计算器的实验是一次综合性比较强的实验,对前面所学的知识是一个很好的考察。
里面很多细小的地方在用汇编编程的时候都很有挑战性。
比如开始该如何在数码管上一直显示就困扰了我很长时间;乘法溢出时如何处理也让我考虑了很久。
总之,这次的实验让我对汇编语言的熟悉程度进一步加深,并且对我结构化模块化编程的能力有一定的提高作用。