单片机实现简易计算器源代码.docx

上传人:b****2 文档编号:22982552 上传时间:2023-04-29 格式:DOCX 页数:55 大小:36.63KB
下载 相关 举报
单片机实现简易计算器源代码.docx_第1页
第1页 / 共55页
单片机实现简易计算器源代码.docx_第2页
第2页 / 共55页
单片机实现简易计算器源代码.docx_第3页
第3页 / 共55页
单片机实现简易计算器源代码.docx_第4页
第4页 / 共55页
单片机实现简易计算器源代码.docx_第5页
第5页 / 共55页
点击查看更多>>
下载资源
资源描述

单片机实现简易计算器源代码.docx

《单片机实现简易计算器源代码.docx》由会员分享,可在线阅读,更多相关《单片机实现简易计算器源代码.docx(55页珍藏版)》请在冰豆网上搜索。

单片机实现简易计算器源代码.docx

单片机实现简易计算器源代码

单片机实现的简易计算器源代码

                                      

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位有效数字导致了数字123456只能表示为123400,最后两位有效数字被摒弃了。

  同时,虽然纯整数可以进行较为高精度的运算,实现也较为容易,但是考虑到要和浮点数混合在一起处理,如果在算法上分别考虑整数和浮点数,整个程序框架代码将会膨胀不少,因此将其简化为统一作为浮点数对待。

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:

 ;按了

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1