Elektronik / Mikrodenetleyici Projeleri/

PIC16C622 ile direnç kapasitör ölçümü (RC metre)

Sponsorlu Bağlantılar

Devre PIC16C622 mikrodenetleyicisi üzerine kurulu 1Ω  999Ω  arası direnç ölçümü 1nF 999 nF arası kapasitör ölçümü yapılabiliryor bilgisayar bağlantısı bulunuyor denetleyici yazılımı assembly ile pc yazılımı Visual Basic ile hazırlanmış. PIC16C622 ve uygulama devresi hakkında tüm detaylar formüller verilmiş orjinal microchip uygulama notudur.

Devre şeması;

The application circuit, called PICMETER, uses a PIC16C622 as a resistance and capacitance meter. The PICMETER uses a variation of the single-slope integrating converter. The linear slope and integrator of Figure 13 are replaced with the exponential charge waveform of an RC. The charge time of a known component is compared against the charge time of an unknown component to determine the value of the unknown component.

A schematic of the PICMETER is shown in Figure 16. All reference designators cited in this section refer to this schematic. Results are transmitted to a PC which displays the value measured.

Uygulama notu ve kodlar: PIC16C622 ile direnç kapasitör ölçümü (RC metre)

Dosya indirme LINK listesi (TXT formatında) link-9194.zip şifre-pass: 320volt.com


        TITLE "PICMETER Firmware for PIC16C622"
        LIST P = 16C622, F = INHX8M

        INCLUDE "C:\PICMASTR\P16CXX.INC"

        __FUSES _BODEN_OFF&_CP_OFF&_PWDT_ON&_WDT_OFF&_XT_OSC

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-                                                                        -*
;*-     PICMETER - Resistance and Capacitance Meter                        -*
;*-                                                                        -*
;*--------------------------------------------------------------------------*
;*-                                                                        -*
;*-     Author:         Rodger Richey                                      -*
;*-                     Applications Engineer                              -*
;*-     Filename:       picmeter.asm                                         -*
;*-     Revision:       1 May 1995                                         -*
;*-                                                                        -*
;*--------------------------------------------------------------------------*
;*-                                                                        -*
;*-     PICMETER is based on a PIC16C622 which has two comparators and a   -*
;*-     variable voltage reference.  Resistance and capacitance is         -*
;*-     calculated by measuring the time constant of a RC network.  The    -*
;*-     toggle switch selects either resistor or capacitor input.  The     -*
;*-     pushbutton switch starts a measurement.  The time constant of the  -*
;*-     unknown component is compared to that of known component to        -*
;*-     calculate the value of the unknown component.  The following       -*
;*-     formulas are used:                                                 -*
;*-                                                                        -*
;*-     Resistance:     Ru = ( Rk * Tu ) / Tk                              -*
;*-     Capacitance:    Cu = ( Ck * Tu ) / Tk                              -*
;*-                                                                        -*
;*--------------------------------------------------------------------------*
;****************************************************************************


;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     RS232 code borrowed from Application Note AN593                    -*
;*-     "Serial Port Routines Without Using the RTCC"                      -*
;*-     Author: Stan D'Souza                                               -*
;*--------------------------------------------------------------------------*
;****************************************************************************
xtal    equ     .4000000
baud    equ     .9600
fclk    equ     xtal/4
;****************************************************************************
;The value baudconst must be a 8-bit value only
baudconst       equ     ((fclk/baud)/3-2)
;****************************************************************************


;****************************************************************************
;       Bit Equates 
;****************************************************************************
BEGIN   equ     0               ;begin a measurement flag
DONE    equ     7               ;done measuring flag
WHICH   equ     5               ;R or C measurement flag
F_ERROR equ     3               ;error detection flag
EMPTY   equ     5               ;flag if component is connected
V0      equ     0               ;power for R reference ckt
V1      equ     1               ;power for C reference ckt
V2      equ     2               ;ground for C reference ckt
V3      equ     3               ;power for unknown R ckt
V4      equ     4               ;ground for unknown C ckt 
msb_bit equ     7               ;define for bit 7
lsb_bit equ     0               ;define for bit 0
RkHI    equ     0x07            ;value of the known resistance, R4, in ohms
RkMID   equ     0x9D            ;measured by a Fluke meter
RkLO    equ     0x38
CkHI    equ     0x07            ;value of the known capacitance, C1, in pF
CkMID   equ     0x47            ;measured by a Fluke meter
CkLO    equ     0x48

;****************************************************************************
;       User Registers
;****************************************************************************
;       Bank 0
W_TEMP  equ     0x20            ;Bank 0 temporary storage for W reg
STATUS_TEMP equ 0x21            ;temporary storage for STATUS reg
Ttemp   equ     0x23            ;temporary Time register
flags   equ     0x24            ;flags register
count   equ     0x25            ;RS232 register
txreg   equ     0x26            ;RS232 data register
delay   equ     0x27            ;RS232 delay register
offset  equ     0x28            ;table position register
msb     equ     0x29            ;general delay register
lsb     equ     0x2A            ;general delay register
TimeLO  equ     0x40            ;Time registers
TimeMID equ     0x41
TimeHI  equ     0x42

;       Math related registers
ACCaHI  equ     0x50            ;24-Bit accumulator a
ACCaMID equ     0x51
ACCaLO  equ     0x52
ACCbHI  equ     0x53            ;24-Bit accumulator b
ACCbMID equ     0x54
ACCbLO  equ     0x55
ACCcHI  equ     0x56            ;24-Bit accumulator c
ACCcMID equ     0x57
ACCcLO  equ     0x58
ACCdHI  equ     0x59            ;24-Bit accumulator d
ACCdMID equ     0x5A
ACCdLO  equ     0x5B
temp    equ     0x5C            ;temporary storage

;       User Registers Bank 1
;W_TEMP  equ     0xA0            ;Bank 1 temporary storage for W reg

;       User defines
#define tx      PORTB,7         ;define for RS232 TXD output pin

;****************************************************************************        

        org     0x0
        goto    init

        org     0x4
        goto    ServiceInterrupts

        org     0x10
init
        bcf     STATUS,RP0      ;select bank 0
        clrf    PORTA           ;clear PORTA and PORTB
        clrf    PORTB
        bsf     tx              ;set TXD output pin
        clrf    flags           ;clear flags register
        movlw   0x10            ;load table offset register
        movwf   offset  
        clrf    INTCON          ;clear interrupt flags and disable interrupts
        movlw   0x07            ;turn off comparators, mode 111
        movwf   CMCON
        call    delay20         ;wait for comarators to settle
        movf    CMCON,F
        bcf     PIR1,CMIF
        bsf     STATUS,RP0      ;select bank 1
        movlw   0x88            ;WDT prescalar,internal TMR0 increment
        movwf   OPTION_REG
        clrf    TRISA           ;PORTA all outputs, discharges RC ckts
        movlw   0x60            ;PORTA<7,4:0> outputs, PORTA<6:5> inputs
        movwf   TRISB
        movlw   0x0C            ;setup Voltage Reference
        movwf   VRCON
        bcf     STATUS,RP0      ;select bank 0
        movlw   0x08            ;enable RBIE interrupt
        movwf   INTCON  
        call    vlong           ;delay before transmitting boot message
        call    vlong           ;to allow computer program to setup
        call    vlong
        call    BootMSG         ;transmit boot message
        bsf     INTCON,GIE      ;enable global interrupt bit

start   
        btfss   flags,BEGIN     ;wait for a start measurement key press
        goto    start
        bcf     flags,BEGIN     ;clear start measurement flag
        
        bcf     INTCON,GIE      ;transmit a start measurement message 
        movlw   'S'             ;to the PC
        call    Send
        bsf     INTCON,GIE
        
        clrf    TimeHI          ;reset Time registers
        clrf    TimeMID
        clrf    TimeLO
        btfss   PORTB,WHICH     ;detect if resistor or capacitor measure   
        goto    Capacitor

Resistor
        bsf     STATUS,RP0      ;set V0 to input
        bsf     TRISB,V0
        bcf     STATUS,RP0
        call    AnalogOn        ;turn analog on
        clrf    TMR0
        nop
        bsf     PORTB,V3        ;turn power on to unknown RC ckt
RwaitU  btfsc   flags,F_ERROR   ;detect if an error occurs
        goto    ErrorDetect
        btfss   flags,DONE      ;measurement completed flag
        goto    RwaitU
        bcf     flags,DONE      ;clear measurement completed flag
        call    AnalogOff       ;turn analog off
        
        call    SwapTtoA        ;swap Time to accumulator a
        movlw   RkHI            ;swap known resistance value
        movwf   ACCbHI          ;to accumulator b
        movlw   RkMID
        movwf   ACCbMID
        movlw   RkLO
        movwf   ACCbLO
        call    Mpy24           ;multiply accumulator a and b

        bsf     STATUS,RP0      ;set V3 to input
        bsf     TRISB,V3
        bcf     STATUS,RP0
        call    AnalogOn        ;turn analog on
        clrf    TMR0
        nop
        bsf     PORTB,V0        ;turn power on to known RC ckt
RwaitK  btfsc   flags,F_ERROR   ;detect if an error occurs
        goto    ErrorDetect
        btfss   flags,DONE      ;measurement completed flag
        goto    RwaitK
        bcf     flags,DONE      ;clear measurement completed flag
        call    AnalogOff       ;turn analog off
        
        call    SwapTtoA        ;swap Time to accumulator a
        call    Div24           ;divide multiply by known time

        bcf     INTCON,GIE      ;disable all interrupts
        movlw   'R'             ;transmit, for R measurement
        call    Send
        bsf     INTCON,GIE      ;enable global interrupt bit
        goto    start           ;restart

Capacitor
        bsf     STATUS,RP0      ;set V2 to input
        bsf     TRISB,V2
        bcf     STATUS,RP0
        call    AnalogOn        ;turn analog on
        clrf    TMR0
        nop
        bsf     PORTB,V1        ;turn power on to unknown RC ckt
CwaitU  btfsc   flags,F_ERROR   ;detect if an error occurs
        goto    ErrorDetect
        btfss   flags,DONE      ;measurement completed flag
        goto    CwaitU
        bcf     flags,DONE      ;clear measurement completed flag
        call    AnalogOff       ;turn analog off

        call    SwapTtoA        ;swap Time to accumulator a
        movlw   CkHI            ;swap known resistance value
        movwf   ACCbHI          ;to accumulator b
        movlw   CkMID
        movwf   ACCbMID
        movlw   CkLO
        movwf   ACCbLO
        call    Mpy24           ;multiply accumulator a and b
        
        bsf     STATUS,RP0      ;set V3 to input
        bsf     TRISB,V4
        bcf     STATUS,RP0
        call    AnalogOn        ;turn analog on
        clrf    TMR0
        nop
        bsf     PORTB,V1        ;turn power on to known RC ckt
CwaitK  btfsc   flags,F_ERROR   ;detect if an error occurs
        goto    ErrorDetect
        btfss   flags,DONE      ;measurement completed flag
        goto    CwaitK
        bcf     flags,DONE      ;clear measurement completed flag
        call    AnalogOff       ;turn analog off

        call    SwapTtoA        ;swap Time to accumulator a
        call    Div24           ;divide multiply by known time
        
        bcf     INTCON,GIE      ;disable all interrupts
        movlw   'C'             ;transmit, for C measurement
        call    Send
        bsf     INTCON,GIE      ;enable global interrupt bit
        goto    start           ;restart

ErrorDetect
        bcf     STATUS,RP0      ;disable TMR0
        bcf     INTCON,T0IE
        bcf     INTCON,T0IF
        call    AnalogOff       ;turn analog off
        bcf     flags,F_ERROR   ;clear error flag
        
        bcf     INTCON,GIE      ;disable all interrupts
        movlw   'E'             ;transmit, for C measurement
        call    Send
        bsf     INTCON,GIE      ;enable global interrupt bit
        goto    start           ;restart

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     RS232 Transmit Routine                                             -*
;*-     Borrowed from AN593, "Serial Port Routines Without Using the RTCC" -*
;*-     Author: Stan D'Souza                                               -*
;*-     This is the routine that interfaces directly to the hardware       -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Transmit
        bcf     STATUS,RP0
        movwf   txreg
        bcf     tx              ;send start bit
        movlw   baudconst
        movwf   delay
        movlw   0x9
        movwf   count
txbaudwait
        decfsz  delay
        goto    txbaudwait
        movlw   baudconst
        movwf   delay
        decfsz  count
        goto    SendNextBit
        movlw   0x9
        movwf   count
        bsf     tx              ;send stop bit
        return
SendNextBit
        rrf     txreg
        btfss   STATUS,C
        goto    Setlo
        bsf     tx
        goto    txbaudwait
Setlo   bcf     tx
        goto    txbaudwait
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Generic Transmit Routine                                           -*
;*-     Sends what is currently in the W register and accumulator ACCc     -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Send        
        call    Transmit
        call    delay1          ;delay between bytes
        movf    ACCcHI,W        ;transmit high resistance byte
        call    Transmit
        call    delay1          ;delay between bytes
        movf    ACCcMID,W       ;transmit mid resistance byte
        call    Transmit
        call    delay1          ;delay between bytes
        movf    ACCcLO,W        ;transmit low resistance byte
        call    Transmit
        call    delay1          ;delay between bytes
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Interrupt Service Routines                                         -*
;*--------------------------------------------------------------------------*
;****************************************************************************
ServiceInterrupts
        movwf   W_TEMP             ;Pseudo push instructions
        swapf   STATUS,W
        bcf     STATUS,RP0
        movwf   STATUS_TEMP

        movf    TMR0,W
        movwf   Ttemp
        btfsc   INTCON,T0IF        ;Service Timer 0 overflow
        call    ServiceTimer
        btfsc   PIR1,CMIF          ;Stops Timer0, Records Value
        call    ServiceComparator
        btfsc   INTCON,RBIF        ;Service pushbutton switch
        call    ServiceKeystroke   ;Starts a measurement
        
        bcf     STATUS,RP0
        swapf   STATUS_TEMP,W      ;Pseudo pop instructions
        movwf   STATUS
        swapf   W_TEMP,F
        swapf   W_TEMP,W

        retfie
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Borrowed from AN552, "Implementing Wake-up on Key Stroke"          -* 
;*-     Author: Stan D'Souza                                               -* 
;*--------------------------------------------------------------------------*
;****************************************************************************
ServiceKeystroke
        bcf     INTCON,RBIE     ;disable interrupt
        comf    PORTB,W         ;read PORTB
        bcf     INTCON,RBIF     ;clear interrupt flag
        andlw   B'01000000'
        btfsc   STATUS,Z
        goto    NotSwitch
        call    delay16         ;de-bounce switch for 16msec
        comf    PORTB,W         ;read PORTB again
        call    KeyRelease      ;check for key release
        bsf     flags,BEGIN
        return

NotSwitch                       ;detected other PORTB pin change
        bcf     INTCON,RBIF     ;reset RBI interrupt
        bsf     INTCON,RBIE
        return

KeyRelease
        call    delay16         ;debounce switch
        comf    PORTB,W         ;read PORTB
        bcf     INTCON,RBIF     ;clear flag
        bsf     INTCON,RBIE     ;enable interrupt
        andlw   B'01000000'
        btfsc   STATUS,Z        ;key still pressed?
        return                  ;if no, then return
        sleep                   ;else, save power
        bcf     INTCON,RBIE     ;disable interrupts
        comf    PORTB,W         ;read PORTB
        bcf     INTCON,RBIF     ;clear flag
        goto    KeyRelease      ;try again
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     ISR to service a Timer0 overflow                                   -*
;*--------------------------------------------------------------------------*
;****************************************************************************
ServiceTimer
        incf    TimeMID,F       ;increment middle Time byte
        btfsc   STATUS,Z        ;if middle overflows,
        incf    TimeHI,F        ;increment high Time byte       
        btfsc   TimeHI,EMPTY    ;check if component is connected
        bsf     flags,F_ERROR   ;set error flag
        bcf     INTCON,T0IF     ;clear TMR0 interrupt flag
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     ISR to service a Comparator interrupt                              -*
;*--------------------------------------------------------------------------*
;****************************************************************************
ServiceComparator
        bcf     STATUS,RP0      ;select bank 0
        btfss   PORTB,WHICH     ;detect which measurement, R or C?
        goto    capcomp
        btfss   CMCON,C1OUT     ;detect if R ckt has interrupted
        goto    scstop
        goto    scend
capcomp
        btfsc   CMCON,C2OUT     ;detect if C ckt has interrupted
        goto    scend
scstop
        bcf     INTCON,T0IE     ;disable TMR0 interrupts
        bcf     INTCON,T0IF
        movf    Ttemp,W
        movwf   TimeLO
        bsf     flags,DONE      ;set DONE flag
scend
        bcf     PIR1,CMIF       ;clear comparator interrupt flag
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Turn Comparators and Vref On                                       -*
;*--------------------------------------------------------------------------*
;****************************************************************************
AnalogOn
        bcf     STATUS,RP0      ;select bank 0
        movlw   0x02            ;turn comparators on, mode 010
        movwf   CMCON           ;4 inputs multiplexed to 2 comparators
        bsf     STATUS,RP0      ;select bank 1
        movlw   0x0F            ;make PORTA<3:0> all inputs
        movwf   TRISA
        bsf     VRCON,VREN
        bcf     STATUS,RP0      ;select bank 0
        call    delay20         ;20msec delay
        movf    CMCON,F         ;clear comparator mismatch condition
        bcf     PIR1,CMIF       ;clear comparator interrupt flag
        bsf     STATUS,RP0
        bsf     PIE1,CMIE       ;enable comparator interrupts
        bcf     STATUS,RP0
        bsf     INTCON,PEIE     ;enable peripheral interrupts
        bcf     flags,F_ERROR
        clrf    TMR0            ;clear TMR0 counter
        nop
        nop
        bcf     INTCON,T0IF     ;clear TMR0 interrupt flag
        bsf     INTCON,T0IE     ;enable TMR0 interrupts
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Turn Comparators and Vref Off                                      -*
;*--------------------------------------------------------------------------*
;****************************************************************************
AnalogOff
        bcf     STATUS,RP0
        bcf     INTCON,PEIE
        movlw   0x80            ;reset PORTB value
        movwf   PORTB
        bsf     STATUS,RP0      ;select bank 1
        bcf     PIE1,CMIE       ;disable comparator interrupts
        clrf    TRISA           ;set PORTA pins to outputs, discharge RC ckt
        movlw   0x60            ;set PORTB 7,4-0 as outputs, 6,5 as inputs
        movwf   TRISB
        bcf     VRCON,VREN      ;disable Vref
        bcf     STATUS,RP0      ;select bank 0
        movlw   0x07
        movwf   CMCON           ;disable comparators
        call    delay20         ;20msec delay
        movf    CMCON,F         ;clear comparator mismatch condition
        bcf     PIR1,CMIF       ;clear comparator interrupt flag
        bcf     INTCON,T0IF     ;clear Timer0 interrupt flag
        call    vlong           ;long delay to allow capacitors to discharge
        call    vlong   
        call    vlong
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Swap Time to Accumulator a                                         -*
;*--------------------------------------------------------------------------*
;****************************************************************************
SwapTtoA
        bcf     STATUS,RP0
        movf    TimeHI,W
        movwf   ACCaHI
        movf    TimeMID,W
        movwf   ACCaMID
        movf    TimeLO,W
        movwf   ACCaLO
        clrf    TimeHI
        clrf    TimeMID
        clrf    TimeLO
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Transmit the Boot Message                                          -*
;*--------------------------------------------------------------------------*
;****************************************************************************
BootMSG     
        bcf     STATUS,RP0      ;select bank 0
msg     movlw   HIGH Table      ;init the PCH for a table call
        movwf   PCLATH
        movf    offset,W        ;move table offset into W
        call    Table           ;get table value
        call    Transmit        ;transmit table value
        call    delay1          ;delay between bytes
        decfsz  offset,F        ;check for end of table
        goto    msg
        movlw   0x10            ;reset table offset
        movwf   offset
        return
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Delay Routines                                                     -*
;*--------------------------------------------------------------------------*
;****************************************************************************
vlong   movlw   0xff            ;very long delay, approx 200msec
        movwf   msb
        goto    d1
delay20                         ;20 msec delay
        movlw   .26
        movwf   msb
        goto    d1
delay16                         ;16 msec delay
        movlw   .21
        movwf   msb
        goto    d1
delay1                          ;approx 750nsec delay
        movlw   .1      
        movwf   msb
d1      movlw   0xff
        movwf   lsb
d2      decfsz  lsb,F
        goto    d2
        decfsz  msb,F
        goto    d1
        return
;____________________________________________________________________________

        
        org     0x200


;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Table for Boot Message                                             -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Table                           ;boot message "PICMETER Booted!"
        addwf   PCL             ;add W to PCL
        retlw   0
        retlw   '!'
        retlw   'd'
        retlw   'e'
        retlw   't'
        retlw   'o'
        retlw   'o'
        retlw   'B'
        retlw   ' '
        retlw   'R'
        retlw   'E'
        retlw   'T'
        retlw   'E'
        retlw   'M'
        retlw   'C'
        retlw   'I'
        retlw   'P'
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     24-bit Addition                                                    -*
;*-                                                                        -*
;*-     Uses ACCa and ACCb                                                 -*
;*-                                                                        -*
;*-     ACCa + ACCb -> ACCb                                                -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Add24
        movf    ACCaLO,W
        addwf   ACCbLO          ;add low bytes
        btfsc   STATUS,C        ;add in carry if necessary
        goto    A2
A1      movf    ACCaMID,W
        addwf   ACCbMID         ;add mid bytes
        btfsc   STATUS,C        ;add in carry if necessary
        incf    ACCbHI
        movf    ACCaHI,W
        addwf   ACCbHI          ;add high bytes
        retlw   0
A2      incf    ACCbMID
        btfsc   STATUS,Z
        incf    ACCbHI
        goto    A1
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*       
;*-     Subtraction ( 24 - 24 -> 24 )                                      -*
;*-                                                                        -*
;*-     Uses ACCa, ACCb, ACCd                                              -*
;*-                                                                        -*
;*-     ACCa -> ACCd,                                                      -*
;*-     2's complement ACCa,                                               -*
;*-     call Add24 ( ACCa + ACCb -> ACCb ),                                -*
;*-     ACCd -> ACCa                                                       -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Sub24
        movf    ACCaHI,W                ;Transfer ACCa to ACCd
        movwf   ACCdHI
        movf    ACCaMID,W
        movwf   ACCdMID
        movf    ACCaLO,W
        movwf   ACCdLO
        call    compA                   ;2's complement ACCa
        call    Add24                   ;Add ACCa to ACCb
        movf    ACCdHI,W                ;Transfer ACCd to ACCa
        movwf   ACCaHI
        movf    ACCdMID,W
        movwf   ACCaMID
        movf    ACCdLO,W
        movwf   ACCaLO
        retlw   0
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Multiply ( 24 X 24 -> 56 )                                         -*
;*-                                                                        -*
;*-     Uses ACCa, ACCb, ACCc, ACCd                                        -*
;*-                                                                        -*
;*-     ACCa * ACCb -> ACCb,ACCc  56-bit output                            -*
;*-     with ACCb (ACCbHI,ACCbMID,ACCbLO) with 24 msb's and                -*
;*-     ACCc (ACCcHI,ACCcMID,ACCcLO) with 24 lsb's                         -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Mpy24
        call    Msetup
mloop   rrf     ACCdHI          ;rotate d right
        rrf     ACCdMID
        rrf     ACCdLO
        btfsc   STATUS,C        ;need to add?
        call    Add24
        rrf     ACCbHI
        rrf     ACCbMID
        rrf     ACCbLO
        rrf     ACCcHI
        rrf     ACCcMID
        rrf     ACCcLO
        decfsz  temp            ;loop until all bits checked
        goto    mloop
        retlw   0

Msetup
        movlw   0x18            ;for 24 bit shifts
        movwf   temp
        movf    ACCbHI,W        ;move ACCb to ACCd
        movwf   ACCdHI
        movf    ACCbMID,W
        movwf   ACCdMID
        movf    ACCbLO,W
        movwf   ACCdLO
        clrf    ACCbHI
        clrf    ACCbMID
        clrf    ACCbLO
        retlw   0
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     Division ( 56 / 24 -> 24 )                                         -*
;*-                                                                        -*
;*-     Uses ACCa, ACCb, ACCc, ACCd                                        -*
;*-                                                                        -*
;*-     56-bit dividend in ACCb,ACCc ( ACCb has msb's and ACCc has lsb's)  -*
;*-     24-bit divisor in ACCa                                             -*
;*-     quotient is stored in ACCc                                         -*
;*-     remainder is stored in ACCb                                        -*
;*--------------------------------------------------------------------------*
;****************************************************************************
Div24
        call    Dsetup

dloop   bcf     STATUS,C
        rlf     ACCcLO          ;Rotate dividend left 1 bit position
        rlf     ACCcMID
        rlf     ACCcHI
        rlf     ACCbLO
        rlf     ACCbMID
        rlf     ACCbHI

        btfsc   STATUS,C        ;invert carry and exclusive or with the
        goto    clear           ;msb of the divisor then move this bit
        btfss   ACCaHI,msb_bit  ;into the lsb of the dividend
        incf    ACCcLO
        goto    cont
clear   btfsc   ACCaHI,msb_bit
        incf    ACCcLO

cont    btfsc   ACCcLO,lsb_bit  ;check the lsb of the dividend
        goto    minus
        call    Add24           ;if = 0, then add divisor to upper 24 bits
        goto    check           ;of dividend
minus   call    Sub24           ;if = 1, then subtract divisor from upper
                                ;24 bits of dividend

check   decfsz  temp,f          ;do 24 times
        goto    dloop

        bcf     STATUS,C
        rlf     ACCcLO          ;shift lower 24 bits of dividend 1 bit 
        rlf     ACCcMID         ;position left
        rlf     ACCcHI
        btfsc   ACCbHI,msb_bit  ;exlusive or the inverse of the msb of the
        goto    w1              ;dividend with the msb of the divisor
        btfss   ACCaHI,msb_bit  ;store in the lsb of the dividend
        incf    ACCcLO
        goto    wzd
w1      btfsc   ACCaHI,msb_bit
        incf    ACCcLO
wzd     btfss   ACCbHI,msb_bit  ;if the msb of the remainder is set and
        goto    wend
        btfsc   ACCaHI,msb_bit  ;the msb of the divisor is not
        goto    wend
        call    Add24           ;add the divisor to the remainder to correct
                                ;for zero partial remainder

wend    retlw   0               ;quotient in 24 lsb's of dividend
                                ;remainder in 24 msb's of dividend

Dsetup        
        movlw   0x18            ;loop 24 times
        movwf   temp
        
        retlw   0
;____________________________________________________________________________

;****************************************************************************
;*--------------------------------------------------------------------------*
;*-     2's Complement                                                     -*
;*-                                                                        -*
;*-     Uses ACCa                                                          -*
;*-                                                                        -*
;*-     Performs 2's complement conversion on ACCa                         -*
;*--------------------------------------------------------------------------*
;****************************************************************************
compA    
        comf    ACCaLO          ;invert all bits in accumulator a
        comf    ACCaMID
        comf    ACCaHI
        incf    ACCaLO          ;add one to accumulator a
        btfsc   STATUS,Z
        incf    ACCaMID
        btfsc   STATUS,Z
        incf    ACCaHI
        retlw   0
;____________________________________________________________________________

        END