目录
实验内容
实现数学猜想“冰雹猜想”,指:一个正整数 x,如果是奇数就乘以 3 再加 1,如果是偶数 就除以 2,这样经过若干个次,最终一定回到 1。使用实验二的器件和电路,从键盘 输入一个数,模拟上述计算过程并显示。要求使用汇编语言完成。(30 分)
具体要求: 1、 在键盘上输入起始数字,按“等号”开始上述计算过程,每秒显示一个中间结
果, 直到数字变成 1;
2、 一个数字计算完成之后,可以继续进行下一次计算
3、 数据范围:输入数字在 100(十进制)以内,注意到某些数的计算过程中可
能产 生较大的数(100 之内最大的数是从 27 出发,会达到 9232),因此中
间数据要用 16bit 存储;
4、 输入数据为 10 进制,显示数据为 16 进制,不带前导零。
5、 扩展功能:显示使用 10 进制。
注意事项:1、 使用实验二的器件和电路图,不要加其他器件。设计报告中硬件部分可简
化。
2、 避免按键的重复检测;
3、 使用 P0 口连接器件的话,注意加上拉电阻;
4、 “每秒”可以使用定时中断或使用延时完成,不要求时间精确。
主要解决的问题
首先是如何处理超过255的值,因为51单片机的寄存器和内存都是八位的。采用了两个地址分别存储高八位和低八位来解决这个问题。但这样的存储也会带来一些操作和计算上的麻烦,也一一解决了。
对于每个值,在进行奇偶判断时,仅需判断低八位的最后一位。
乘法运算
在进行乘三加一运算时,需要先将低八位和3进行MUL运算,运算后溢出的值存到B中,我们将B存起来,A的值就是乘三后数据的低八位,存到相应的位置(31H)。之后再对高八位进行乘三操作,这里在本实验中不会再溢出,但是要再将第八位的溢出值加上,之后得到乘三后的高八位数据,存到相应的位置(36H)。之后进行加一,对低八位进行加一操作后,再对高八位进行一次ADDC加0操作,如果低八位有进位,那么高八位会加上这一位。至此实现了分两个地址存储数据的乘三加一操作。
除法运算
在进行除二操作时,需要对按顺序对高八位和低八位进行RRC右移操作,这里不能用RR进行右移,而且必须先移动高八位再移动低八位,这样可以确保高八位的最低位移动到低八位的最高位,保证数据的正确性,同时还要注意,高八位右移动之前需要CLR C清除标记位。
两个八位数据在四个数码管上的十进制显示
在进行四位显示时,尤其要处理高八位。我们的办法是,分成千位百位十位个位进行。高八位存储的数据乘以256就是对应的十进制数,加上低八位对应的十进制数字就是最终数据。所以我们将高八位数据乘6模10后得到的就是高八位对应的个位数据,再对低八位模10后就可以得到低八位的个位数据,两者相加并处理好进位即可得到最后的个位,十位百位千位类似,不过要记住处理前一位的进位。51单片机没有除法操作,我们通过减10操作并计算减10的 次数实现了模10得到商和余数的操作。
电路连线
程序框图
主程序的框架是:循环检测,中断显示
实现代码
$NOMOD51
$INCLUDE (8051.MCU)
org 0000h
jmp Start
org 001Bh
LJMP OUT1 ;中断输出程序
org 0100h
Start:
MOV TMOD, #11H
MOV A,#10
MOV 32H,A
MOV A,#10
MOV 33H,A
MOV A,#10
MOV 34H,A
MOV A,#10
MOV 35H,A
;=========================中断程序初始化定义============================
;MOV R0, #32H
MOV TH1, #0D8H ; 将十六进制值 0xD8 赋给 TH1,高字节
MOV TL1, #0F0H ; 将十六进制值 0xF0 赋给 TL1,低字节 共10ms
SETB TR1 ;允许计数
SETB ET1 ;启动计时器1时钟中断
SETB EA ;CPU可以响应中断
;========================键盘输入检测==================================
KEYIN:
CLR P1.0
SETB P1.1 ;判断1.0
SETB P1.2
SETB P1.3
MOV C,P1.4
JNC NUM7
MOV C,P1.5
JNC NUM4
MOV C,P1.6
JNC NUM1
MOV C,P1.7
JNC NUM12 ;清零
CLR P1.1
SETB P1.0 ;判断1.1
MOV C,P1.4
JNC NUM8
MOV C,P1.5
JNC NUM5
MOV C,P1.6
JNC NUM2
MOV C,P1.7
JNC NUM10 ;0
CLR P1.2
SETB P1.1 ;判断1.2
MOV C,P1.4
JNC NUM9
MOV C,P1.5
JNC NUM6
MOV C,P1.6
JNC NUM3
MOV C,P1.7
JNC NUM13 ;等号
CLR P1.3
SETB P1.2 ;判断1.3
MOV C,P1.4
JNC NUM11 ;%除法
MOV C,P1.5
JNC NUM14 ;X乘法
MOV C,P1.6
JNC NUM15 ;-减法
MOV C,P1.7
JNC NUM16 ;+加法
JMP KEYIN
NUM1:MOV R1,#1
JMP _NOP ;检测键盘输入并且赋值
NUM2:MOV R1,#2
JMP _NOP
NUM3:MOV R1,#3
JMP _NOP
NUM4:MOV R1,#4
JMP _NOP
NUM5:MOV R1,#5
JMP _NOP
NUM6:MOV R1,#6
JMP _NOP
NUM7:MOV R1,#7
JMP _NOP
NUM8:MOV R1,#8
JMP _NOP
NUM9:MOV R1,#9
JMP _NOP
NUM10:MOV R1,#0
JMP _NOP
NUM11:MOV R1,#11
JMP _NOP
NUM12: ;清零
JMP START
NUM13:MOV R1,#13 ;等号,进行冰雹算法
JMP HailAlgorithm
NUM14:MOV R1,#14
JMP _NOP
NUM15:MOV R1,#15
JMP _NOP
NUM16:MOV R1,#16
JMP _NOP
_NOP: ;检测是否抬起
MOV A,P1
ANL A,#0F0H
CLR C
SUBB A,#0F0H
JNC ADDRESS_UP
JMP _NOP
;=======================寄存器输出缓冲=========================================
ADDRESS_UP:
MOV A,33H
MOV 32H,A
MOV A,34H
MOV 33H,A
MOV A,35H
MOV 34H,A
MOV A,R1
MOV 35H,A
;MOVX @R0,A
JMP KEYIN
;=======================冰雹算法==============================================
HailAlgorithm:
;先判断输入是否合法
MOV A,35H
CJNE A,#10,HAIL
JMP START
HAIL:
MOV A,34H
CJNE A,#10,JIXU
MOV 34H,#0
JIXU:
MOV A,35H
MOV B,#1
MUL AB
MOV 31H,A
MOV A,34H
MOV B,#10
MUL AB
ADD A,31H
MOV 31H,A
;A存的是十进制数0-99,下面进行循环奇偶判断以及结束判断
AGAIN:
MOV A,31H
CLR C
CJNE A,#01,GOON
MOV 35H,#1 ;显示1,完成冰雹算法
MOV 32H,#10
MOV 33H,#10
MOV 34H,#10
MOV R5,#0FFH
BUXINLE:
CALL DELAY_LONG
CALL DELAY_LONG
DJNZ R5,BUXINLE
JMP START
GOON:
MOV A,31H
ANL A,#01
CLR C
CJNE A,#01,EVEN ;最低位为0,该数为偶数
ODD:;为奇数
MOV A,31H
MOV B,#3
MUL AB
MOV 37H,B ;向高八位的进位,放在37H
MOV 31H,A
MOV A,36H
MOV B,#3
MUL AB
ADD A,37H
MOV 36H,A ;最终的高八位
MOV A,31H
ADD A,#1;暂时假设加一之后A不发生溢出
MOV 31H,A
MOV A,36H
ADDC A,#0 ;如果发生溢出,即加一超过255,那么这个语句会让高八位加一
MOV 36H,A
JMP HailOUT
EVEN:;为偶数
CLR C
MOV A,36H
RRC A
MOV 36H,A
MOV A,31H
RRC A
MOV 31H,A
JMP HailOUT
;=======================冰雹算法中间显示处理====================================
HailOUT:
;进行除法处理,每个数分四位显示
MOV A,#10
MOV 32H,A
MOV A,#10
MOV 33H,A
MOV A,#10
MOV 34H,A
MOV A,#10
MOV 35H,A
;***********低八位************
MOV R0,#0
MOV A,31H ;先处理低八位
MOV B,#10
DIV_LOOP_1:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_1_END
INC R0
JMP DIV_LOOP_1
DIV_LOOP_1_END:
MOV 40H,51H ;得到个位,存在40H
MOV A,R0
MOV R0,#0
DIV_LOOP_2:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_2_END
INC R0
JMP DIV_LOOP_2
DIV_LOOP_2_END:
MOV 41H,51H;得到十位,存在41H
MOV A,R0
MOV R0,#0
DIV_LOOP_3:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_3_END
INC R0
JMP DIV_LOOP_3
DIV_LOOP_3_END:
MOV 42H,51H;得到百位,存在42H
MOV 43H,#0;得到千位,存在43H
;************高八位****************
MOV A,36H ;再处理高八位,依照256的个数处理
MOV B,#6
MUL AB ;这里不会再用到B来计溢出的了,最大是9000,不到40个256,不到40个6
MOV B,#10
MOV R0,#0
DIV_LOOP_5:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_5_END
INC R0
JMP DIV_LOOP_5
DIV_LOOP_5_END:
MOV 44H,51H ;得到个位,存在44H
MOV 50H,R0;用于存储进位
MOV A,36H
MOV B,#5 ;十位
MUL AB
ADD A,50H;加上进位
MOV B,#10
MOV R0,#0
DIV_LOOP_6:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_6_END
INC R0
JMP DIV_LOOP_6
DIV_LOOP_6_END:
MOV 45H,51H ;得到十位,存在45H
MOV 50H,R0;用于存储进位
MOV A,36H
MOV B,#2 ;百位
MUL AB
ADD A,50H;加上进位
MOV B,#10
MOV R0,#0
DIV_LOOP_7:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_7_END
INC R0
JMP DIV_LOOP_7
DIV_LOOP_7_END:
MOV 46H,51H ;得到百位,存在46H
MOV 47H,R0;用于存储进位,这里就是千位了,47H
;********************处理完高八和低八,再进行四位的加法进位*********************
;个位
MOV A,40H
ADD A,44H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R1_OUT
MOV 35H,A
MOV A,41H
INC A
MOV 41H,A
;进行十位
JMP TEN
R1_OUT:
MOV 35H,51H
;十位
TEN:
MOV A,41H
ADD A,45H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R2_OUT
MOV 34H,A
MOV A,42H
INC A
MOV 42H,A
;进行百位
JMP HUNDRED
R2_OUT:
MOV 34H,51H
;百位
HUNDRED:
MOV A,42H
ADD A,46H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R3_OUT
MOV 33H,A
MOV A,43H
INC A
MOV 43H,A
;进行百位
JMP THOUSAND
R3_OUT:
MOV 33H,51H
;千位
THOUSAND:
MOV A,43H
ADD A,47H
MOV 32H,A
MOV R5,#0FH
BUXINLE_2:
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
DJNZ R5,BUXINLE_2
JMP AGAIN
;========================中断显示模块=====================================
OUT1:
MOV SP, #07FH
PUSH PSW
PUSH ACC
MOV TH1, #0D8H ; 重置初值,用于再次计时
MOV TL1, #0F0H
CLR TF1 ;使用时钟1
MOV P0,#0FFH ;一号灯
MOV A,32H
MOV DPTR, #TABLE
MOVC A,@A+DPTR
MOV P0,A
SETB P2.0
CLR P2.1
CLR P2.2
CLR P2.3
CALL DELAY
MOV P0,#0FFH ;二号
MOV A,33H
MOV DPTR, #TABLE
MOVC A,@A+DPTR
MOV P0,A
CLR P2.0
SETB P2.1
CLR P2.2
CLR P2.3
CALL DELAY
MOV P0,#0FFH ;3
MOV A,34H
MOV DPTR, #TABLE
MOVC A,@A+DPTR
MOV P0,A
CLR P2.0
CLR P2.1
SETB P2.2
CLR P2.3
CALL DELAY
MOV P0,#0FFH ;4号灯
MOV A,35H
MOV DPTR, #TABLE
MOVC A,@A+DPTR
MOV P0,A
CLR P2.0
CLR P2.1
CLR P2.2
SETB P2.3
POP ACC
POP PSW
RETI
;============================软件延迟,计时器延迟=======================
DELAY:
MOV R6, #0FH
DELAY_1:
MOV R7, #0FH
DJNZ R7, $
DJNZ R6, DELAY_1
RET
DELAY_LONG:
MOV R6, #0FFH
DELAY_2:
MOV R7, #0FFH
DJNZ R7, $
DJNZ R6, DELAY_2
RET
DELAY_UPDATED:
CLR TF0 ;计时器延迟,T0计时器在TMOD设定时一起启动了,方式一16位
MOV TH0,#0FFH ;255uS
MOV TL0,#0FFH
SETB TR0
LOOP_1:
MOV C,TF0
JC CMPLETE
JMP LOOP_1
CMPLETE:
CLR C
RET
TABLE:
DB 0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H,0FFH
;====================================================================
END
没找到汇编语言的选项(悲)
冰雹猜想实现部分
;=======================冰雹算法==============================================
HailAlgorithm:
;先判断输入是否合法
MOV A,35H
CJNE A,#10,HAIL
JMP START
HAIL:
MOV A,34H
CJNE A,#10,JIXU
MOV 34H,#0
JIXU:
MOV A,35H
MOV B,#1
MUL AB
MOV 31H,A
MOV A,34H
MOV B,#10
MUL AB
ADD A,31H
MOV 31H,A
;A存的是十进制数0-99,下面进行循环奇偶判断以及结束判断
AGAIN:
MOV A,31H
CLR C
CJNE A,#01,GOON
MOV 35H,#1 ;显示1,完成冰雹算法
MOV 32H,#10
MOV 33H,#10
MOV 34H,#10
MOV R5,#0FFH
BUXINLE:
CALL DELAY_LONG
CALL DELAY_LONG
DJNZ R5,BUXINLE
JMP START
GOON:
MOV A,31H
ANL A,#01
CLR C
CJNE A,#01,EVEN ;最低位为0,该数为偶数
ODD:;为奇数
MOV A,31H
MOV B,#3
MUL AB
MOV 37H,B ;向高八位的进位,放在37H
MOV 31H,A
MOV A,36H
MOV B,#3
MUL AB
ADD A,37H
MOV 36H,A ;最终的高八位
MOV A,31H
ADD A,#1;暂时假设加一之后A不发生溢出
MOV 31H,A
MOV A,36H
ADDC A,#0 ;如果发生溢出,即加一超过255,那么这个语句会让高八位加一
MOV 36H,A
JMP HailOUT
EVEN:;为偶数
CLR C
MOV A,36H
RRC A
MOV 36H,A
MOV A,31H
RRC A
MOV 31H,A
JMP HailOUT
;=======================冰雹算法中间显示处理====================================
HailOUT:
;进行除法处理,每个数分四位显示
MOV A,#10
MOV 32H,A
MOV A,#10
MOV 33H,A
MOV A,#10
MOV 34H,A
MOV A,#10
MOV 35H,A
;***********低八位************
MOV R0,#0
MOV A,31H ;先处理低八位
MOV B,#10
DIV_LOOP_1:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_1_END
INC R0
JMP DIV_LOOP_1
DIV_LOOP_1_END:
MOV 40H,51H ;得到个位,存在40H
MOV A,R0
MOV R0,#0
DIV_LOOP_2:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_2_END
INC R0
JMP DIV_LOOP_2
DIV_LOOP_2_END:
MOV 41H,51H;得到十位,存在41H
MOV A,R0
MOV R0,#0
DIV_LOOP_3:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_3_END
INC R0
JMP DIV_LOOP_3
DIV_LOOP_3_END:
MOV 42H,51H;得到百位,存在42H
MOV 43H,#0;得到千位,存在43H
;************高八位****************
MOV A,36H ;再处理高八位,依照256的个数处理
MOV B,#6
MUL AB ;这里不会再用到B来计溢出的了,最大是9000,不到40个256,不到40个6
MOV B,#10
MOV R0,#0
DIV_LOOP_5:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_5_END
INC R0
JMP DIV_LOOP_5
DIV_LOOP_5_END:
MOV 44H,51H ;得到个位,存在44H
MOV 50H,R0;用于存储进位
MOV A,36H
MOV B,#5 ;十位
MUL AB
ADD A,50H;加上进位
MOV B,#10
MOV R0,#0
DIV_LOOP_6:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_6_END
INC R0
JMP DIV_LOOP_6
DIV_LOOP_6_END:
MOV 45H,51H ;得到十位,存在45H
MOV 50H,R0;用于存储进位
MOV A,36H
MOV B,#2 ;百位
MUL AB
ADD A,50H;加上进位
MOV B,#10
MOV R0,#0
DIV_LOOP_7:
MOV 51H,A
CLR C
SUBB A,B
JC DIV_LOOP_7_END
INC R0
JMP DIV_LOOP_7
DIV_LOOP_7_END:
MOV 46H,51H ;得到百位,存在46H
MOV 47H,R0;用于存储进位,这里就是千位了,47H
;********************处理完高八和低八,再进行四位的加法进位*********************
;个位
MOV A,40H
ADD A,44H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R1_OUT
MOV 35H,A
MOV A,41H
INC A
MOV 41H,A
;进行十位
JMP TEN
R1_OUT:
MOV 35H,51H
;十位
TEN:
MOV A,41H
ADD A,45H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R2_OUT
MOV 34H,A
MOV A,42H
INC A
MOV 42H,A
;进行百位
JMP HUNDRED
R2_OUT:
MOV 34H,51H
;百位
HUNDRED:
MOV A,42H
ADD A,46H
MOV B,#10
MOV 51H,A
CLR C
SUBB A,B
JC R3_OUT
MOV 33H,A
MOV A,43H
INC A
MOV 43H,A
;进行百位
JMP THOUSAND
R3_OUT:
MOV 33H,51H
;千位
THOUSAND:
MOV A,43H
ADD A,47H
MOV 32H,A
MOV R5,#0FH
BUXINLE_2:
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
CALL DELAY_LONG
DJNZ R5,BUXINLE_2
JMP AGAIN
代码测试数据有限如有错误以及纰漏欢迎大家指正