天堂草原最受欢迎的角色,天堂动漫,天堂在线,色天堂下载,天堂中文在线资源,亚洲男人天堂

技術(shù)熱線: 4007-888-234
設(shè)計(jì)開(kāi)發(fā)

專注差異化嵌入式產(chǎn)品解決方案 給智能產(chǎn)品定制注入靈魂給予生命

開(kāi)發(fā)工具

提供開(kāi)發(fā)工具、應(yīng)用測(cè)試 完善的開(kāi)發(fā)代碼案例庫(kù)分享

技術(shù)支持

從全面的產(chǎn)品導(dǎo)入到強(qiáng)大技術(shù)支援服務(wù) 全程貼心伴隨服務(wù),創(chuàng)造無(wú)限潛能!

新品推廣

提供新的芯片及解決方案,提升客戶產(chǎn)品競(jìng)爭(zhēng)力

新聞中心

提供最新的單片機(jī)資訊,行業(yè)消息以及公司新聞動(dòng)態(tài)

PIC16F877 單片機(jī)運(yùn)算子程序

更新時(shí)間: 2019-03-23
閱讀量:1805

十年專注單片機(jī)方案開(kāi)發(fā)的方案公司英銳恩,分享PIC16F877 單片機(jī)運(yùn)算子程序。英銳恩現(xiàn)提供服務(wù)產(chǎn)品涉及主控芯片:8位單片機(jī)、16位單片機(jī)、32位單片機(jī)及各類運(yùn)算放大器等。

1  PIC16F877單片機(jī)匯編語(yǔ)言程序主體框架
以下是一個(gè)典型的程序結(jié)構(gòu):
;***************程序說(shuō)明區(qū)*******************
    LIST    p=16f877    ;指定微控制器型號(hào)和文件輸出格式
    INCLUDE    p16f877.inc    ;讀入MPLAB提供的定義文件P16F877.INC
;***片內(nèi)RAM常用資源、變量定義和相應(yīng)的說(shuō)明*********
    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)
        ;指令,使單片機(jī)復(fù)位后能跳過(guò)中斷矢量,
                                ;直接執(zhí)行主程序
START    GOTO        MAIN        
;******************中斷矢量**********************

ORG          0X0004    ;由于PIC16F877的中斷矢量為0004h,所以
        ;當(dāng)中斷開(kāi)放時(shí), 需在此處加入中斷程序,
        ;使單片機(jī)能在中斷到來(lái)時(shí)及時(shí)進(jìn)入相應(yīng)的
        ;中斷服務(wù)程序。為了可靠起見(jiàn),如果單片
        ;機(jī)不使用中斷,則常常在該中斷矢量處放
        ;置RETFIE指令,可以使單片機(jī)不會(huì)因
        ;干擾產(chǎn)生誤中斷而導(dǎo)致程序跑飛
    CALL    PUSH    ;調(diào)用保護(hù)現(xiàn)場(chǎng)子程序
    BTFSS    PIR1,ADIF
    CALL    AD    ;若AD中斷到,則執(zhí)行中斷服務(wù)程序
    ……..        ;此處可放多個(gè)中斷子程序,并以軟件安排
            ;中斷優(yōu)先級(jí)
    CALL    POP    ;恢復(fù)中斷現(xiàn)場(chǎng)
    RETFIE    ;中斷返回
;****************主程序區(qū)*****************
    ORG    0X0100    ;將主程序、子程序和中斷服務(wù)程序等存放
        ;在0100h單元之后,在中斷矢量和主程序
        ;區(qū)之間預(yù)留一些存儲(chǔ)單元,以便寫入判
        ;跳指令和一些必要的現(xiàn)場(chǎng)保護(hù)程序。此外
        ;用戶也可以根據(jù)實(shí)際需要,使主程序從其
        ;它地址開(kāi)始存放
MAIN    BSF          STATUS,RP0    ;選擇存儲(chǔ)體1
    MOVLW    0XFF    ;定義RA口為輸入端口

MOVWF    TRISA
    BCF    STATUS,RP0    ;選擇存儲(chǔ)體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    ;保護(hù)W寄存器
    MOVF    STATUS,0    ;保護(hù)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中斷標(biāo)志
    ……                        ;中斷服務(wù)主體程序
    RETURN                    ;子程序返回
            END
2  四則運(yùn)算子程序
2.1  16×16位定點(diǎn)數(shù)加、減法子程序
以下子程序?qū)崿F(xiàn)2個(gè)16×16位有符號(hào)數(shù)加、減運(yùn)算,其和或差用一個(gè)16位數(shù)表示。在子程序中,減法是通過(guò)對(duì)減數(shù)求補(bǔ)后再與被減數(shù)相加來(lái)實(shí)現(xiàn)的。因此,當(dāng)程序從D_sub進(jìn)入子程序時(shí)為減法,當(dāng)從D_add進(jìn)入子程序時(shí)為加法。
子程序的入口條件和出口條件如下:
入口條件:16位被加數(shù)/被減數(shù)存放在ACCBHI、ACCBLO中;
              16位加數(shù)/減數(shù)存放在ACCAHI、ACCALO中;
出口條件:16位和/差存放在ACCBHI和ACCBLO中。
以下為16×16位有符號(hào)數(shù)加、減法子程序。
注意:在以下注釋程序中均以ACCA代替ACCAHI、ACCALO兩個(gè)字節(jié),以ACCB代替ACCBHI、ACCBLO兩個(gè)字節(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的補(bǔ)碼
;***雙字節(jié)加法子程序,入口地址ACCB+ACCA,出口地址ACCB***
D_add      MOVF     ACCALO,0    ;ACCB和ACCA低半字節(jié)相加
    ADDWF     ACCBLO
    BTFSC     STATUS,C    ;有進(jìn)位否?
    INCF     ACCBHI    ;有,ACCB高字節(jié)加1,再加ACCAHI
    MOVF     ACCAHI,0    ;ACCA、ACCB高半字節(jié)相加
    ADDWF     ACCBHI
    RETURN    ;子程序返回
;************** ACCA取補(bǔ)子程序*****************
NEG_A    COMF     ACCALO    ;ACCALO取反加1
    INCF     ACCALO

BTFSC     STATUS,Z    ;低8位有進(jìn)位嗎?
    DECF     ACCAHI    ;有,ACCAHI減1,再取反
    COMF     ACCAHI    ;否則ACCAHI直接取反
    RETURN    ;子程序返回
【校驗(yàn)舉例1】 19531+(-16594)=2937(十進(jìn)制)
化為十六進(jìn)制數(shù):4C46H+BF2EH
結(jié)果:0B79H(十六進(jìn)制)
【校驗(yàn)舉例2】 26222+3000=29222(十進(jìn)制)
化為十六進(jìn)制數(shù): 666EH+0BB8H
結(jié)果:7226H(十六進(jìn)制)
【例程】
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位定點(diǎn)數(shù)乘法子程序
子程序采用部分積右移加法實(shí)現(xiàn)乘法運(yùn)算。乘數(shù)和被乘數(shù)分別為16位二進(jìn)制有符號(hào)數(shù)(均采用補(bǔ)碼表示,第16位為符號(hào)位),積為32位二進(jìn)制有符號(hào)數(shù),第32位為符號(hào)位。子程序的入口條件和出口條件如下:
入口條件:被乘數(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    ;臨時(shí)寄存器
    ACCDHI     EQU     29    ;臨時(shí)寄存器
    TEMP     EQU     2A    ;臨時(shí)寄存器
    SIGN     EQU     2B    ;存放乘積的符號(hào)
    ORG    0X0000
START    GOTO     MAIN
;***16×16位乘法子程序,入口地址ACCB×ACCA,出口地址ACCB和ACCC ***
    ORG    0X0100
D_mpy    CALL     S_SIGN    ;求取乘積的符號(hào),并對(duì)負(fù)數(shù)取補(bǔ)
     CALL     SETUP    ;調(diào)用子程序,將ACCB的值送ACCD
    INCF    TEMP
    CLRF     ACCCHI    ;清ACCC
    CLRF     ACCCLO
MLOOP    BCF     STATUS,C    ;清進(jìn)位位

 RRF     ACCDHI    ;ACCD右移
    RRF     ACCDLO
    BTFSC     STATUS,C    ;判斷是否需要相加
    CALL     D_add    ;加乘數(shù)至ACCB,見(jiàn)加法程序
    BCF     STATUS,C    ;清進(jìn)位位
    RRF     ACCBHI    ;右移部分乘積
    RRF     ACCBLO
    RRF     ACCCHI
    RRF     ACCCLO
    DECFSZ     TEMP    ;乘法完成否?
    GOTO     MLOOP    ;否,繼續(xù)求乘積
    BTFSS     SIGN,7    ;是,確定乘積的符號(hào)
    GOTO     OVER    ;為正,乘法結(jié)束
    COMF     ACCCLO    ;為負(fù),乘積取補(bǔ)
    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        ;子程序返回
;*******乘法運(yùn)算確定結(jié)果符號(hào)判斷子程序******
S_SIGN    MOVF     ACCAHI,0    ;ACCAHI異或ACCBHI,結(jié)果送SIGN單元
    XORWF     ACCBHI,0

  MOVWF     SIGN            
    BTFSS     ACCBHI,7    ;ACCB為負(fù)嗎?
    GOTO     CHEK_A    ;否,檢查ACCA
    CALL    NEG_B    ;是,求取ACCB絕對(duì)值
CHEK_A    BTFSC     ACCAHI,7    ;ACCA為負(fù)嗎?
    CALL     NEG_A    ;ACCA為負(fù),求取ACCA絕對(duì)值,
            ;見(jiàn)雙字節(jié)加法程序
    RETURN        ;ACCA和ACCB均為正,返回
【校驗(yàn)舉例1】:-24555×(-7391)=181486005(十進(jìn)制)
化為十六進(jìn)制數(shù):A015H×E321H
結(jié)果:0AD141B5H(十六進(jìn)制)
【校驗(yàn)舉例2】 16405×13089=214725045(十進(jìn)制)
化為十六進(jìn)制數(shù):4015H×3321H
結(jié)果:0CCC71B5H(十六進(jìn)制)
【例程】
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位定點(diǎn)數(shù)除法子程序
子程序采用反復(fù)的減法算法,除數(shù)和被除數(shù)分別為16位二進(jìn)制有符號(hào)數(shù)(均采用補(bǔ)碼表示,第16位為符號(hào)位),商為16位二進(jìn)制有符號(hào)數(shù),第16位為符號(hào)位。子程序的入口條件和出口條件如下:
入口條件:被除數(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    ;臨時(shí)寄存器
    ACCDHI     EQU     27    ;臨時(shí)寄存器
    TEMP     EQU     28    ;臨時(shí)寄存器
    SIGN     EQU     29    ;存放商的符號(hào)
    ORG    0X0000
START    GOTO    MAIN

;***16×16位數(shù)除法子程序,入口地址ACCB /ACCA,出口地址ACCB ***
    ORG    0X0100
D_div    CALL     S_SIGN    ;確定商的符號(hào),并將負(fù)數(shù)取補(bǔ)
    CALL    SETUP    ;初始化TEMP,將被除數(shù)移至ACCD,
            ;(SETUP子程序請(qǐng)參見(jiàn)16×16位定點(diǎn)數(shù)
            ;乘法子程序SETUP)
    INCF    TEMP
    CLRF    ACCCHI    ;清余數(shù)寄存器
    CLRF    ACCCLO
DLOOP    BCF    STATUS,C    ;清進(jìn)位位
    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    ;置進(jìn)位位
NOGO    RLF    ACCBLO    ;商左移1位
    RLF    ACCBHI
    DECFSZ    TEMP    ;循環(huán)完畢?
    GOTO    DLOOP
    BTFSS     SIGN,7    ;是,確定商的符號(hào)
    GOTO     DIVOVER    ;為正,除法結(jié)束,跳轉(zhuǎn)到結(jié)束行
    COMF     ACCCLO    ;為負(fù),商和余數(shù)分別取補(bǔ)
    INCF     ACCCLO
    BTFSC    STATUS,Z
    DECF     ACCCHI
    COMF     ACCCHI
    CALL    NEG_B    ;見(jiàn)乘法程序中間NEG_B

DIVOVER    RETURN        ;子程序返回
;************除法運(yùn)算確定結(jié)果符號(hào)子程序*******************
S_SIGN    MOVF     ACCAHI,0    ;ACCAHI異或ACCBHI,結(jié)果送SIGN單元
    XORWF     ACCBHI,0
    MOVWF     SIGN            
    BTFSS     ACCBHI,7    ;ACCB為負(fù)?
    GOTO     CHEK_A    ;否,檢查ACCA
    COMF     ACCBLO    ;是,ACCB取補(bǔ)
    INCF     ACCBLO
    BTFSC     STATUS,Z
    DECF     ACCBHI
    COMF     ACCBHI
CHEK_A    BTFSC     ACCAHI,7    ;ACCA為負(fù)?
    CALL     NEG_A    ;ACCA為負(fù),取補(bǔ)(NEG_A子程序請(qǐng)參見(jiàn)
            ;16×16位定點(diǎn)數(shù)乘法子程序NEG_A)
    RETURN        ;ACCA和ACCB均為負(fù),返回
【校驗(yàn)舉例1】 -23775÷(-240)=99.0625(十進(jìn)制)
化為十六進(jìn)制數(shù):A321H÷FF10H;
結(jié)果:(商)0063H,(余數(shù))000FH(十六進(jìn)制)。
【校驗(yàn)舉例2】 769÷3856=0.199429(十進(jìn)制)

化為十六進(jìn)制數(shù):0301H÷0F10H;
結(jié)果:(商)0000H,(余數(shù))0301H(十六進(jìn)制)。
【例程】
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é)浮點(diǎn)四則運(yùn)算子程序
3.1  浮點(diǎn)數(shù)加(減)法子程序
以下為浮點(diǎn)加(減)運(yùn)算例程:

    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        ;臨時(shí)寄存器
    ACCCHI         EQU     27        ;臨時(shí)寄存器
    ACCDLO        EQU     28        ;臨時(shí)寄存器
    ACCDHI         EQU     29        ;臨時(shí)寄存器
    TEMP         EQU     2A        ;臨時(shí)寄存器
    TEMP1         EQU     30        ;臨時(shí)寄存器
    TIMES         EQU     31        ;臨時(shí)寄存器

  ORG             0X000
START    GOTO        MAIN
    ORG            0X0100
;**************浮點(diǎn)減法子程序****************
F_sub    CALL         NEG_A        ;求ACCA的補(bǔ)碼,將減法轉(zhuǎn)換為補(bǔ)碼加法
;***********浮點(diǎn)加法子程序**************
F_add    CALL        SUBADJ        ;調(diào)子程序判斷EXPB和EXPA的大小
    BTFSC         STATUS,Z    ;參與運(yùn)算的兩個(gè)數(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        ;是,存和(差)的階碼

联系我们: 双峰县| 三都| 灌阳县| 长治县| 碌曲县| 绥芬河市| 松溪县| 永和县| 凤台县| 天全县| 星子县| 岢岚县| 延川县| 贵溪市| 当雄县| 开化县| 普格县| 台东市| 新郑市| 新乡县| 大埔县| 冷水江市| 平潭县| 三门峡市| 漳平市| 秦皇岛市| 津南区| 鹤山市| 苍梧县| 中宁县| 梁平县| 虎林市| 武陟县| 桐城市| 忻州市| 民乐县| 安阳县| 吉林省| 寿宁县| 海晏县| 洛南县|