A44基于51单片机汇编语言LCD12864简易计算器Proteus设计
作者:单片机仿真   类别:51单片机仿真    日期:2026-10-23 09:34:07    阅读:15 次   消耗积分:12 分

image.png

A44基于51单片机汇编语言LCD12864简易计算器Proteus设计

用51单片机汇编语言做一个简易计算器:4×4矩阵键盘输入数字和运算符,LCD12864液晶显示"数字1:/数字2:/结果"三行,支持加减乘除四则运算。数字在内存里按BCD逐位存放,加法靠ADD加DIV AB取进位,减法先补10再SUBB借位,乘法用MUL AB逐位相乘,除法用长除法一位一位往下除。

一、设计实现功能

本设计功能简介:使用51单片机和汇编语言设计一个简易计算器的proteus仿真,要求以下功能:

1、使用汇编语言编写程序。

2、4×4矩阵键盘输入,0~9数字键、加减乘除键、等号键、清除键。

3、LCD12864液晶显示输入的数字和计算结果。

4、实现8位以内整数的加、减、乘、除四则运算,除法结果带小数。

二、资源汇总

1、仿真文件:Proteus工程,7.8和8.6两个版本都能直接打开。

2、程序文件:main.ASM汇编源码,以及编译好的cx.hex。

3、修改日期小工具:购买资料后赠送,用于修改文件创建日期,下载地址在文章最后。

三、设计介绍

拿到压缩包之后先解压,没有解压软件的直接搜"压缩",下载解压软件后先解压文件,再运行仿真和程序。

图1 Proteus仿真总览

仿真原理图

硬件分三块:LCD12864数据口接P0,控制脚接P2,键盘接P1。LCD12864是并行接口,16个引脚挂上去就行:

信号引脚作用
D0~D7P0.0~P0.78位数据总线
EP2.0使能,下降沿锁存
RWP2.1读/写选择,本设计只写不读
RSP2.20选指令、1选数据
CSBP2.3右半屏片选
CSAP2.4左半屏片选

12864屏幕内部是左右两片64×64的驱动IC,程序里用writeleft和writeleft2两个子程序分别往左半屏和右半屏写字,本质是拉低CSA或CSB再送数据。P0口外接了一个10K排阻上拉,因为P0内部没有上拉电阻,不加上拉屏上什么都不显示。

上电后先LCALL INT初始化液晶,再LCALL CLEAR清屏,然后往指定行列写固定字符"数字1:"、"数字2:"、"结果"。字符不是调字库,是程序里存好的字模:

`asm
mov column3,#0
mov pagef3,#0
mov codes,#0 ;字模编号0 = "数字1:"
lcall writeleft2
mov column,#40
mov pagef,#2
mov codes,#15 ;字模编号15 = "结果"
lcall writeleft
`

pagef是页地址(屏幕纵向8像素为1页),column是列地址,12864每页64列,所以列地址超过63就要换到另一片半屏。这套"列地址+页地址+字模编号"的写法比直接算指令字节直观,改界面只要改这三个数。

键盘是标准的4×4接法,接在P1口,P1.0~P1.3接行、P1.4~P1.7接列。扫描没有用查表,而是用一根"跑零线":

`asm
dd: mov r0,#0f7h ;11110111B,P1.3先拉低
mov r1,#0 ;键值计数器
cc: mov a,r0
mov p1,a
mov a,p1
mov r2,a ;原始读回值存r2
setb c
mov r3,#4
bb: rlc a ;逐位左移找0
jnc aa
ee: inc r1
djnz r3,bb
mov a,r0
setb c
rrc a ;0往右移一位,轮下一行
mov r0,a
jc cc
`

0F7H是P1.3为0、其余为1,读回P1时哪一位变0就说明哪一行哪一列接通。RLC配合进位位C一路数下来,落到第几位R1就加几次,最后R1正好是0~15的键值——按下第3行第2列,R1就是9。松开判断用xrl a,r2比较前后两次读值,相等才算稳定按下,等于软件消抖。

键值直接当功能码用:

键值功能键值功能
0~9数字0~913除号÷
10加号+14等号=
11减号-15清除/复位
12乘号×

按下运算符时INC 51H累计次数:加一次是加法、减两次是减法、乘三次是乘法、除四次是除法,等号按下时按51H的值分派到四段运算程序。这个写法省掉了独立的运算符变量,代价是四种运算的判断必须严格按顺序写,中间漏一个INC就会跳到错误的运算分支。

数字的存放是这套程序最有意思的地方。8位BCD不放在连续单元里,而是故意隔开:

位数数字1数字2
个位40H60H
十位41H71H
百位42H72H
千位44H74H
万位45H75H
十万位46H76H
百万位48H78H
千万位49H79H

跳开43H、47H和73H、77H,是为了避开中断和显示子程序用的工作单元,防止算到一半数字被别的程序改掉。这也是51汇编里很典型的手工分配内存思路。

每按一个数字键,先把已输入的数字整体左移一位(高位往高处搬),再把新键值填到个位。以输入第4位为例:

`asm
AA3: CJNE A,#3,AA5
MOV 42H,41H ;原十位→百位
MOV 41H,40H ;原个位→十位
MOV 40H,R1 ;新键值→个位
LCALL A0
LCALL A1
LCALL A2
LCALL A3
INC 50H
`

50H记当前已经输入了几位,A0~A3是刷新显示的子程序,只重画变动的位,不用整屏刷新,所以按键响应很快。

加法是逐位带进位串起来的,最低位加完用DIV AB取商当进位:

`asm
MOV A,40H
ADD A,60H
MOV B,#10
DIV AB ;A=进位,B=本位结果
MOV 40H,B
ADD A,41H ;上一次的进位加本位
ADD A,71H
MOV B,#10
DIV AB
MOV 41H,B
`

因为BCD每位不超过9,两个数相加最大18,加进位最大19,除以10的商只可能是0或1,正好当进位用。八位一路加下去,最后49H再往上的进位存到0CEH,结果超过8位时靠它显示最高位。

减法反过来,先给被减数补位再减:个位补10,其余位补9,然后SUBB带借位减,DIV AB的商就是借位:

`asm
MOV A,40H
ADD A,#10 ;个位预补10
MOV 40H,A
MOV A,41H
ADD A,#9 ;高位预补9
MOV 41H,A
CLR C
MOV A,40H
SUBB A,60H
MOV B,#10
DIV AB
MOV 40H,B
`

补9而不是补10,是因为高位本身还要借1给低位,补9等于"补10再减1",跟借位正好抵掉。这个技巧在51的BCD减法里用得很多,比逐位判断大小再借位省事。

乘法用MUL AB逐位乘,乘积的十位存进暂存单元91H,累加到下一位:

`asm
MOV B,40H
MOV A,60H
MUL AB
MOV B,#10
DIV AB
MOV 3AH,B ;本位结果
MOV 91H,A ;进位暂存
MOV A,60H
MOV B,41H
MUL AB
MOV B,#10
ADD A,91H ;加上一次的进位
DIV AB
MOV 3BH,B
`

除法是长除法:从最高位开始,取一位除以除数得到商,余数乘10再拉下一位继续除,结果里既有整数部分也有小数部分(69H、6FH、4FH…对应十分位、百分位)。所以这个计算器除不尽时能显示小数,不是直接取整。

结果算完以后,从最高位49H往下找第一个非零位,找到哪一位就跳到对应的显示位置:

`asm
MOV A,49H
CJNE A,#0,CC1
MOV A,48H
CJNE A,#0,CC2
MOV A,46H
CJNE A,#0,CC3
...
`

A00~A08这九个子程序唯一的区别就是column的值(56、48、40…每次减8),一个字模占8列,所以定位到第几位就把列地址设成几倍。这样前导零不会被显示出来,1+2显示"3"而不是"00000003"。

特别注意: 屏幕全黑或者全白,先查P0的上拉排阻有没有接,P0没有内部上拉,悬空时送什么都是乱码;只亮半屏,检查CSA、CSB两个片选,12864是左右两片64×64,写右半屏时CSB要拉低;按键没反应,看P1的接法,行和列接反了扫出来的键值全乱;按键连加好几下,是消抖没做,松开判断要比较前后两次读值;结果显示成乱码,先看数字是不是被写进了43H、47H这些被程序占用的单元;减法出负数,这段程序只处理大减小,被减数小于减数时结果会错,是算法本身的限制,不是bug;除法结果小数位不对,检查余数有没有乘10再拉下一位。

四、日期修改

资料中提供修改日期的小工具,购买资料赠送修改文件创建日期的小工具,三个下载地址都在文章最后。

五、资料下载

付费后获取下载链接,直接下载到电脑上,然后解压即可!每个链接前面都配了二维码,手机扫码可以直接跳转。

/

版权所有,转载本站文章请注明出处:proteus单片机
上一篇:A43基于51单片机汇编语言梁祝音乐盒Proteus设计
下一篇:51单片机汇编系列仿真资料目录(A01~A44)
${comment['nickname']}   ${comment['createtime']}
  
       
${comment.content}
${reply.nickname} 回复 ${comment.nickname}    ${reply.createtime}
     
  
回复内容:${reply.content}