⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 字节浮点数至5位压缩bcd码转换程序.txt

📁 实用子程序.rar本子程序库对《单片机应用程序设计技术》一书附录中的子程序库作了重大修订
💻 TXT
字号:
还少程序
;【校验举例1】 -5.8125(十进制)
;化为浮点数:A30003
;结果:058120(BCD),C_MUL=4,C_DIV=0,FPOL=A3

; 5.2  3字节浮点数至5位压缩BCD码转换程序
 ;
;图2.6  浮点数至5位压缩BCD码转换程序
;程序通过3个步骤将一个3字节浮点数转换成5位压缩BCD码(压缩BCD码是指将
;两个BCD码分别存放在一个8位字节的高半字节和低半字节中)。首先,判断浮
;点数的符号,如果是负数,存符号位,并将之取补。其次,调用浮点数乘法或
;除法子程序,对浮点数进行连续的乘以10或除以10的操作,把浮点的阶码控制
;在+12≤EXPB<+16之间,即使得浮点数转换成定点数后,数值在4095(FFFH)
;和32767(7FFFH)之间。再次,调用浮点数至定点数子程序,将浮点数转换成
;双字节定点数。最后,调用定点数至BCD码子程序,将双字节无符号数转换成5位
;压缩BCD码,从而完成浮点数至压缩BCD码的转换。此外,乘以10或除以10的次数可
;以用来确定小数点的位置。在子程序中,乘以10或除以10的次数分别存在C_MUL
;和C_DIV单元中,但二者不可能同时大于0(二者不可能同时小于0,但可以同时
;等于0)。其中,当C_MUL>0时(此时,C_DIV必然等于0),表示小数点从BCD码的
;最后往前移动C_MUL位;当C_DIV>0时(此时,C_MUL必为0),表示小数点由BCD码
;的最后往后移动C_DIV位。转换后的BCD码的符号存于FPOL单元的第7位。


;在该子程序中要调用大量的子程序,如浮点数乘法子程序、浮点数除法子程序、
;浮点数至定点数转换子程序和定点数至BCD码转换子程序等。在此由于篇幅的
;原因都予以省略,需要这些子程序的读者,请参阅前面相关章节。
;浮点数至压缩BCD码转换程序的入口条件和出口条件如下:
;入口条件:ACCBHI、ACCBLO、EXPB
;出口条件:5位压缩BCD码存于ACCCHI低半字节、ACCCLO和ACCDHI中,符号保存
;于FPOL寄存器的第7位,小数点位置存于C_MUL和C_DIV中。
;以下为本子程序的程序清单。

    LIST            p=16f877
    INCLUDE        p16f877.inc

ACCALO         EQU     20H        ;临时寄存器
ACCAHI         EQU     21H
EXPA        EQU     22H        ;临时寄存器
ACCBLO         EQU     23H        ;存放被转换浮点数尾数
ACCBHI         EQU     24H
EXPB         EQU     25H        ;存放被转换浮点数阶码
ACCCLO         EQU     26H        ;临时寄存器
ACCCHI         EQU     27H        ;临时寄存器
ACCDLO         EQU     28H        ;临时寄存器
ACCDHI         EQU     29H        ;临时寄存器
TEMP         EQU     2AH        ;临时寄存器
TEMP1         EQU     30H        ;临时寄存器
TIMES         EQU     31H        ;临时寄存器
SIGN         EQU     2BH        ;临时寄存器
COUNT         EQU     2FH        ;临时寄存器
C_MUL         EQU     2CH        ;存放小数点位置
C_DIV         EQU     2DH        ;存放小数点位置
FPOL         EQU     2EH        ;存放被转换数的符号
FULL         EQU     2FH       ;  2F.0进位标志
    ORG            0X0000
START    GOTO        MAIN
    ORG            0X0100
;*************浮点数到BCD码子程序****************
FtoBCD    CLRF         C_MUL        ;清小数点位数寄存器
    CLRF         C_DIV
    CLRF         ACCAHI        ;求取结果符号,存于FPOL.7
    CALL         S_SIGN
    MOVF         SIGN ,0
    MOVWF        FPOL
    MOVLW         50            ;ACCA赋初值,ACCA=10(十进制)
    MOVWF         ACCAHI
    CLRF         ACCALO
    MOVLW         04
    MOVWF         EXPA
MUl5    BTFSS        EXPB,7        ;阶码EXPB<0?
    GOTO        MUl2        ;否,转MU12
MUl1    CALL         F_mpy        ;是,ACCA×10
    INCF         C_MUL        ;小数点左移寄存器加1
    GOTO         MUl5        ;重新判断阶码是否小于零
MUl2    MOVLW         .12            ;阶码EXPB<12?
    SUBWF         EXPB,0
    BTFSC         STATUS,C
    GOTO         MUl4        ;否,转MU14
MUl3    CALL         F_mpy        ;是,ACCA×10
    INCF         C_MUL        ;小数点左移寄存器加1
    GOTO         MUL2        ;重判阶码值
MUl4    MOVLW         .16            ;阶码EXPB>16?
    SUBWF         EXPB,0
    BTFSS        STATUS,C
    GOTO         NEXT        ;否,表示阶码12≤EXPB<16,求取BCD码值
DIV1    CALL         FDIV            ;是,EXPB÷10
    INCF         C_DIV        ;小数点右移寄存器加1
    GOTO         MUl4        ;重新判断阶码值
NEXT    CALL         FTOW3        ;调子程序,将浮点数转换为定点数
    CALL         BtoBCD        ;调双字节数到BCD码子程序,求BCD码
    MOVF         ACCCHI        ;ACCCHI=0?
    BTFSS         STATUS,Z
    RETLW         0            ;否,返回
    MOVLW         04            ;是,结果左移4次,保证ACCCHI不为零
    MOVWF         TIMES
    BCF             STATUS,C
MUl6    RLF             ACCDHI
    RLF            ACCCLO
    RLF             ACCCHI
    DECFSZ         TIMES
    GOTO         MUl6
    MOVF         C_DIV        ;C_DIV=0?
    BTFSC         STATUS,Z
    GOTO         TEMUL        ;是,转判断C_MUL
    DECF         C_DIV        ;否,小数点右移寄存器减1
    RETLW         0
TEMUL    INCF         C_MUL        ;小数点左移寄存器加1
    RETLW         0 

SETUP    MOVLW     .15    ;初始化TEMP寄存器        
    MOVWF     TEMP
    MOVF     ACCBHI,0    ;ACCB送ACCD
    MOVWF    ACCDHI
    MOVF     ACCBLO,0
    MOVWF     ACCDLO
    CLRF     ACCBHI    ;清ACCB
    CLRF     ACCBLO
    RETURN        ;子程序返回


FTOW3    MOVLW         .15            ;EXPB=15(十进制数)?
    SUBWF         EXPB,0
    BTFSC         STATUS,Z
    RETLW         0            ;是,返回
    BCF             STATUS,C    ;否,ACCB继续右移,EXPB加1
    RRF             ACCBHI
    RRF             ACCBLO
    INCF         EXPB
    GOTO         FTOW3        ;重新判断EXPB=15?

;**********双字节数至BCD码子程序************
BtoBCD    CLRF        SIGN            ;初始化符号寄存器
    BTFSS        ACCBHI,7    ;被转换数为负?
    GOTO        LOOP1        ;否,转BtoBCD
    BSF            SIGN,7        ;是,存符号
    CALL        NEG_B        ;ACCB取补
LOOP1    BCF             STATUS,C    ;清进位位
    MOVLW         .16            ;移位计数器赋初值
    MOVWF         COUNT
    CLRF         ACCCHI        ;初始化出口寄存器
    CLRF         ACCCLO
    CLRF         ACCDHI
LOOP16    RLF             ACCBLO        ;ACCB左移一位至出口寄存器
    RLF             ACCBHI
    RLF             ACCDHI
    RLF             ACCCLO
    RLF             ACCCHI
    DECFSZ         COUNT         ;移位计数器=0?
    GOTO         ADJDEC        ;否,转ADJDEC
    RETLW         0            ;是,返回
ADJDEC    MOVLW         ACCDHI        ;指针指向ACCDHI
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序
    MOVLW         ACCCLO        ;指针指向ACCCLO
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序    
    MOVLW         ACCCHI        ;指针指向ACCCHI
    MOVWF         FSR
    CALL         ADJBCD        ;调用BCD码校正子程序
    GOTO         LOOP16        ;ACCB重新左移

;************* BCD码校正子程序**************
ADJBCD     MOVLW         0X03        ;LSD+3>7?
    ADDWF         INDF,0
    MOVWF         TEMP
    BTFSC         TEMP,3
    MOVWF         INDF         ;是,LSD=LSD+3
    MOVLW         0X30            ;否,MSD+3>7?
    ADDWF         INDF,0
    MOVWF         TEMP
    BTFSC         TEMP,7
    MOVWF         INDF            ;是,MSD=MSD+3
    RETLW         0            ;返回


;***双字节加法子程序,入口地址ACCB+ACCA,出口地址ACCB***
D_add      MOVF     ACCALO,0    ;ACCB和ACCA低半字节相加
    ADDWF     ACCBLO
    BTFSC     STATUS,C    ;有进位否?
    goto      $+6         ;有,
    MOVF      ACCAHI,0    ;ACCA、ACCB高半字节相加
    ADDWF     ACCBHI
    BTFSC     STATUS,C
    BSF       FULL,0
    RETURN    ;子程序返回
    MOVFW     ACCBHI      ;ACCB高字节加1,再加ACCAHI
    ADDLW     1h
    BTFSC     STATUS,C     ;有进位否?
    BSF       FULL,0
    MOVWF     ACCBHI
    GOTO      $-D'10'



;***浮点乘法子程序,入口地址(ACCB、EXPB)×(ACCA、EXPA),出口地址ACCB、EXPB ***
F_mpy    CALL         S_SIGN        ;求取乘积的符号,并对负数取补
     CALL         SETUP        ;调用子程序将ACCB的值送ACCD
    CLRF         ACCCHI        ;清ACCC
    CLRF         ACCCLO
MLOOP    BCF             STATUS,C    ;清进位位
    RRF             ACCDHI        ;ACCD右移
    RRF             ACCDLO
    BTFSC         STATUS,C    ;判断是否需要相加
    CALL         D_add        ;加乘数至ACCB
    BCF             STATUS,C    ;清进位位
    RRF             ACCBHI        ;右移部分乘积
    RRF             ACCBLO
    RRF             ACCCHI
    RRF             ACCCLO
    DECFSZ         TEMP        ;乘法完成否?
    GOTO         MLOOP        ;否,继续循环
    MOVF         EXPA,0        ;是,乘数与被乘数阶码相加,得积的阶码
    ADDWF        EXPB
    MOVF         ACCBHI        ;ACCBHI=0?
    BTFSS         STATUS,Z
    GOTO         FINUP        ;否,转FINUP
    MOVF         ACCBLO        ;ACCB=0?
    BTFSS         STATUS ,Z
    GOTO         SHFT08        ;否,只有ACCBHI=0,转SHFT08
    MOVF         ACCCHI,0    ;ACCB=0,将乘积左移15位
    MOVWF         ACCBHI
    MOVF         ACCCLO,0
    MOVWF         ACCBLO
    BCF             STATUS,C
    RRF             ACCBHI
    RRF             ACCBLO
    MOVLW         .15            ;乘积阶码减15(十进制数)
    SUBWF         EXPB
    GOTO         FINUP
SHFT08    MOVF         ACCBLO,0    ;只有ACCBHI=0,乘积左移7位
    MOVWF         ACCBHI
    MOVF         ACCCHI,0
    MOVWF         ACCBLO
    BCF             STATUS,C
    RRF             ACCBHI
    RRF             ACCBLO
    MOVLW         .7            ;乘积阶码减7
    SUBWF         EXPB
FINUP    CALL         F_norm        ;对乘积进行规格化
    BTFSS         SIGN,7        ;确定乘积的符号
    GOTO         OVER        ;为正,乘法结束
    COMF         ACCCLO        ;为负,乘积取补
    INCF         ACCCLO
    BTFSC         STATUS,Z
    DECF         ACCCHI
    COMF         ACCCHI
    BTFSC         STATUS,Z
NEG_B    DECF         ACCBLO
    COMF         ACCBLO
    BTFSC         STATUS,Z
    DECF         ACCBHI
    COMF         ACCBHI
OVER    RETURN                    ;乘法结束,子程序返回

F_norm      MOVF         ACCBHI        ;ACCB=0?
    BTFSS         STATUS,Z
    GOTO         C_norm
    MOVF         ACCBLO
    BTFSC         STATUS,Z
    RETLW         0            ;是,不需规格化,返回

C_norm    BTFSC        ACCBHI,7    ;否。ACCB为负?
     GOTO        C_norm2
C_norm1    BTFSC         ACCBHI,6    ;为正。规格化完毕?
    RETLW         0            ;ACCBHI.6=1,规格化结束
    CALL         SHFTSL        ;否。ACCB左移
    DECF         EXPB        ;EXPB减1
    GOTO         C_norm1        ;重新判断规格化完毕否?
C_norm2    BTFSS        ACCBHI,6    ;ACCB为负。规格化完毕否?
    RETLW        0            ;ACCBHI.6=0,规格化结束
    BCF            STATUS,C    
    CALL        SHFTSL        ;否,ACCB左移
    BSF            ACCBHI,7    ;加符号
    DECF        EXPB        ;EXPB减1
    GOTO        C_norm2        ;重新判断规格化完毕否?
SHFTSL    BCF             STATUS,C    ;ACCB左移子程序    
    RLF             ACCCLO        
    RLF             ACCCHI
    RLF             ACCBLO
    RLF             ACCBHI
    RETLW         0

 

S_SIGN    MOVF         ACCAHI,0    ;ACCAHI异或ACCBHI,结果送SIGN
    XORWF         ACCBHI,0
    MOVWF        SIGN            
    BTFSS         ACCBHI,7    ;ACCB为负?
    GOTO         CHEK_A        ;否,检查ACCA
    COMF         ACCBLO        ;是,ACCB取补
    INCF         ACCBLO
    BTFSC         STATUS,Z
    DECF         ACCBHI
    COMF         ACCBHI
CHEK_A        BTFSC   ACCAHI,7    ;ACCA为负?
    CALL        NEG_A        ;ACCA取补
    RETURN                    ;返回


NEG_A    COMF         ACCALO        ;ACCALO取反加1
    INCF         ACCALO
    BTFSC         STATUS,Z    ;低8位有进位吗?
    DECF         ACCAHI        ;有,ACCAHI减1,再取反
    COMF         ACCAHI        ;否,ACCAHI直接取反
    RETLW         0




MAIN    MOVLW        0X00            ;将被转换数的尾数赋给ACCB
    MOVWF        ACCBLO
    MOVLW        0XA3
    MOVWF        ACCBHI
    MOVLW        0X03            ;将被转换数的阶码赋给EXPB
    MOVWF        EXPB
    CALL        FtoBCD        ;调用子程序开始转换
    END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -