專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命
提供開發(fā)工具、應(yīng)用測試 完善的開發(fā)代碼案例庫分享
從全面的產(chǎn)品導(dǎo)入到強大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無限潛能!
提供新的芯片及解決方案,提升客戶產(chǎn)品競爭力
提供最新的單片機資訊,行業(yè)消息以及公司新聞動態(tài)
PIC16F877單片機運算子程序
1 PIC16F877匯編語言程序主體框架
以下是一個典型的程序結(jié)構(gòu):
;***************程序說明區(qū)*******************
LIST p=16f877 ;指定微控制器型號和文件輸出格式
INCLUDE p16f877.inc ;讀入MPLAB提供的定義文件P16F877.INC
;***片內(nèi)RAM常用資源、變量定義和相應(yīng)的說明*********
ACCALO EQU 20 ;存放加數(shù)或減數(shù)低8位
ACCAHI EQU 21 ;存放加數(shù)或減數(shù)高8位
ACCBLO EQU 23 ;存放被加數(shù)或被減數(shù)低8位
ACCBHI EQU 24 ;存放被加數(shù)或被減數(shù)高8位
S_W EQU 25 ;棧存W寄存器值
S_STATUS EQU 26 ;棧存STATUS寄存器值
;****************芯片復(fù)位矢量*******************
ORG 0X0000 ;由于PIC16F877芯片復(fù)位矢量在0000h單
;元,所以常在0000h單元處放置一條跳轉(zhuǎn)
;指令,使單片機復(fù)位后能跳過中斷矢量,
;直接執(zhí)行主程序
START GOTO MAIN
;******************中斷矢量**********************
ORG 0X0004 ;由于PIC16F877的中斷矢量為0004h,所以
;當中斷開放時, 需在此處加入中斷程序,
;使單片機能在中斷到來時及時進入相應(yīng)的
;中斷服務(wù)程序。為了可靠起見,如果單片
;機不使用中斷,則常常在該中斷矢量處放
;置RETFIE指令,可以使單片機不會因
;干擾產(chǎn)生誤中斷而導(dǎo)致程序跑飛
CALL PUSH ;調(diào)用保護現(xiàn)場子程序
BTFSS PIR1,ADIF
CALL AD ;若AD中斷到,則執(zhí)行中斷服務(wù)程序
…….. ;此處可放多個中斷子程序,并以軟件安排
;中斷優(yōu)先級
CALL POP ;恢復(fù)中斷現(xiàn)場
RETFIE ;中斷返回
;****************主程序區(qū)*****************
ORG 0X0100 ;將主程序、子程序和中斷服務(wù)程序等存放
;在0100h單元之后,在中斷矢量和主程序
;區(qū)之間預(yù)留一些存儲單元,以便寫入判
;跳指令和一些必要的現(xiàn)場保護程序。此外
;用戶也可以根據(jù)實際需要,使主程序從其
;它地址開始存放
MAIN BSF STATUS,RP0 ;選擇存儲體1
MOVLW 0XFF ;定義RA口為輸入端口
MOVWF TRISA
BCF STATUS,RP0 ;選擇存儲體0
MOVLW 0X04 ;初值化ACCALO
MOVWF ACCALO
CALL DX ;調(diào)用DX子程序
LOOP1 …… ;任務(wù)1
…… ;任務(wù)2
:
:
:
GOTO LOOP1 ;反復(fù)執(zhí)行任務(wù)一和任務(wù)二等
;***************子程序區(qū)*********************
DX MOVF ACCALO,0 ;ACCB和ACCA低半字節(jié)相加
ADDWF ACCBLO
RETURN ;子程序返回
;****************************************
PUSH MOVWF S_W ;保護W寄存器
MOVF STATUS,0 ;保護STATUS寄存器
MOVWF S_STATUS
RETURN ;子程序返回
;****************************************
POP MOVF S_STATUS,0 ;恢復(fù)STATUS寄存器
MOVWF STATUS
MOVF S_W,0 ;恢復(fù)W寄存器
RETURN ;子程序返回
;****************中斷服務(wù)子程序區(qū)************************
AD BCF PIR1,ADIF ;清AD中斷標志
…… ;中斷服務(wù)主體程序
RETURN ;子程序返回
END
2 四則運算子程序
2.1 16×16位定點數(shù)加、減法子程序
以下子程序?qū)崿F(xiàn)2個16×16位有符號數(shù)加、減運算,其和或差用一個16位數(shù)表示。在子程序中,減法是通過對減數(shù)求補后再與被減數(shù)相加來實現(xiàn)的。因此,當程序從D_sub進入子程序時為減法,當從D_add進入子程序時為加法。
子程序的入口條件和出口條件如下:
入口條件:16位被加數(shù)/被減數(shù)存放在ACCBHI、ACCBLO中;
16位加數(shù)/減數(shù)存放在ACCAHI、ACCALO中;
出口條件:16位和/差存放在ACCBHI和ACCBLO中。
以下為16×16位有符號數(shù)加、減法子程序。
注意:在以下注釋程序中均以ACCA代替ACCAHI、ACCALO兩個字節(jié),以ACCB代替ACCBHI、ACCBLO兩個字節(jié)。
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放加數(shù)或減數(shù)低8位
ACCAHI EQU 21 ;存放加數(shù)或減數(shù)高8位
ACCBLO EQU 23 ;存放被加數(shù)或被減數(shù)低8位
ACCBHI EQU 24 ;存放被加數(shù)或被減數(shù)高8位
ORG 0X0000
START GOTO MAIN
;***雙字節(jié)減法子程序,入口地址ACCB-ACCA,出口地址ACCB***
D_sub CALL NEG_A ;求ACCA的補碼
;***雙字節(jié)加法子程序,入口地址ACCB+ACCA,出口地址ACCB***
D_add MOVF ACCALO,0 ;ACCB和ACCA低半字節(jié)相加
ADDWF ACCBLO
BTFSC STATUS,C ;有進位否?
INCF ACCBHI ;有,ACCB高字節(jié)加1,再加ACCAHI
MOVF ACCAHI,0 ;ACCA、ACCB高半字節(jié)相加
ADDWF ACCBHI
RETURN ;子程序返回
;************** ACCA取補子程序*****************
NEG_A COMF ACCALO ;ACCALO取反加1
INCF ACCALO
BTFSC STATUS,Z ;低8位有進位嗎?
DECF ACCAHI ;有,ACCAHI減1,再取反
COMF ACCAHI ;否則ACCAHI直接取反
RETURN ;子程序返回
【校驗舉例1】 19531+(-16594)=2937(十進制)
化為十六進制數(shù):4C46H+BF2EH
結(jié)果:0B79H(十六進制)
【校驗舉例2】 26222+3000=29222(十進制)
化為十六進制數(shù): 666EH+0BB8H
結(jié)果:7226H(十六進制)
【例程】
MAIN MOVLW 0X6E ;被加數(shù)666EH送ACCB
MOVWF ACCBLO
MOVLW 0X66
MOVWF ACCBHI
MOVLW 0XB8 ;加數(shù)BB8H送ACCA
MOVWF ACCALO
MOVLW 0X0B
MOVWF ACCAHI
CALL D_add ;調(diào)用雙字節(jié)加法子程序,求和
END
2.2 16×16位定點數(shù)乘法子程序
子程序采用部分積右移加法實現(xiàn)乘法運算。乘數(shù)和被乘數(shù)分別為16位二進制有符號數(shù)(均采用補碼表示,第16位為符號位),積為32位二進制有符號數(shù),第32位為符號位。子程序的入口條件和出口條件如下:
入口條件:被乘數(shù)存放在ACCBHI和ACCBLO單元中,
乘數(shù)存放在ACCAHI和ACCALO單元中。
出口條件:積存放在ACCBHI、ACCBLO、ACCCHI和ACCCLO單元中,ACCB為高16位,ACCC為低16位。
以下為本子程序的程序清單:
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放乘數(shù)低8位
ACCAHI EQU 21 ;存放乘數(shù)高8位
ACCBLO EQU 23 ;存放被乘數(shù)低8位和乘積第16~23位
ACCBHI EQU 24 ;存放被乘數(shù)高8位和乘積第24~31位
ACCCLO EQU 26 ;存放乘積低8位
ACCCHI EQU 27 ;存放乘積高8位
ACCDLO EQU 28 ;臨時寄存器
ACCDHI EQU 29 ;臨時寄存器
TEMP EQU 2A ;臨時寄存器
SIGN EQU 2B ;存放乘積的符號
ORG 0X0000
START GOTO MAIN
;***16×16位乘法子程序,入口地址ACCB×ACCA,出口地址ACCB和ACCC ***
ORG 0X0100
D_mpy CALL S_SIGN ;求取乘積的符號,并對負數(shù)取補
CALL SETUP ;調(diào)用子程序,將ACCB的值送ACCD
INCF TEMP
CLRF ACCCHI ;清ACCC
CLRF ACCCLO
MLOOP BCF STATUS,C ;清進位位
RRF ACCDHI ;ACCD右移
RRF ACCDLO
BTFSC STATUS,C ;判斷是否需要相加
CALL D_add ;加乘數(shù)至ACCB,見加法程序
BCF STATUS,C ;清進位位
RRF ACCBHI ;右移部分乘積
RRF ACCBLO
RRF ACCCHI
RRF ACCCLO
DECFSZ TEMP ;乘法完成否?
GOTO MLOOP ;否,繼續(xù)求乘積
BTFSS SIGN,7 ;是,確定乘積的符號
GOTO OVER ;為正,乘法結(jié)束
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 ;子程序返回
;****************************************
SETUP MOVLW .15 ;初始化TEMP寄存器
MOVWF TEMP
MOVF ACCBHI,0 ;ACCB送ACCD
MOVWF ACCDHI
MOVF ACCBLO,0
MOVWF ACCDLO
CLRF ACCBHI ;清ACCB
CLRF ACCBLO
RETURN ;子程序返回
;*******乘法運算確定結(jié)果符號判斷子程序******
S_SIGN MOVF ACCAHI,0 ;ACCAHI異或ACCBHI,結(jié)果送SIGN單元
XORWF ACCBHI,0
MOVWF SIGN
BTFSS ACCBHI,7 ;ACCB為負嗎?
GOTO CHEK_A ;否,檢查ACCA
CALL NEG_B ;是,求取ACCB絕對值
CHEK_A BTFSC ACCAHI,7 ;ACCA為負嗎?
CALL NEG_A ;ACCA為負,求取ACCA絕對值,
;見雙字節(jié)加法程序
RETURN ;ACCA和ACCB均為正,返回
【校驗舉例1】:-24555×(-7391)=181486005(十進制)
化為十六進制數(shù):A015H×E321H
結(jié)果:0AD141B5H(十六進制)
【校驗舉例2】 16405×13089=214725045(十進制)
化為十六進制數(shù):4015H×3321H
結(jié)果:0CCC71B5H(十六進制)
【例程】
MAIN MOVLW 0X15 ;被乘數(shù)4015H送ACCB
MOVWF ACCBLO
MOVLW 0X40
MOVWF ACCBHI
MOVLW 0X21 ;乘數(shù)3321H送ACCA
MOVWF ACCALO
MOVLW 0X33
MOVWF ACCAHI
CALL D_mpy ;調(diào)用雙字節(jié)乘法子程序,求積
END
2.3 16×16位定點數(shù)除法子程序
子程序采用反復(fù)的減法算法,除數(shù)和被除數(shù)分別為16位二進制有符號數(shù)(均采用補碼表示,第16位為符號位),商為16位二進制有符號數(shù),第16位為符號位。子程序的入口條件和出口條件如下:
入口條件:被除數(shù)存放在ACCBHI、ACCBLO單元中;
除數(shù)存放在ACCAHI、ACCALO單元中。
出口條件:商存放在ACCBHI、ACCBLO單元中;
余數(shù)存放在ACCCHI、ACCCLO單元中。
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放除數(shù)低8位
ACCAHI EQU 21 ;存放除數(shù)高8位
ACCBLO EQU 22 ;存放被除數(shù)和商的低8位
ACCBHI EQU 23 ;存放被除數(shù)和商的高8位
ACCCLO EQU 24 ;存放余數(shù)低8位
ACCCHI EQU 25 ;存放余數(shù)高8位
ACCDLO EQU 26 ;臨時寄存器
ACCDHI EQU 27 ;臨時寄存器
TEMP EQU 28 ;臨時寄存器
SIGN EQU 29 ;存放商的符號
ORG 0X0000
START GOTO MAIN
;***16×16位數(shù)除法子程序,入口地址ACCB /ACCA,出口地址ACCB ***
ORG 0X0100
D_div CALL S_SIGN ;確定商的符號,并將負數(shù)取補
CALL SETUP ;初始化TEMP,將被除數(shù)移至ACCD,
;(SETUP子程序請參見16×16位定點數(shù)
;乘法子程序SETUP)
INCF TEMP
CLRF ACCCHI ;清余數(shù)寄存器
CLRF ACCCLO
DLOOP BCF STATUS,C ;清進位位
RLF ACCDLO ;被除數(shù)、余數(shù)左移1位
RLF ACCDHI
RLF ACCCLO
RLF ACCCHI
MOVF ACCAHI,0 ;ACCCHI-ACCAHI
SUBWF ACCCHI,0
BTFSS STATUS,Z ;ACCCHI=ACCAHI?
GOTO NOCHK
MOVF ACCALO,0 ;是,ACCCLO-ACCALO
SUBWF ACCCLO,0
NOCHK BTFSS STATUS,C ;ACCC>ACCA?
GOTO NOGO
MOVF ACCALO,0 ;是,余數(shù)減除數(shù)
SUBWF ACCCLO
BTFSS STATUS,C
DECF ACCCHI
MOVF ACCAHI,0
SUBWF ACCCHI
BSF STATUS,C ;置進位位
NOGO RLF ACCBLO ;商左移1位
RLF ACCBHI
DECFSZ TEMP ;循環(huán)完畢?
GOTO DLOOP
BTFSS SIGN,7 ;是,確定商的符號
GOTO DIVOVER ;為正,除法結(jié)束,跳轉(zhuǎn)到結(jié)束行
COMF ACCCLO ;為負,商和余數(shù)分別取補
INCF ACCCLO
BTFSC STATUS,Z
DECF ACCCHI
COMF ACCCHI
CALL NEG_B ;見乘法程序中間NEG_B
DIVOVER RETURN ;子程序返回
;************除法運算確定結(jié)果符號子程序*******************
S_SIGN MOVF ACCAHI,0 ;ACCAHI異或ACCBHI,結(jié)果送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為負,取補(NEG_A子程序請參見
;16×16位定點數(shù)乘法子程序NEG_A)
RETURN ;ACCA和ACCB均為負,返回
【校驗舉例1】 -23775÷(-240)=99.0625(十進制)
化為十六進制數(shù):A321H÷FF10H;
結(jié)果:(商)0063H,(余數(shù))000FH(十六進制)。
【校驗舉例2】 769÷3856=0.199429(十進制)
化為十六進制數(shù):0301H÷0F10H;
結(jié)果:(商)0000H,(余數(shù))0301H(十六進制)。
【例程】
MAIN MOVLW 0X01 ;被除數(shù)0301H送ACCB
MOVWF ACCBLO
MOVLW 0X03
MOVWF ACCBHI
MOVLW 0X10 ;除數(shù)0F10H送ACCA
MOVWF ACCALO
MOVLW 0X0F
MOVWF ACCAHI
CALL D_div ;調(diào)用雙字節(jié)除法子程序,求商
END
3 3字節(jié)浮點四則運算子程序
3.1 浮點數(shù)加(減)法子程序
以下為浮點加(減)運算例程:
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放加數(shù)或減數(shù)的尾數(shù)
ACCAHI EQU 21
EXPA EQU 22 ;存放加數(shù)或減數(shù)階碼
ACCBLO EQU 23 ;存放被加數(shù)或被減數(shù)尾數(shù)以及和或差
ACCBHI EQU 24
EXPB EQU 25 ;存放被加數(shù)或被減數(shù)階碼
ACCCLO EQU 26 ;臨時寄存器
ACCCHI EQU 27 ;臨時寄存器
ACCDLO EQU 28 ;臨時寄存器
ACCDHI EQU 29 ;臨時寄存器
TEMP EQU 2A ;臨時寄存器
TEMP1 EQU 30 ;臨時寄存器
TIMES EQU 31 ;臨時寄存器
ORG 0X000
START GOTO MAIN
ORG 0X0100
;**************浮點減法子程序****************
F_sub CALL NEG_A ;求ACCA的補碼,將減法轉(zhuǎn)換為補碼加法
;***********浮點加法子程序**************
F_add CALL SUBADJ ;調(diào)子程序判斷EXPB和EXPA的大小
BTFSC STATUS,Z ;參與運算的兩個數(shù)階碼相等?
GOTO PADD ;是,求尾數(shù)的和
BTFSC STATUS,C ;EXPB>EXPA?
CALL F_swap ;是,ACCB與ACCA互換
MOVF EXPA,0 ;否,求取兩者的差值
SUBWF EXPB
SCLOOP CALL SHFTSR ;ACCB右移規(guī)格化
INCFSZ EXPB ;EXPB=EXPA?
GOTO SCLOOP ;否,繼續(xù)右移
MOVF EXPA,0 ;是,存和(差)的階碼
MOVWF EXPB
PADD MOVF ACCAHI,0 ;ACCAHI或ACCBHI
IORWF ACCBHI,0
MOVWF SIGN ;存于SIGN寄存器
MOVF ACCBHI,0 ;暫存ACCBHI
MOVWF EXPA
CALL D_add ;尾數(shù)相加
BTFSS SIGN,7 ;ACCA和ACCB有負數(shù)?
BTFSC ACCBHI,7 ;否,把和的最高位和次高位同時進位?
GOTO ADD2 ;否,轉(zhuǎn)ADD2
BTFSS ACCAHI,7 ;ACCA為負嗎?
GOTO ADD3 ;ACCA和ACCB不同時為負,轉(zhuǎn)ADD3
BTFSS EXPA,7 ;是,ACCB為負嗎?
GOTO ADD3
BSF STATUS,C ;ACCA和ACCB同為負,帶負號右移
RRF ACCBHI
RRF ACCBLO
INCF EXPB
ADD3 CLRF ACCCHI ;和(差)規(guī)格化
CLRF ACCCLO
CALL F_norm
RETURN ;子程序返回
ADD2 BCF STATUS,C ;最高位次高位不同時進位,ACCB右移
INCF EXPB
GOTO SHFTR
SHFTSR BCF STATUS,C ;ACCB帶符號右移子程序
BTFSC ACCBHI,7
BSF STATUS,C
SHFTR RRF ACCBHI
RRF ACCBLO
RETURN ;子程序返回
;********* ACCB、ACCA互換子程序************
F_swap MOVF ACCAHI,0 ;ACCAHI、ACCBHI互換
MOVWF TEMP
MOVF ACCBHI,0
MOVWF ACCAHI
MOVF TEMP,0
MOVWF ACCBHI
MOVF ACCALO,0 ;ACCALO、ACCBLO互換
MOVWF TEMP
MOVF ACCBLO,0
MOVWF ACCALO
MOVF TEMP,0
MOVWF ACCBLO
MOVF EXPA,0 ;EXPA、EXPB互換
MOVWF TEMP
MOVF EXPB,0
MOVWF EXPA
MOVF TEMP,0
MOVWF EXPB
RETURN
;*************比較EXPB、EXPA大小子程序*************
SUBADJ MOVF EXPA,0 ;EXPA異或EXPB,結(jié)果送C_DIV
XORWF EXPB,0
MOVWF C_DIV
MOVF EXPA,0 ;EXPB-EXPA
SUBWF EXPB,0
BTFSS C_DIV,7 ;EXPA和EXPB同號?
RETURN ;是,進位位的值真確反映兩者的大小,返回
BTFSS STATUS,C ;否,進位位的值取反
GOTO CHANGEC
BCF STATUS,C
RETURN
CHANGEC BSF STATUS,C
RETURN
;***********浮點數(shù)規(guī)格化子程序****************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETURN ;是,不需規(guī)格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB為負?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;為正。規(guī)格化完畢?
RETURN ;ACCBHI.6=1,規(guī)格化結(jié)束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB減1
GOTO C_norm1 ;重新判斷規(guī)格化完畢否?
C_norm2 BTFSS ACCBHI,6 ;ACCB為負。規(guī)格化完畢否?
RETURN ;ACCBHI.6=0,規(guī)格化結(jié)束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符號
DECF EXPB ;EXPB減1
GOTO C_norm2 ;重新判斷規(guī)格化完畢否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
RLF ACCCLO
RLF ACCCHI
RLF ACCBLO
RLF ACCBHI
RETURN
【校驗舉例1】 0.0019531+(-0.00016594)=0.00178716
化為十六進制數(shù):4000F8+A900F4
結(jié)果:7520F7
【校驗舉例2】 0.26222+3.5025=3.76478
化為十六進制數(shù): 4321FF+701502
結(jié)果:787902
【例程】
MAIN MOVLW 0X21 ;被加數(shù)的尾數(shù)4321H送ACCB
MOVWF ACCBLO
MOVLW 0X43
MOVWF ACCBHI
MOVLW 0XFF ;被加數(shù)的階碼FFH送EXPB
MOVWF EXPB
MOVLW 0X15 ;加數(shù)尾數(shù)7015H送ACCA
MOVWF ACCALO
MOVLW 0X70
MOVWF ACCAHI
MOVLW 0X02 ;加數(shù)階碼送EXPA
MOVWF EXPA
CALL F_add ;調(diào)用浮點數(shù)加法子程序,求和
END
3.2 浮點數(shù)乘法子程序
以下為浮點數(shù)乘法的程序清單。
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放乘數(shù)尾數(shù)
ACCAHI EQU 21
EXPA EQU 22 ;存放乘數(shù)階碼
ACCBLO EQU 23 ;存放被乘數(shù)尾數(shù)和乘積高16位
ACCBHI EQU 24
EXPB EQU 25 ;存放被乘數(shù)階碼
ACCCLO EQU 26 ;存放乘積低16位
ACCCHI EQU 27
ACCDLO EQU 28 ;臨時寄存器
ACCDHI EQU 29 ;臨時寄存器
TEMP EQU 2A ;臨時寄存器
TEMP1 EQU 30 ;臨時寄存器
TIMES EQU 31 ;臨時寄存器
SIGN EQU 2B ;存放乘積符號
COUNT EQU 2F ;臨時寄存器
ACCEHI EQU 30 ;臨時寄存器
ACCELO EQU 31 ;臨時寄存器
ORG 0X0000
START GOTO MAIN
ORG 0X0100
;***浮點乘法子程序,入口地址(ACCB、EXPB)×(ACCA、EXPA),出口地址ACCB、EXPB ***
F_mpy CALL S_SIGN ;求取乘積的符號,并對負數(shù)取補
CALL SETUP ;調(diào)用子程序?qū)CCB的值送ACCD
CLRF ACCCHI ;清ACCC
CLRF ACCCLO
MLOOP BCF STATUS,C ;清進位位
RRF ACCDHI ;ACCD右移
RRF ACCDLO
BTFSC STATUS,C ;判斷是否需要相加
CALL D_add ;加乘數(shù)至ACCB
BCF STATUS,C ;清進位位
RRF ACCBHI ;右移部分乘積
RRF ACCBLO
RRF ACCCHI
RRF ACCCLO
DECFSZ TEMP ;乘法完成否?
GOTO MLOOP ;否,繼續(xù)循環(huán)
MOVF EXPA,0 ;是,乘數(shù)與被乘數(shù)階碼相加,得積的階碼
ADDWF EXPB
MOVF ACCBHI ;ACCBHI=0?
BTFSS STATUS,Z
GOTO FINUP ;否,轉(zhuǎn)FINUP
MOVF ACCBLO ;ACCB=0?
BTFSS STATUS ,Z
GOTO SHFT08 ;否,只有ACCBHI=0,轉(zhuǎn)SHFT08
MOVF ACCCHI,0 ;ACCB=0,將乘積左移15位
MOVWF ACCBHI
MOVF ACCCLO,0
MOVWF ACCBLO
BCF STATUS,C
RRF ACCBHI
RRF ACCBLO
MOVLW .15 ;乘積階碼減15(十進制數(shù))
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 ;對乘積進行規(guī)格化
BTFSS SIGN,7 ;確定乘積的符號
GOTO OVER ;為正,乘法結(jié)束
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 ;乘法結(jié)束,子程序返回
;********浮點乘除法運算確定結(jié)果符號子程序***********
S_SIGN MOVF ACCAHI,0 ;ACCAHI異或ACCBHI,結(jié)果送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 ;返回
;*********浮點運算結(jié)果規(guī)格化子程序*************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETURN ;是,不需規(guī)格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB為負?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;為正。規(guī)格化完畢?
RETURN ;ACCBHI.6=1,規(guī)格化結(jié)束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB減1
GOTO C_norm1 ;重新判斷規(guī)格化完畢否?
C_norm2 BTFSS ACCBHI,6 ;ACCB為負。規(guī)格化完畢否?
RETURN ;ACCBHI.6=0,規(guī)格化結(jié)束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符號
DECF EXPB ;EXPB減1
GOTO C_norm2 ;重新判斷規(guī)格化完畢否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
RLF ACCCLO
RLF ACCCHI
RLF ACCBLO
RLF ACCBHI
RETURN
【校驗舉例1】 0.0019531×(-0.00016594)=-0.000000324
化為十六進制數(shù):4000F8×A900F4
結(jié)果:A900EB
【校驗舉例2】 0.26222×3.5025=0.91842
化為十六進制數(shù): 4321FF×701502
結(jié)果: 758F00
【例程】
MAIN MOVLW 0X21 ;被乘數(shù)的尾數(shù)4321H送ACCB
MOVWF ACCBLO
MOVLW 0X43
MOVWF ACCBHI
MOVLW 0XFF ;被乘數(shù)的階碼FFH送EXPB
MOVWF EXPB
MOVLW 0X15 ;乘數(shù)尾數(shù)7015H送ACCA
MOVWF ACCALO
MOVLW 0X70
MOVWF ACCAHI
MOVLW 0X02 ;乘數(shù)階碼送EXPA
MOVWF EXPA
CALL F_mpy ;調(diào)用浮點數(shù)乘法子程序,求積
END
3.3 浮點數(shù)除法子程序
以下為浮點數(shù)除法子程序清單。
LIST p=16f877
INCLUDE p16f877.inc
ACCALO EQU 20 ;存放除數(shù)的尾數(shù)
ACCAHI EQU 21
EXPA EQU 22 ;存放除數(shù)的階碼
ACCBLO EQU 23 ;存放被除數(shù)的尾數(shù)和商的尾數(shù)
ACCBHI EQU 24
EXPB EQU 25 ;存放被除數(shù)和商的階碼
ACCCLO EQU 26 ;存放余數(shù)
ACCCHI EQU 27
ACCDLO EQU 28 ;臨時寄存器
ACCDHI EQU 29 ;臨時寄存器
TEMP EQU 2A ;臨時寄存器
TEMP1 EQU 30 ;臨時寄存器
TIMES EQU 31 ;臨時寄存器
SIGN EQU 2B ;存放商的符號
COUNT EQU 2F ;臨時寄存器
ACCEHI EQU 30 ;臨時寄存器
ACCELO EQU 31 ;臨時寄存器
ORG 0X0000
START GOTO MAIN
ORG 0X0100
;***浮點數(shù)除法子程序,入口地址(ACCB、EXPB)/(ACCA、EXPA),出口地址ACCB、EXPB***
F_div CALL S_SIGN ;確定商的符號,并將負數(shù)取補
CLRF ACCCHI ;初始化ACCC寄存器
CLRF ACCCLO
CALL F_norm ;規(guī)格化ACCB
CLRF ACCCLO
CLRF ACCCHI
CLRF TIMES
MOVF ACCAHI ;除數(shù)為零?
BTFSS STATUS,Z
GOTO FD0 ;否,求商
MOVF ACCALO
BTFSC STATUS,Z
RETLW 01 ;是,返回
FD0 CALL NEG_A ;除數(shù)取補
FD1 MOVF ACCBHI,0 ;ACCBHI送ACCDLO
MOVWF ACCDLO
CALL D_add1 ;被除數(shù)尾數(shù)大于除數(shù)尾數(shù)?
BTFSS STATUS,C
GOTO FD2
RRF1 BCF STATUS,C ;是,被除數(shù)右移規(guī)格化,直到小于除數(shù)為止
RRF ACCBHI
RRF ACCBLO
INCF TIMES
RRF ACCCHI
BCF STATUS,C
GOTO FD1
FD2 CALL DDIV ;否,調(diào)用雙字節(jié)除法子程序,求商的尾數(shù)
MOVF TIMES,0 ;根據(jù)右移規(guī)格化次數(shù)調(diào)整ACCB階碼
ADDWF EXPB
MOVF EXPA,0 ;求商的階碼
SUBWF EXPB
CALL F_norm ;商規(guī)格化
BTFSC SIGN,7 ;商為負?
CALL NEG_B ;是,取補
CALL NEG_A ;除數(shù)還原
RETURN ;浮點數(shù)除法完成,返回
;***********雙字節(jié)純小數(shù)除法子程序***************
DDIV MOVLW 0X0F ;初始化ACCDHI
MOVWF ACCDHI
DV1 BCF STATUS,C
RLF ACCCLO ;左移商
RLF ACCCHI
RLF ACCBLO ;左移余數(shù)
RLF ACCBHI
MOVF STATUS,0 ;暫存STATUS寄存器
MOVWF ACCDLO
MOVF ACCBHI,0 ;ACCBHI送TEMP1
MOVWF TEMP1
MOVF ACCALO,0 ;ACCB-ACCA
ADDWF ACCBLO,0
MOVWF TEMP
BTFSC STATUS,C
INCF TEMP1
MOVF ACCAHI,0
ADDWF TEMP1,0
BTFSC ACCDLO,0 ;左移余數(shù)時移出來的數(shù)為1?
GOTO DV2
TESTC BTFSS STATUS,C ;是,再判斷ACCB尾數(shù)是否大于ACCA
GOTO DV3
DV2 MOVWF ACCBHI ;是,余數(shù)送ACCB
MOVF TEMP,0
MOVWF ACCBLO
INCF ACCCLO ;商加1
DV3 DECFSZ ACCDHI ;商求取完畢?
GOTO DV1
MOVF ACCCHI,0 ;是,將商送ACCB
MOVWF ACCBHI
MOVF ACCCLO,0
MOVWF ACCBLO
RETLW 00
;**********本子程序用于判斷比較ACCB與ACCA的大小**********
D_add1 MOVF ACCALO,0 ;加數(shù)、被加數(shù)低半字節(jié)相加
ADDWF ACCBLO,0
BTFSC STATUS,C ;有進位?
INCF ACCDLO ;ACCD低半字節(jié)加1
MOVF ACCAHI,0 ;ACCAHI+ACCDLO
ADDWF ACCDLO
RETLW 0 ;子程序返回
;****************************************
SETUP MOVLW .15
MOVWF TEMP
MOVF ACCBHI,0
MOVWF ACCDHI
MOVF ACCBLO,0
MOVWF ACCDLO
CLRF ACCBHI
CLRF ACCBLO
RETLW 0
;*************** ACCA取補子程序*************
NEG_A COMF ACCALO ;ACCALO取反加1
INCF ACCALO
BTFSC STATUS,Z ;低8位有進位嗎?
DECF ACCAHI ;有,ACCAHI減1,再取反
COMF ACCAHI ;否,ACCAHI直接取反
RETLW 0
;********* ACCB取補子程序*************
NEG_B DECF ACCBLO ;ACCBLO取反加1
COMF ACCBLO
BTFSC STATUS,Z ;低8位有進位嗎?
DECF ACCBHI ;有,ACCBHI減1,再取反
COMF ACCBHI ;否,ACCBHI直接取反
RETLW 0
;*********浮點乘除法運算確定結(jié)果符號子程序**********
S_SIGN MOVF ACCAHI,0 ;ACCAHI異或ACCBHI,結(jié)果送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為負,取補
RETLW 0 ;ACCA和ACCB均為負,返回
;************浮點運算結(jié)果規(guī)格化子程序***************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETLW 0 ;是,不需規(guī)格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB為負?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;為正。規(guī)格化完畢?
RETLW 0 ;ACCBHI.6=1,規(guī)格化結(jié)束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB減1
GOTO C_norm1 ;重新判斷規(guī)格化完畢否?
C_norm2 BTFSS ACCBHI,6 ;ACCB為負。規(guī)格化完畢否?
RETLW 0 ;ACCBHI.6=0,規(guī)格化結(jié)束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符號
DECF EXPB ;EXPB減1
GOTO C_norm2 ;重新判斷規(guī)格化完畢否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
RLF ACCCLO
RLF ACCCHI
RLF ACCBLO
RLF ACCBHI
RETLW 0
【校驗舉例1】 0.0019531÷(-0.00016594)=-12.7699
化為十六進制數(shù):4000F8÷A900F4
結(jié)果:A1D704
【校驗舉例2】 0.26222÷3.5025=0.074867
化為十六進制數(shù): 4321FF÷701502
結(jié)果:4CA9FD
【例程】
MAIN MOVLW 0X21 ;被除數(shù)的尾數(shù)4321H送ACCB
MOVWF ACCBLO
MOVLW 0X43
MOVWF ACCBHI
MOVLW 0XFF ;被除數(shù)的階碼FFH送EXPB
MOVWF EXPB
MOVLW 0X15 ;除數(shù)尾數(shù)7015H送ACCA
MOVWF ACCALO
MOVLW 0X70
MOVWF ACCAHI
MOVLW 0X02 ;除數(shù)階碼送EXPA
MOVWF EXPA
CALL F_div ;調(diào)用浮點數(shù)除法子程序,求商
END
4 定點數(shù)與浮點數(shù)轉(zhuǎn)換程序
4.1 定點數(shù)轉(zhuǎn)換成浮點數(shù)
本子程序的功能是將雙字節(jié)定點整數(shù)(十六進制)轉(zhuǎn)換為3字節(jié)浮點數(shù),其轉(zhuǎn)換數(shù)值范圍:-32768~32767,入口條件和出口條件如下:
入口條件:ACCBHI、ACCBLO
出口條件:ACCBHI、ACCBLO、EXPB
以下為定點整數(shù)轉(zhuǎn)換成浮點數(shù)的程序清單。
LIST p=16f877
INCLUDE p16f877.inc
ACCBLO EQU 23 ;存放定點整數(shù)和轉(zhuǎn)換后浮點數(shù)的尾數(shù)
ACCBHI EQU 24
EXPB EQU 25 ;存放轉(zhuǎn)換后浮點數(shù)的階碼
ACCCLO EQU 26 ;臨時寄存器
ACCCHI EQU 27 ;臨時寄存器
ACCDLO EQU 28 ;臨時寄存器
ACCDHI EQU 29 ;臨時寄存器
SIGN EQU 2B ;存放被轉(zhuǎn)換數(shù)的符號
ORG 0X0000
START GOTO MAIN
ORG 0X0100
;*********雙字節(jié)定點整數(shù)到浮點數(shù)轉(zhuǎn)換子程序***********
DtoF CLRF SIGN ;根據(jù)被轉(zhuǎn)換數(shù)確定結(jié)果的符號,對負數(shù)取補
BTFSS ACCBHI,7
GOTO INTF1
BSF SIGN,7
CALL NEG_B
INTF1 MOVLW .15 ;初始化EXPB
MOVWF EXPB
CLRF ACCCHI
CLRF ACCCLO
CALL F_norm ;對ACCB進行規(guī)格化
BTFSS SIGN,7 ;結(jié)果為負?
GOTO DtoF1
CALL NEG_B ;是,求補
DtoF1 RETURN
;**************浮點數(shù)規(guī)格化子程序**************
F_norm MOVF ACCBHI ;ACCB=0?
BTFSS STATUS,Z
GOTO C_norm
MOVF ACCBLO
BTFSC STATUS,Z
RETLW 0 ;是,不需規(guī)格化,返回
C_norm BTFSC ACCBHI,7 ;否。ACCB為負?
GOTO C_norm2
C_norm1 BTFSC ACCBHI,6 ;為正。規(guī)格化完畢?
RETLW 0 ;ACCBHI.6=1,規(guī)格化結(jié)束
CALL SHFTSL ;否。ACCB左移
DECF EXPB ;EXPB減1
GOTO C_norm1 ;重新判斷規(guī)格化完畢否?
C_norm2 BTFSS ACCBHI,6 ;ACCB為負。規(guī)格化完畢否?
RETLW 0 ;ACCBHI.6=0,規(guī)格化結(jié)束
BCF STATUS,C
CALL SHFTSL ;否,ACCB左移
BSF ACCBHI,7 ;加符號
DECF EXPB ;EXPB減1
GOTO C_norm2 ;重新判斷規(guī)格化完畢否?
SHFTSL BCF STATUS ,C ;ACCB左移子程序
RLF ACCCLO
RLF ACCCHI
RLF ACCBLO
RLF ACCBHI
RETLW 0
【校驗舉例1】 19531(十進制)
化為十六進制數(shù):4C4BH
結(jié)果:4C4B0FH
【校驗舉例2】 2622(十進制)
化為十六進制數(shù): 0A3EH
結(jié)果:51F00CH
【例程】
MAIN MOVLW 0X4B ;被轉(zhuǎn)換數(shù)4C4BH送ACCB
MOVWF ACCBLO
MOVLW 0X4C
MOVWF ACCBHI
CALL DtoF ;調(diào)用定點數(shù)至浮點數(shù)轉(zhuǎn)換子程序
END