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

技術熱線: 4007-888-234
設計開發

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

開發工具

提供開發工具、應用測試 完善的開發代碼案例庫分享

技術支持

從全面的產品導入到強大技術支援服務 全程貼心伴隨服務,創造無限潛能!

新聞中心

提供最新的單片機資訊,行業消息以及公司新聞動態

PIC16F877 運算子程序

更新時間: 2019-03-26
閱讀量:1724

1  PIC16F877匯編語言程序主體框架
以下是一個典型的程序結構:
***************程序說明區*******************
    LIST    p=16f877    ;指定微控制器型號和文件輸出格式
    INCLUDE    p16f877.inc    ;讀入MPLAB提供的定義文件P16F877.INC
***片內RAM常用資源、變量定義和相應的說明*********
    ACCALO    EQU  20    ;存放加數或減數低8
    ACCAHI     EQU  21    ;存放加數或減數高8
    ACCBLO     EQU     23    ;存放被加數或被減數低8
    ACCBHI     EQU     24    ;存放被加數或被減數高8
    S_W    EQU     25    ;棧存W寄存器值
    S_STATUS    EQU    26    ;棧存STATUS寄存器值
****************芯片復位矢量*******************
    ORG          0X0000    ;由于PIC16F877芯片復位矢量在0000h
        ;元,所以常在0000h單元處放置一條跳轉
        ;指令,使單片機復位后能跳過中斷矢量,
                                ;直接執行主程序
START    GOTO        MAIN        
******************中斷矢量**********************

ORG          0X0004    ;由于PIC16F877的中斷矢量為0004h,所以
        ;當中斷開放時, 需在此處加入中斷程序,
        ;使單片機能在中斷到來時及時進入相應的
        ;中斷服務程序。為了可靠起見,如果單片
        ;機不使用中斷,則常常在該中斷矢量處放
        ;置RETFIE指令,可以使單片機不會因
        ;干擾產生誤中斷而導致程序跑飛
    CALL    PUSH    ;調用保護現場子程序
    BTFSS    PIR1ADIF
    CALL    AD    ;若AD中斷到,則執行中斷服務程序
    ……..        ;此處可放多個中斷子程序,并以軟件安排
            ;中斷優先級
    CALL    POP    ;恢復中斷現場
    RETFIE    ;中斷返回
****************主程序區*****************
    ORG    0X0100    ;將主程序、子程序和中斷服務程序等存放
        ;在0100h單元之后,在中斷矢量和主程序
        ;區之間預留一些存儲單元,以便寫入判
        ;跳指令和一些必要的現場保護程序。此外
        ;用戶也可以根據實際需要,使主程序從其
        ;它地址開始存放
MAIN    BSF          STATUSRP0    ;選擇存儲體1
    MOVLW    0XFF    ;定義RA口為輸入端口

MOVWF    TRISA
    BCF    STATUSRP0    ;選擇存儲體0
    MOVLW    0X04    ;初值化ACCALO
    MOVWF    ACCALO    
    CALL    DX    ;調用DX子程序
LOOP1    ……    ;任務1
    ……    ;任務2
    :
    :
    :
    GOTO    LOOP1    ;反復執行任務一和任務二等
***************子程序區*********************
DX    MOVF        ACCALO0    ACCBACCA低半字節相加
    ADDWF     ACCBLO
    RETURN        ;子程序返回
****************************************
PUSH    MOVWF      S_W    ;保護W寄存器
    MOVF    STATUS0    ;保護STATUS寄存器
    MOVWF    S_STATUS
    RETURN        ;子程序返回
****************************************

POP    MOVF        S_STATUS0    ;恢復STATUS寄存器
    MOVWF    STATUS
    MOVF    S_W0    ;恢復W寄存器
    RETURN    ;子程序返回
****************中斷服務子程序區************************
AD        BCF            PIR1ADIF    ;清AD中斷標志
    ……                        ;中斷服務主體程序
    RETURN                    ;子程序返回
            END
2  四則運算子程序
2.1  16×16位定點數加、減法子程序
以下子程序實現216×16位有符號數加、減運算,其和或差用一個16位數表示。在子程序中,減法是通過對減數求補后再與被減數相加來實現的。因此,當程序從D_sub進入子程序時為減法,當從D_add進入子程序時為加法。
子程序的入口條件和出口條件如下:
入口條件:16位被加數/被減數存放在ACCBHIACCBLO;
              16位加數/減數存放在ACCAHIACCALO;
出口條件:16位和/差存放在ACCBHIACCBLO中。
以下為16×16位有符號數加、減法子程序。
注意:在以下注釋程序中均以ACCA代替ACCAHIACCALO兩個字節,以ACCB代替ACCBHIACCBLO兩個字節。

    LIST            p=16f877

 INCLUDE        p16f877.inc
    ACCALO     EQU     20    ;存放加數或減數低8
    ACCAHI     EQU     21    ;存放加數或減數高8
    ACCBLO     EQU     23    ;存放被加數或被減數低8
    ACCBHI     EQU     24    ;存放被加數或被減數高8
    ORG    0X0000
START    GOTO     MAIN
***雙字節減法子程序,入口地址ACCB-ACCA,出口地址ACCB***
D_sub    CALL    NEG_A    ;求ACCA的補碼
***雙字節加法子程序,入口地址ACCB+ACCA,出口地址ACCB***
D_add      MOVF     ACCALO0    ACCBACCA低半字節相加
    ADDWF     ACCBLO
    BTFSC     STATUSC    ;有進位否?
    INCF     ACCBHI    ;有,ACCB高字節加1,再加ACCAHI
    MOVF     ACCAHI0    ACCAACCB高半字節相加
    ADDWF     ACCBHI
    RETURN    ;子程序返回
************** ACCA取補子程序*****************
NEG_A    COMF     ACCALO    ACCALO取反加1
    INCF     ACCALO

BTFSC     STATUSZ    ;低8位有進位嗎?
    DECF     ACCAHI    ;有,ACCAHI1,再取反
    COMF     ACCAHI    ;否則ACCAHI直接取反
    RETURN    ;子程序返回
【校驗舉例119531+-16594=2937(十進制)
化為十六進制數:4C46H+BF2EH
結果:0B79H(十六進制)
【校驗舉例226222+3000=29222(十進制)
化為十六進制數: 666EH+0BB8H
結果:7226H(十六進制)
【例程】
MAIN    MOVLW      0X6E    ;被加數666EHACCB
    MOVWF    ACCBLO
    MOVLW    0X66
    MOVWF    ACCBHI
    MOVLW    0XB8    ;加數BB8HACCA
    MOVWF    ACCALO
    MOVLW    0X0B
    MOVWF    ACCAHI
    CALL    D_add    ;調用雙字節加法子程序,求和
    END

2.2  16×16位定點數乘法子程序
子程序采用部分積右移加法實現乘法運算。乘數和被乘數分別為16位二進制有符號數(均采用補碼表示,第16位為符號位),積為32位二進制有符號數,第32位為符號位。子程序的入口條件和出口條件如下:
入口條件:被乘數存放在ACCBHIACCBLO單元中,
          乘數存放在ACCAHIACCALO單元中。
出口條件:積存放在ACCBHIACCBLOACCCHIACCCLO單元中,ACCB為高16位,ACCC為低16位。
以下為本子程序的程序清單:

  LIST    p=16f877
    INCLUDE    p16f877.inc
    ACCALO     EQU     20    ;存放乘數低8
    ACCAHI     EQU     21    ;存放乘數高8
    ACCBLO     EQU     23    ;存放被乘數低8位和乘積第1623
    ACCBHI     EQU     24    ;存放被乘數高8位和乘積第2431
    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,出口地址ACCBACCC ***
    ORG    0X0100
D_mpy    CALL     S_SIGN    ;求取乘積的符號,并對負數取補
     CALL     SETUP    ;調用子程序,將ACCB的值送ACCD
    INCF    TEMP
    CLRF     ACCCHI    ;清ACCC
    CLRF     ACCCLO
MLOOP    BCF     STATUSC    ;清進位位

 RRF     ACCDHI    ACCD右移
    RRF     ACCDLO
    BTFSC     STATUSC    ;判斷是否需要相加
    CALL     D_add    ;加乘數至ACCB,見加法程序
    BCF     STATUSC    ;清進位位
    RRF     ACCBHI    ;右移部分乘積
    RRF     ACCBLO
    RRF     ACCCHI
    RRF     ACCCLO
    DECFSZ     TEMP    ;乘法完成否?
    GOTO     MLOOP    ;否,繼續求乘積
    BTFSS     SIGN7    ;是,確定乘積的符號
    GOTO     OVER    ;為正,乘法結束
    COMF     ACCCLO    ;為負,乘積取補
    INCF         ACCCLO

  BTFSC        STATUSZ
    DECF         ACCCHI
    COMF         ACCCHI
    BTFSC         STATUSZ
NEG_B    DECF         ACCBLO        
    COMF         ACCBLO
    BTFSC         STATUSZ
    DECF         ACCBHI
    COMF         ACCBHI
OVER    RETURN        ;子程序返回
****************************************
SETUP    MOVLW     .15    ;初始化TEMP寄存器        
    MOVWF     TEMP
    MOVF     ACCBHI0    ACCBACCD
    MOVWF    ACCDHI
    MOVF     ACCBLO0
    MOVWF     ACCDLO
    CLRF     ACCBHI    ;清ACCB
    CLRF     ACCBLO
    RETURN        ;子程序返回
*******乘法運算確定結果符號判斷子程序******
S_SIGN    MOVF     ACCAHI0    ACCAHI異或ACCBHI,結果送SIGN單元
    XORWF     ACCBHI0

  MOVWF     SIGN            
    BTFSS     ACCBHI7    ACCB為負嗎?
    GOTO     CHEK_A    ;否,檢查ACCA
    CALL    NEG_B    ;是,求取ACCB絕對值
CHEK_A    BTFSC     ACCAHI7    ACCA為負嗎?
    CALL     NEG_A    ACCA為負,求取ACCA絕對值,
            ;見雙字節加法程序
    RETURN        ACCAACCB均為正,返回
【校驗舉例1】:-24555×-7391=181486005(十進制)
化為十六進制數:A015H×E321H
結果:0AD141B5H(十六進制)
【校驗舉例216405×13089=214725045(十進制)
化為十六進制數:4015H×3321H
結果:0CCC71B5H(十六進制)
【例程】
MAIN    MOVLW    0X15    ;被乘數4015HACCB
    MOVWF    ACCBLO
    MOVLW    0X40
    MOVWF    ACCBHI
    MOVLW    0X21    ;乘數3321HACCA
    MOVWF    ACCALO

  MOVLW    0X33
    MOVWF    ACCAHI
    CALL    D_mpy    ;調用雙字節乘法子程序,求積
    END
2.3  16×16位定點數除法子程序
子程序采用反復的減法算法,除數和被除數分別為16位二進制有符號數(均采用補碼表示,第16位為符號位),商為16位二進制有符號數,第16位為符號位。子程序的入口條件和出口條件如下:
入口條件:被除數存放在ACCBHIACCBLO單元中;
      除數存放在ACCAHIACCALO單元中。
出口條件:商存放在ACCBHIACCBLO單元中;
          余數存放在ACCCHIACCCLO單元中。
    
    LIST    p=16f877
    INCLUDE    p16f877.inc
    ACCALO    EQU     20    ;存放除數低8
    ACCAHI     EQU     21    ;存放除數高8
    ACCBLO     EQU     22    ;存放被除數和商的低8
    ACCBHI     EQU     23    ;存放被除數和商的高8
    ACCCLO     EQU     24    ;存放余數低8
    ACCCHI     EQU     25    ;存放余數高8
    ACCDLO     EQU     26    ;臨時寄存器
    ACCDHI     EQU     27    ;臨時寄存器
    TEMP     EQU     28    ;臨時寄存器
    SIGN     EQU     29    ;存放商的符號
    ORG    0X0000
START    GOTO    MAIN

***16×16位數除法子程序,入口地址ACCB /ACCA,出口地址ACCB ***
    ORG    0X0100
D_div    CALL     S_SIGN    ;確定商的符號,并將負數取補
    CALL    SETUP    ;初始化TEMP,將被除數移至ACCD
            ;(SETUP子程序請參見16×16位定點數
            ;乘法子程序SETUP
    INCF    TEMP
    CLRF    ACCCHI    ;清余數寄存器
    CLRF    ACCCLO
DLOOP    BCF    STATUSC    ;清進位位
    RLF    ACCDLO    ;被除數、余數左移1
    RLF    ACCDHI
    RLF    ACCCLO
    RLF    ACCCHI
    MOVF    ACCAHI0    ACCCHI-ACCAHI
    SUBWF    ACCCHI0
    BTFSS    STATUSZ    ACCCHI=ACCAHI

 GOTO    NOCHK
    MOVF    ACCALO0    ;是,ACCCLO-ACCALO
    SUBWF    ACCCLO0
NOCHK    BTFSS    STATUSC    ACCC>ACCA
    GOTO    NOGO
    MOVF    ACCALO0    ;是,余數減除數
    SUBWF    ACCCLO
    BTFSS    STATUSC
    DECF    ACCCHI
    MOVF    ACCAHI0
    SUBWF    ACCCHI
    BSF    STATUSC    ;置進位位
NOGO    RLF    ACCBLO    ;商左移1
    RLF    ACCBHI
    DECFSZ    TEMP    ;循環完畢?
    GOTO    DLOOP
    BTFSS     SIGN7    ;是,確定商的符號
    GOTO     DIVOVER    ;為正,除法結束,跳轉到結束行
    COMF     ACCCLO    ;為負,商和余數分別取補
    INCF     ACCCLO
    BTFSC    STATUSZ
    DECF     ACCCHI
    COMF     ACCCHI
    CALL    NEG_B    ;見乘法程序中間NEG_B

DIVOVER    RETURN        ;子程序返回
************除法運算確定結果符號子程序*******************
S_SIGN    MOVF     ACCAHI0    ACCAHI異或ACCBHI,結果送SIGN單元
    XORWF     ACCBHI0
    MOVWF     SIGN            
    BTFSS     ACCBHI7    ACCB為負?
    GOTO     CHEK_A    ;否,檢查ACCA
    COMF     ACCBLO    ;是,ACCB取補
    INCF     ACCBLO
    BTFSC     STATUSZ
    DECF     ACCBHI
    COMF     ACCBHI
CHEK_A    BTFSC     ACCAHI7    ACCA為負?
    CALL     NEG_A    ACCA為負,取補(NEG_A子程序請參見
            16×16位定點數乘法子程序NEG_A
    RETURN        ACCAACCB均為負,返回
【校驗舉例1-23775÷-240=99.0625(十進制)
化為十六進制數:A321H÷FF10H
結果:(商)0063H,(余數)000FH(十六進制)。
【校驗舉例2769÷3856=0.199429(十進制)

化為十六進制數:0301H÷0F10H
結果:(商)0000H,(余數)0301H(十六進制)。
【例程】
MAIN    MOVLW    0X01    ;被除數0301HACCB
    MOVWF    ACCBLO
    MOVLW    0X03
    MOVWF    ACCBHI
    MOVLW    0X10    ;除數0F10HACCA
    MOVWF    ACCALO
    MOVLW    0X0F
    MOVWF    ACCAHI
    CALL    D_div    ;調用雙字節除法子程序,求商
    END
3  3字節浮點四則運算子程序
3.1  浮點數加(減)法子程序
以下為浮點加(減)運算例程:

    LIST            p=16f877
    INCLUDE         p16f877.inc
    ACCALO         EQU     20        ;存放加數或減數的尾數
    ACCAHI         EQU    21
    EXPA        EQU     22        ;存放加數或減數階碼
    ACCBLO        EQU     23        ;存放被加數或被減數尾數以及和或差
    ACCBHI         EQU     24
    EXPB         EQU    25        ;存放被加數或被減數階碼
    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的補碼,將減法轉換為補碼加法
***********浮點加法子程序**************
F_add    CALL        SUBADJ        ;調子程序判斷EXPBEXPA的大小
    BTFSC         STATUSZ    ;參與運算的兩個數階碼相等?
    GOTO         PADD        ;是,求尾數的和

BTFSC         STATUSC    EXPB>EXPA
    CALL         F_swap        ;是,ACCBACCA互換
    MOVF         EXPA0        ;否,求取兩者的差值
    SUBWF         EXPB
SCLOOP    CALL         SHFTSR        ACCB右移規格化
    INCFSZ         EXPB        EXPBEXPA?        
    GOTO         SCLOOP        ;否,繼續右移
    MOVF         EXPA0        ;是,存和(差)的階碼


联系我们: 伽师县| 太谷县| 兴海县| 铁力市| 四子王旗| 富平县| 茶陵县| 浦东新区| 平谷区| 磐安县| 东方市| 龙门县| 泸西县| 灌云县| 湖南省| 淮北市| 临沭县| 肇源县| 平原县| 康平县| 鄯善县| 孟连| 板桥市| 晋州市| 防城港市| 旬邑县| 黎川县| 安徽省| 永济市| 陆丰市| 汉沽区| 阜宁县| 伽师县| 横山县| 乌拉特中旗| 离岛区| 肃宁县| 通榆县| 融水| 淄博市| 桐梓县|