单片机实现的简易计算器源代码.docx
- 文档编号:5256914
- 上传时间:2022-12-14
- 格式:DOCX
- 页数:44
- 大小:35.91KB
单片机实现的简易计算器源代码.docx
《单片机实现的简易计算器源代码.docx》由会员分享,可在线阅读,更多相关《单片机实现的简易计算器源代码.docx(44页珍藏版)》请在冰豆网上搜索。
单片机实现的简易计算器源代码
单片机实现的简易计算器源代码
2005暑期生产实习单片机实现的简易计算器总结
1.4X4键盘输入,点阵字符型液晶显示。
2.由于所采用的浮点程序库的限制(MCU平台只找到这个……),浮点运算采用3字节二进制补码表示,有效数字6位。
对于输入输出,采用3字节BCD码浮点数格式,有效数字只有4位,因此最终有效数字只有4位。
3.可进行连续输入,例如:
1.23+4.56*8.23/234.8,但是运算结果为从左到右,这也是8位简易计算器的方式。
4.可进行错误判断,溢出、除零等错误将显示一个字符E。
5.由于键盘只有16个按键,安排如下:
+---------------+
|7|8|9|+|
|4|5|6|- |
|1|2|3|* |
|0|. |=|/ |
+---------------+
6.按键的缺少导致取消了一些特殊函数,即开根号,三角函数(sin,cos,tan,ctg)的实现,由于这些函数在浮点程序库中均已提供,如果硬件允许,在原来的框架上添加这些附加功能是很容易的(可以看作和+,-,*,/等价的按键操作,调用不同的子程序进行运算即可)
7.按两次=等于清灵。
因为按键实在太少,才采用了这个做法。
8.相应举例:
按键 结果 说明
-----------------------------------------------
123+= 123 按下等号而没有第二个操作数,保留第一个操作数
并认为此次运算结束(等号的功能)
123+321/111 4.0 等价于(123+321)/111
2.3+5.4=/0.1+ 77 等号后直接按/,则将前面的运算结果作为第一个
操作数
1/0= E 错误显示
9.不足
使用3字节的浮点数表示,不可避免的带来了数表示的不精确,加上有效数字比较少,因此计算结果很容易产生误差,尤其是进行连续多次运算后,结果和精度较高的科学计算器的误差会很快达到0.01以上,当然这个差距和所测试的用例也有关系,4位有效数字导致了数字只能表示为,最后两位有效数字被摒弃了。
同时,虽然纯整数可以进行较为高精度的运算,实现也较为容易,但是考虑到要和浮点数混合在一起处理,如果在算法上分别考虑整数和浮点数,整个程序框架代码将会膨胀不少,因此将其简化为统一作为浮点数对待。
10.源代码
2000行左右(含注释、空行),其中浮点程序库约900行。
其余为键盘输入扫描、液晶输出显示和按键处理程序。
文件大小47.2KB
-=-=-=-=-=-=-=-=-=-=-=-= SOURCECODE=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;;
;;显示程序符号定义
;;
COM EQU 45H
DAT EQU 46H
CW_ADD EQU 5FFCH
CR_ADD EQU 5FFDH
DW_ADD EQU 5FFEH
DR_ADD EQU 5FFFH
;子程序说明:
;寄存器工作组使用
;WAITKEY,00
;KEYPRESSED,MAKENUM,RES2RAW等子程序,01
;FLOATINGLIB,10
;CALCULATE使用01,当调用浮点程序库时10
;显示子程序,11
;======================================================================
;工作区使用注意:
;-=-=1.位寻址区=-=-=-
;20H-21H两个字用作位状态(位地址00H-0FH)
;23H-27H ;NOTUSE!
ESP.23H
;28H-2FH为显示区域与记录输入数字所用,RAWIN
PNTB BIT10H;小数点位指示(位地址,POINTBIT)
POSB BIT11H;位置位,POSB=1表示创建BCD低位,POSB=0表示创建BCD高位
DPB BIT12H ;大于1的浮点数MAKENUM时,指示小数点是否已经加入
;04H-08H,ARBITRARYUSE
BYTE2 BIT14H ;SEEBYTE2USAGE(CTRL+F,FINDIT.)
;STAT保存整个计算器的运行状态!
;BITASSIGNMENT:
; .7:
ERROR
; .6:
FLOAT
; .5&.4:
OPERATOR
; VALUEMEANING:
; 00:
ADD
; 01:
SUB
; 10:
MUL
; 11:
DIV
; .3:
OPERATORPRESSED
; .2:
CONSTRUCTINGNUM2
; .1:
CONSTRUCTINGNUM1
; .0:
EQUALSIGNPRESSED
STAT EQU20H
DCOUNT EQU21H ;数字位数计数(DIGITCOUNT),只是RAWIN中有效字节
INPUT EQU2AH ;键盘输入暂存
RAWPTR EQU2BH ;显示缓冲区指针
NUMPTR EQU2CH ;当前组建数字的指针
TEMP1 EQU2DH ;临时存储,一般用于临时保存R0,R1
TEMP2 EQU2EH ;以切换寄存器组,UNUNSED...07.25.NIGHT
;-=-=2.IRAM=-=-
;30H-33H为第一个操作数
;34H-37H为第二个操作数
;38H-3FH为显示区域
;48H-4FH为临时存储区域
;结果则存储在第一个操作数位置
NUM1 EQU30H
NUM2 EQU34H
RAWIN EQU38H
TEMP EQU48H
;-=-=-=3.REGISTERS=-=-=-
;键盘扫描使用寄存器组0,浮点程序使用寄存器组2
;其余数字组合部分用寄存器组1
;测试程序使用寄存器组3
;ASCIITABLE
;'.'->2EH
;'+'->2BH
;'-'->2DH
;'*'->2AH
;'/'->2FH
;'='->3DH
;////////////////////////////////////////////////////////////////////
;///
;/// THE [MAIN] PROGRAM
;/// ZEROX@2005.7.14
;////////////////////////////////////////////////////////////////////
ORG0000H
LJMPMAIN
ORG0030H
MAIN:
; 全局初始化
MOVSP,#60H ;堆栈
MOVIE,#00H ;禁止所有中断
;寄存器组00
CLRRS1
CLRRS0
;工作区IRAM(20H-5FH)默认全为0
INIT20TO5F:
MOVR0,#20H ;STARTAT20H
MOVR7,#40H ;64BYTESTOZERO
LOOP20TO5F:
MOV@R0,#00H
INCR0
DJNZR7,LOOP20TO5F
;---------------------------------
SETBSTAT.0 ;初始状态为等号状态
MOVR7,#00H
MOVSCON,#00H;串行工作方式0
;-------------------------------------
;;DISPLAYINIT
;-------------------------------------
LCALL LCDINIT
MOV COM,#06H
LCALL PR1
MOV COM,#0C0H
LCALL PR1
MAIN_LOOP:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 键盘输入
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;获取键盘输入,使用寄存器组00
CLRRS1
CLRRS0
;获取输入
MOVA,#0F0H
WAITKEY:
NOP
CJNEA,#0F0H,WAITKEY_OK
LCALLKEY
SJMPWAITKEY
WAITKEY_OK:
MOVA,R7
MOVINPUT,A ;保存键盘输入到INPUT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 按键响应(内部处理)
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;处理键盘输入,使用寄存器组01
CLRRS1
SETBRS0
LCALLKEYPRESSED
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 显 示
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LCALLDISPLAY
SJMPMAIN_LOOP
;========================================================
;==
;== SUBROUTINES
;==
;========================================================
KEYPRESSED:
;键盘输入保存在A中,同时也保存在INPUT中
ANLA,#0F0H ;屏闭低4位字节
JNZNONDIGIT ;高位非零,不是数字
;=========================================
;按键为数字
;否则按下的是数字,添加到显示缓冲区
MOVA,INPUT ;取回数字,高位已经是0
;如果之前处于“等号”状态,则此为NUM1
JBSTAT.0,NEWNUM1
;如果之前处于运算符状态,则此为NUM2
JBSTAT.3,NEWNUM2
;如果处于第一个数字状态
JBSTAT.1,INNUM1
;如果处于第二个数字状态
JBSTAT.2,INNUM2
;否则出错!
!
SETBSTAT.7 ;ERRORBIT
RET ;KEYPRESSED直接结束
;--------------------------
NEWNUM1:
ANLSTAT,#0F0H ;操作状态清零(低4位)
SETBSTAT.1 ;计算器状态改为NUM1
;同时清除浮点运算状态
CLRSTAT.6 ;STAT.6->FLOATINGPOINT
SJMPNEWNUM
NEWNUM2:
ANLSTAT,#0F0H ;操作状态清零(低4位)
SETBSTAT.2 ;计算器状态改为NUM2
SJMPNEWNUM
NEWNUM:
;准备开始一个新的操作数,首先清除显示缓冲区
MOVRAWPTR,#RAWIN;指向开始
;清除小数点标志位
CLRPNTB
MOVDCOUNT,#00H ;数字个数清零
;判断数字是否为0,0则忽略
JZIGNORE0
;非零数字,保存
MOVRAWIN,A ;此时RAWPTR单元的值,也就是地址
;就是RAWIN
INCRAWPTR
;数字位数增1
INCDCOUNT
IGNORE0:
RET
;--------------------------
INNUM1:
INNUM2:
MOVR2,DCOUNT
CJNER2,#08H,INNUM_OK
;数字个数已经达到最大值,忽略本次输入
RET
INNUM_OK:
MOVR0,RAWPTR ;使用R0间接寻址
MOV@R0,A
INCRAWPTR
INCDCOUNT
RET
;=========================================
;按键非数字
NONDIGIT:
MOVA,INPUT ;恢复A
INCA ;'.'用0FFH表示,加1后为0
JZDECPNT ;DECIMALPOINTPRESSED
DECA ;否则不是小数点,减一恢复之
;非数字的情况:
;1.加,减,乘,除:
高4位应该分别为0001,0010,0011,0100
;2.小数点:
代码为0FFH,前面已经考虑
;3.等号:
10000000(80H)
;首先检查是否是等号(最高位为1)
JBACC.7,KEYEQU
;否则作为运算符对待
LJMPKEYOP
;---------------------------------
ERRORND:
;ERROROFNON-DIGIT
;出错…………
SETBSTAT.7
LJMPEXIT
;=======================================================
DECPNT:
;根据计算器状态进行操作
JBSTAT.1,DP1
JBSTAT.2,DP2
JBSTAT.3,DP3
JBSTAT.0,DP0
;ERROR
SETBSTAT.7
LCALLEXIT
DP1:
DP2:
;在数字输入状态下下按下了小数点,如果之前已经按过小数点
;则忽略此次输入,计算器状态字无需修改
JBPNTB,DP_DONE;小数点已经按下
;否则,这是本次操作数输入第一次按下小数点
;首先设置小数点已经按下标志位
SETBPNTB
;否则添加小数点到输入区,也就是显示区
;首先判断第一个数字是不是0
MOVR0,RAWPTR ;获取指针用于比较
;如果当前输入位置不是开始(前面已有非零数字存储),直接添加小数点
CJNER0,#RAWIN,DP_ADD
;否则,RAWPTR还是指向RAWIN位置,第一个数字设置为0,
;后再添加小数点
MOVR0,RAWPTR ;用R0间接寻址
MOV@R0,#00H
INCRAWPTR
INCDCOUNT
DP_ADD:
MOVR0,RAWPTR ;R0间接寻址
MOV@R0,#0FFH ;DECIMALPOINT
INCRAWPTR
INCDCOUNT
DP_DONE:
RET
;--------------------
DP0:
;之前的状态为等号,按下小数点后因该开始第一个操作数输入
;设置状态
ANLSTAT,#0F0H
SETBSTAT.1
SJMPDP_NEW
;--------------------
DP3:
;之前处于操作符状态,按下小数点则应该开始第二个操作数输入
;设置状态
ANLSTAT,#0F0H
SETBSTAT.2
;新的操作数开始
SJMPDP_NEW
;--------------------
DP_NEW:
;小数点开始的新的操作数,添加'0''.'两个输入
;初始化
MOVRAWPTR,#RAWIN
MOVDCOUNT,#00H
CLRPNTB
MOVRAWIN,#00H ;第一个数字,0
INCRAWPTR
INCDCOUNT
MOVR0,RAWPTR ;使用R0间接寻址来存储小数点
MOV@R0,#0FFH ;小数点使用0FFH表示
INCRAWPTR
INCDCOUNT
RET
;=======================================================
KEYEQU:
;保存原来的状态
MOVB,STAT
;设置现在的状态为EQU
ANLSTAT,#0F0H ;清楚低4位状态
SETBSTAT.0 ;EQUSTATBIT
;根据原来的状态采取相应的操作
JBB.1,EQU1 ;原来处于第一个数的输入状态
JBB.2,EQU2 ;原来处于第二个数的输入状态(NORMAL)
JBB.3,EQU3 ;原来处于操作符状态
JBB.0,EQU0 ;原来处于等号状态
;ERROR
SETBSTAT.7
LJMPEXIT
EQU1:
;在第一个数的状态下按了等号,那么第一个数不需要进计算
;直接作为结果显示,实际上RAWIN就是当前的操作数的显示格式
;因此只需要将第一个数转换成浮点数存储于NUM1
SETBRS0
CLRRS1
MOVR0,#RAWIN ;SOURCE
MOVR1,#NUM1 ;DESTINATION
LCALLMAKENUM ;NOTE:
MAKENUM!
!
!
RET
EQU2:
;在第二个数的状态下按了等号,这是最普通的操作
;首先转换操作数二到NUM2位置,然后计算结果
;并将结果转化为RAWIN形式,供DISPLAY显示
MOVR0,#RAWIN
MOVR1,#NUM2 ;DESTINATION
LCALLMAKENUM ;NOTE:
MAKENUM..
;计算结果,结果放在NUM1
LCALLCALCULATE ;NOTE:
CALCULATE!
!
!
;结果转换为RAWIN,即从NUM1到RAWIN
LCALLRES2RAW ;NOTE:
RES2RAW
NOP
RET
EQU3:
;原来状态为操作符,然后直接按了等号
;本程序采取的措施为:
等1号覆盖前面的操作符
;因此不需要采取任何措施,直接同按下了第一个
;操作数后直接按等号相同,由于按下操作符的时候
;已经处理了第一个操作数,因此这里直接返回
RET
EQU0:
;SYSTEMRESET
;原来状态为等号,然后又按了等号
;第一次按等号的时候已经处理好,这里只需返回
;07.24修改,连续两次等号相当于清0
;首先清除错误状态位
CLRSTAT.7
MOVDCOUNT,#00H ;DCOUNT设置为0,显示就为0
RET
;========================================================
;操作符处理,注意:
前面已经判断不是等号
KEYOP:
;保存操作符号:
给定的是10H,20H,30H,40H
;转换为00H,10H,20H,30H.即,减去10H
;DEBUGHERE
CLRC
SUBBA,#10H
;INVARIANT:
除了4,5位,其他位不可能为1
KEYOP_NE:
;KEYOPERATOR,NOERROR
;如果是第一个数之后按的运算符
JBSTAT.1,KOP1
;如果是第二个数之后按的运算符
JBSTAT.2,KOP2
;如果是一个运算符之后按的运算符
JBSTAT.3,KOP3
;如果是按了等号后按的运算符
JBSTAT.0,KOP0
;ERROR
SETBSTAT.7
LJMPEXIT
;------------------
KO_NE_DONE:
;KEYOPERATOR,NOTEQUAL,DONE
;完成相应的操作后,更新STAT到当前状态
;取回INPUT,并减去10H,成为STAT要求的操作符表示
MOVA,INPUT
CLRC
SUBBA,#10H
;运算符信息保存在STAT的4,5位
;先将4,5位清0
ANLSTAT,#0CFH ;#11001111B
ORLSTAT,A ;设置4,5位
;设置新的计算器状态
ANLSTAT,#0F0H ;清除状态(低4位)
SETBSTAT.3 ;操作符号状态
RET ;KEYPRESSED返回
;--------
KOP1:
;如果按了第一个数字之后按了操作符
;则首先将当前显示缓冲区里的数字
;拼合为3字节浮点数
;保存在NUM1位置
;RAWIN保持不变,因此计算器显示的仍然为
;第一个操作数
MOVR0,#RAWIN ;需要进行拼凑的数字
MOVR1,#NUM1 ;目的
LCALLMAKENUM
SJMPKO_NE_DONE
KOP2:
;如果按了第二个数字之后按了操作符,
;首先计算前面的结果,然后结果作为
;第一个数,并设置状态为操作符
;显示区域的数据为前面操作的结果
;即:
需要将3字节的浮点数结果转化
;为可以显示的RAWIN格式。
;创建第二个操作数
MOVR0,#RAWIN
MOVR1,#NUM2
LCALLMAKENUM
;执行计算
LCALLCALCULATE
;结果默认已经存储于到NUM1位置
;但是需要将其转换为RAWIN形式用于DISPLAY子程序的显示
LCALLRES2RAW ;NOTE:
RES2RAW
SJMPKO_NE_DONE
KOP3:
;按了一个操作符后又按了另一个操
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 单片机 实现 简易 计算器 源代码