📄 compulater.txt
字号:
LIST P=16F877
INCLUDE "P16F877.INC"
A1 EQU 21H
A2 EQU 22H
A3 EQU 23H ;扫描后的键的地址值
A4 EQU 24H
G1 EQU 25H
G2 EQU 26H
AA EQU 27H
BUFF EQU 28H
BIT EQU 29H
OUT1 EQU 30H
COUNT EQU 31H ;取数时的四位限制
ADDER0 EQU 32H ;ADDER0-3作为显示缓存区
ADDER1 EQU 33H ;存放将要显示的数字的
ADDER2 EQU 34H ;非压缩BCD码
ADDER3 EQU 35H
ADDER4 EQU 36H ;ADDER4存放键盘输入数字的个数
KEY_ANS EQU 37H ;键的地址翻译后的数值
TEST1 EQU 38H ;和A3内容相同,翻译键址后的数值时用到
DATA0 EQU 39H ;DATA0-3存放 被加数、减数、小数的整数部分
DATA1 EQU 40H
DATA2 EQU 41H
DATA3 EQU 42H
DATB0 EQU 43H ;DATB0-3存放 加数、被减数、小数的整数部分
DATB1 EQU 44H
DATB2 EQU 45H
DATB3 EQU 46H
ANSER0 EQU 47H ;加、减运算结果缓存区
ANSER1 EQU 48H
ANSER2 EQU 49H
ANSER3 EQU 50H
FLAGA EQU 51H ;标志位,加进位,减借位时FLAGA=1
DATC0 EQU 52H ;DATC0-3存乘数、被除数、余数
DATC1 EQU 53H
DATC2 EQU 54H
DATC3 EQU 55H
DATD0 EQU 56H ;DATD0-3存被乘数、除数
DATD1 EQU 57H
DATD2 EQU 58H
DATD3 EQU 59H
DATE0 EQU 60H ;DATE0-3存乘法结果、除数的商
DATE1 EQU 61H
DATE2 EQU 62H
DATE3 EQU 63H
DATF0 EQU 66H ;DATF0-3中间数据暂存区
DATF1 EQU 67H
DATF2 EQU 68H
DATF3 EQU 69H
FLAGB EQU 64H ;如果DATD中的数据为零,则FLAGB=1
FLAGC EQU 65H ;报错标志位,执行ERROR-FUN后,FLAGC=1
FG_DOT EQU 6AH ;小数点标志位,有小数点按下,则FG_DOT=1
DATG0 EQU 6BH ;;DATF0-3中间数据暂存区
DATG1 EQU 6CH
DATG2 EQU 6DH
DATG3 EQU 6EH
;********************MAIN FUNTION*****************************
ORG 000H
MAIN
NOP
CALL LEDD ;初始化LED
AAA CALL INI_ADDER ;显示空字符
CALL PLAY
CALL GET_NUM ;获取键入的数字
DD2 BTFSC FLAGC,0 ;检测,出错则重新开始
GOTO AAA
CALL NEXT_MATH ;翻译符号,进行相关运算处理
;------------------------------
BTFSS FLAGA,0 ;运算出错则重新开始
GOTO BBB
CALL ERROR_FUN
GOTO CCC
BBB
CALL PLAY ;显示结果
CCC CALL EQU_Y_N ;‘=’号按下后,重新开始
GOTO AAA
GOTO ENDD
; 01-funtion************keyboard number**********************
KEYNUM NOP
STA BCF STATUS,RP1
BSF STATUS,RP0 ;设置为体1
MOVLW 0F0H
MOVWF TRISD ;设置RD口低四位为输出,高四位为输入
BCF STATUS,RP0 ;设置为体0
;-------------just if the key is-on-------
IFON MOVLW 00H
MOVWF PORTD ;将低四位全部输出0
MOVF PORTD,W ;将高四位输入给W
IORLW 0FH ;屏蔽低四位
MOVWF A4
COMF A4,1 ;判断高四位输入中是否有键按下
BTFSC STATUS,Z ;若Z=1,表明无键按下,跳回IFON继续
GOTO IFON ;扫描直至有键按下
CALL DELAY ;否则延时后再次扫描
IFON2 MOVLW 00H
MOVWF PORTD
MOVF PORTD,W
IORLW 0FH
MOVWF A4
COMF A4,1
BTFSS STATUS,Z ;再次扫描后,仍有键按下,则跳到KEYSCAN
GOTO KEYSCAN ;没有的话则延时后继续扫描
CALL DELAY
GOTO IFON
;------------KEYNUMBER-----------------------
KEYSCAN
MOVLW 0EH ;RD1-3口输出高电平,RD0口输出低电平,判段该行
MOVWF A1 ;是否有键按下
MOVWF PORTD
MOVF PORTD,W
ANDLW 0F0H ;屏蔽掉高四位
MOVWF A2 ;输出A2
XORLW 0F0H ;屏蔽掉低四位
BTFSS STATUS,Z ;有键按下时,Z=0,则跳转到KEYON
GOTO KEYON ;无键按下时,Z=1,继续扫描下一行
MOVLW 0DH ;RD0、2、3口输出高电平,RD1口输出低电平
MOVWF A1
MOVWF PORTD
MOVF PORTD,W
ANDLW 0F0H
MOVWF A2
XORLW 0F0H
BTFSS STATUS,Z
GOTO KEYON
MOVLW 0BH ;RD0、1、3口输出高电平,RD2口输出低电平
MOVWF A1
MOVWF PORTD
MOVF PORTD,W
ANDLW 0F0H
MOVWF A2
XORLW 0F0H
BTFSS STATUS,Z
GOTO KEYON
MOVLW 07H ;RD0、1、2口输出高电平,RD3口输出低电平
MOVWF A1
MOVWF PORTD
MOVF PORTD,W
ANDLW 0F0H
MOVWF A2
XORLW 0F0H
BTFSS STATUS,Z
GOTO KEYON
GOTO STA
KEYON MOVF A1,0
ADDWF A2,W
MOVWF A3 ;把扫描到的键值存入A3
;---------------wait for keyboard off----------
IFOFF MOVLW 00H ;判断按下的键是否已经起来,并通过延时来防抖
MOVWF PORTD
MOVF PORTD,W
IORLW 0FH
MOVWF A4
COMF A4,1
BTFSS STATUS,Z ;键已起来则Z=1,延时后再扫描
GOTO IFOFF
CALL DELAY
CALL DELAY
IFOFF2 MOVLW 00H
MOVWF PORTD
MOVF PORTD,W
IORLW 0FH
MOVWF A4
COMF A4,1
BTFSS STATUS,Z ;再次扫描仍键已起来则RETURN
GOTO IFOFF
RETURN
; 02-funtion************ 将扫描得到的键地址翻译成数字
TRANSK NOP
MOVF A3,0
MOVWF TEST1
BTFSS TEST1,3 ;如果是符号
RETURN
BTFSS TEST1,2 ;键的低四位的地址是 _BH
GOTO NEXT2
BTFSS TEST1,1 ;键的低四位的地址是 _DH
GOTO NEXT1
BTFSS TEST1,0 ;键的低四位的地址是 _EH
GOTO NEXT0
GOTO NEXT_END
NEXT2 ;test 7-4, _BH
BTFSC TEST1,5
GOTO NEXT25
CLRF KEY_ANS ;DBH <=> 00
NEXT25 BTFSC TEST1,4
GOTO NEXT_END
MOVLW 09H
MOVWF KEY_ANS ;EBH <=> 09
GOTO NEXT_END
NEXT1 BTFSC TEST1,7 ;test 7-4, _DH
GOTO NEXT16
MOVLW 08H
MOVWF KEY_ANS ; 7DH <=> 08
GOTO NEXT_END
NEXT16 BTFSC TEST1,6
GOTO NEXT15
MOVLW 07H
MOVWF KEY_ANS ; BDH <=> 07
GOTO NEXT_END
NEXT15 BTFSC TEST1,5
GOTO NEXT14
MOVLW 06H
MOVWF KEY_ANS ; DDH <=> 06
GOTO NEXT_END
NEXT14 BTFSC TEST1,4
GOTO ERROR_1
MOVLW 05H
MOVWF KEY_ANS ; EDH <=> 05
GOTO NEXT_END
NEXT0 BTFSC TEST1,7 ;test 7-4, _EH
GOTO NEXT06
MOVLW 04H
MOVWF KEY_ANS ; 7EH <=> 04
GOTO NEXT_END
NEXT06 BTFSC TEST1,6
GOTO NEXT05
MOVLW 03H
MOVWF KEY_ANS ; BEH <=> 03
GOTO NEXT_END
NEXT05 BTFSC TEST1,5
GOTO NEXT04
MOVLW 02H
MOVWF KEY_ANS ; DEH <=> 02
GOTO NEXT_END
NEXT04 BTFSC TEST1,4
GOTO ERROR_1
MOVLW 01H
MOVWF KEY_ANS ; EEH <=> 01
GOTO NEXT_END
NEXT_END
NOP
RETURN
; 03-funtion******************************************************
GET_NUM CLRF FLAGC
CLRF FG_DOT
LL2 CALL INI_ADDER
CALL PLAY
MOVLW 05H ;5给计数器COUNT,限制只能取四位数
MOVWF COUNT
LL1 CALL KEYNUM ;调用取键值子程序
;-------IF the num we get is not the signal__go on----------
MOVF A3,0
MOVWF TEST1
BTFSS TEST1,3 ;检测有运算符号按下时跳到END1
GOTO END_1
BTFSC TEST1,2
GOTO NNEXT
BTFSS TEST1,7
GOTO END_1 ;检测有等号按下时跳到END1
BTFSC TEST1,6
GOTO NNEXT
CALL DOT_FUN ;检测到小数点时,执行相应程序并显示
CALL PLAY
GOTO LL1
;----------------------------------------
NNEXT CALL TRANSK ;调用翻译键值子程序
CALL ANS_ADDER
CALL PLAY ;将结果显示
DECFSZ COUNT,1 ;计数器减一
GOTO LL1 ;不为0则继续取下一位
GOTO LL2 ;为0则说明已超过四位,重新开始取值
END_1 NOP
MOVF ADDER4,0 ;检测第一次按下运算符号或等号时报错
IORLW 00H ;不是第一次按下则返回,即检测到符号时表明输入数结束
BTFSS STATUS,Z
GOTO END_2
CALL ERROR_FUN
BSF FLAGC,0
END_2 RETURN
; 04-funtion********Calculation funtion***********翻译运算符号
NEXT_MATH
BTFSC FG_DOT,0 ;如果有小数点,则执行小数的相应程序
GOTO M_DOT
BTFSS TEST1,3 ;检测 ,是运算符号,则执行相应跳转
GOTO MATH7
GOTO FUN_RET ;不是运算符号,则返回
MATH7 BTFSC TEST1,7 ;如果‘除’号
GOTO MATH6
CALL DIVI_FUN ;执行‘除’法程序
GOTO FUN_RET
MATH6 BTFSC TEST1,6 ;如果‘乘’号
GOTO MATH5
CALL MULT_FUN ;执行‘乘’法程序
GOTO FUN_RET
MATH5 BTFSC TEST1,5 ;如果‘减’号
GOTO MATH4
CALL SUB_FUN ;执行‘减’法程序
GOTO FUN_RET
MATH4 BTFSC TEST1,4 ;如果‘加’号
GOTO FUN_RET
CALL ADD_FUN ;执行‘加’法程序
GOTO FUN_RET
M_DOT BTFSC TEST1,7 ;小数‘除’法
GOTO MAT_6
BSF FLAGA,0 ;强行报错,返回
GOTO FUN_RET
MAT_6 BTFSC TEST1,6 ;小数‘乘’法
GOTO MAT_5
BSF FLAGA,0 ;强行报错,返回
GOTO FUN_RET
MAT_5 BTFSC TEST1,5 ;如果‘减’号
GOTO MAT_4
CALL SUB_DOTT ;小数‘减’法
GOTO FUN_RET
MAT_4 BTFSC TEST1,4 ;如果‘加’号
GOTO FUN_RET
CALL ADD_DOTT ;小数‘加’法
FUN_RET NOP
RETURN
;************ addition funtion ************************************************
; 05-funtion*****************ADD_PREPARE****************
ADD_FUN NOP ;加法准备函数
CLRF DATA0
CLRF DATA1
CLRF DATA2
CLRF DATA3 ;DATA清零
CLRF DATB0
CLRF DATB1
CLRF DATB2
CLRF DATB3 ;DATB清零
CALL ADDER_A ;把显示缓存区的内容‘被加数’给DATA
CALL GET_NUM ;取‘加数’
CALL ADDER_B ;把显示缓存区的内容‘加数’给DATB
CALL INI_ADDER ;清屏
CALL ADD_A_B ;计算DATA+DATB=ANSER
CALL RES_ADDER ;把结果ANSER给显示缓存区
RETURN
; 06-funtion********************** ADDTION ****************
ADD_A_B NOP ;计算DATA+DATB
MOVLW 06H
ADDWF DATA0,0
ADDWF DATB0,0 ;计算个位数相加
MOVWF ANSER0 ;ANSER0=DATA0+DATB0+6
BTFSS STATUS,DC
GOTO A_DD2 ;DC=0,没有进位则减六
MOVLW 01H ;有进位则FLAGA=1
MOVWF FLAGA
MOVF ANSER0,W ;保证ANSER0中存放的是非压缩BCD码
ANDLW 0FH
MOVWF ANSER0
GOTO JIA_1 ;继续进行十位数的相加
A_DD2 MOVLW 06H
SUBWF ANSER0,1 ;没有进位则ANSER0=ANSER0-6
MOVLW 00H
MOVWF FLAGA ;没有进位则FLAGA=0
JIA_1 MOVLW 06H ;十位数相加(原理同个位数)
ADDWF DATA1,0
MOVWF ANSER1
MOVF FLAGA,0
ADDWF DATB1,0
ADDWF ANSER1,1
BTFSS STATUS,DC
GOTO A_DD3 ;DC=0
MOVLW 01H
MOVWF FLAGA
MOVF ANSER1,W
ANDLW 0FH
MOVWF ANSER1
GOTO JIA_2
A_DD3 MOVLW 06H
SUBWF ANSER1,1
MOVLW 00H
MOVWF FLAGA
JIA_2 MOVLW 06H ;百位数相加(原理同个位数)
ADDWF DATA2,0
MOVWF ANSER2
MOVF FLAGA,0
ADDWF DATB2,0
ADDWF ANSER2,1
BTFSS STATUS,DC
GOTO A_DD4 ;DC=0
MOVLW 01H
MOVWF FLAGA
MOVF ANSER2,W
ANDLW 0FH
MOVWF ANSER2
GOTO JIA_3
A_DD4 MOVLW 06H
SUBWF ANSER2,1
MOVLW 00H
MOVWF FLAGA
JIA_3 MOVLW 06H ;千位数相加(原理同个位数)
ADDWF DATA3,0
MOVWF ANSER3
MOVF FLAGA,0
ADDWF DATB3,0
ADDWF ANSER3,1
BTFSS STATUS,DC
GOTO A_DD5 ;DC=0
MOVLW 01H
MOVWF FLAGA
MOVF ANSER3,W
ANDLW 0FH
MOVWF ANSER3
GOTO JIA_4
A_DD5 MOVLW 06H
SUBWF ANSER3,1
MOVLW 00H
MOVWF FLAGA
JIA_4 RETURN
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -