ADVERTISEMENT

F628_2x20.zip

Miernik LC - konstrukcja na PIC16F84

Załączam ulepszoną wersję programu (poprawiona jest precyzja obliczeń) dla PIC16F628A oraz LCD 2x20. W EEPROMie pod adresem 0x60 znajduje się współczynnik korygujący wskazania na zakresie L przy kalibracji przeprowadzonej na C. Odejmowana jest szeregowa indukcyjność montażowa w zakresie ok. 0..0.5uH. Aktualnie wpisany jest współczynnik 0x27, który u mnie odpowiada korekcji -0.39uH (39 dziesiętnie, to 27 szesnastkowo). Każdy może go sobie dobrać, dopasowując do swojej indywidualnej konstrukcji.


Download file - link to post
  • F628_2x20.zip
    • opis.txt
    • LC_meter 005_LQ.jpg
    • FP.TXT
    • lc007.asm
    • LC_F628_20x2_XLQ.gif
    • lc007.HEX


F628_2x20.zip > opis.txt

http://ironbark.bendigo.latrobe.edu.au/~rice/lc/index.html

Ulepszy³em czêœæ pomiarow¹ tego miernika. Doda³em uk³ad automatycznie prze³¹czaj¹cy funkcjê " L/C " . To doœæ wygodne rozwi¹zanie w wersji kieszonkowej. Wystarczy pod³¹czyæ kondensator lub indukcyjnoœæ, a przyrz¹d sam " rozpozna " element i poka¿e jego wartoœæ. Wykonawcz¹ rolê automatycznego prze³¹cznika pe³ni miniaturowy przekaŸnik. Kondensator C5 powinien byæ najlepiej tantalowy.

Jeszcze kilka uwag na temat dok³adnoœci/stabilnoœci pomiarów przy u¿yciu tego przyrz¹du.
Oczywiœcie C2cal powinien byæ najlepiej mikowy. Znalaz³em na dnie swojej szuflady taki kondensator wyprodukowany w 1968 roku 1000pF/2% 500V. Realnie mia³ ok. 982pF, wiêc równolegle do³o¿y³em 18pF. Przy wiêkszej pojemnoœci ni¿ 1000pF warto odpowiednio zmodyfikowaæ sta³¹ w pliku Ÿród³owym(korzysta³em akurat ze tego Ÿród³a: http://ironbark.bendigo.latrobe.edu.au/~rice/lc/lc007.txt).

Dosæ wa¿ne dla komfortu u¿ywania miernika s¹ elementy obwodu rezonansowego L1, C4. Je¿eli nie chcemy zbyt czêsto wykonywaæ kalibracji/zerowania przyrz¹du, warto zadbaæ o stabilnoœæ ich parametrów. Nieistotny jest precyzyjny dobór ich wartoœci, wa¿na za to jest ich stabilnoœæ temperaturowa. Cewka L1 powinna mieæ te¿ mo¿liwie du¿¹ dobroæ Q. Najlepiej nawin¹æ j¹ w miniaturowym ferrytowym rdzeniu kubkowym o niskim AL rzêdu 250...400 ze szczelin¹. Zapewni to stosunkowo nisk¹ wartoœæ wspó³czynnika stabilnoœci cieplnej rdzenia rzêdu +100 ppm/°C oraz w miarê wysok¹ dobroæ Q. Kto ma licê niech j¹ wykorzysta!
Je¿eli jako C4 zastosujemy kondensator styrofleksowy, który typowo ma ujemny wspó³czynnik temperaturowy ok. -110ppm/°C, to otrzymamy obwód LC nieŸle skompensowany termicznie. Zero/offset nie powinno zbytnio p³ywaæ, co bynajmniej nie oznacza, ¿e wskazania bêd¹ super-dok³adne. Przed bardzo dok³adnymi pomiarami nale¿y przeprowadziæ kalibracjê, która kompensuje równie¿ p³yniêcie " skali " mimo, ¿e na wyœwietlaczu ³adnie b³yska zero.

Niestety miernik dokonuje pomiarów przy zmieniaj¹cej siê czêstotliwoœci rzêdu nastu do 550..600kHz, wiêc trudno bezpoœrednio porównywaæ wyniki jego pomiarów z profesjonalnymi przyrz¹dami RCL mierz¹cymi najczêœciej przy sta³ych czêstotliwoœciach 100Hz, 1kHz, 10kHz. Jednak jak na prost¹, amatorsk¹ konstrukcjê jego dok³adnoœæ jest zupe³nie wystarczaj¹ca. Kto ma wiêksze ambicje mo¿e zmontowaæ sobie np. tak¹ mini- " koby³kê " typu RLC-meter:
http://www.youritronics.com/dspic30f4012-diy-lcr-meter/

Za³¹czam zmodyfikowan¹ wersjê programu dla PIC16F628A oraz LCD 2x20.
W EEPROMie pod adresem 0x60 znajduje siê wspó³czynnik koryguj¹cy wskazania na zakresie L przy kalibracji przeprowadzonej na C. Odejmowana jest szeregowa indukcyjnoœæ monta¿owa w zakresie ok. 0..0.5uH. Aktualnie wpisany jest wspó³czynnik 0x27, który u mnie odpowiada korekcji -0.39uH.
Ka¿dy mo¿e go sobie dowolnie dobraæ, dopasowuj¹c do swojej indywidualnej konstrukcji.
Oczywiœcie mo¿na wpisaæ 0x00 i kalibrowaæ na zakresie L przy zwartym gnieŸdzie pomiarowym.


F628_2x20.zip > FP.TXT

; RCS Header $Id: fp24.a16 2.7 1996/10/07 13:50:29 F.J.Testa Exp $



; $Revision: 2.7 $



; PIC16 24 BIT FLOATING POINT LIBRARY

;

; Unary operations: both input and output are in AEXP,AARG

;

; Binary operations: input in AEXP,AARG and BEXP,BARG with output in AEXP,AARG

;

; All routines return WREG = 0x00 for successful completion, and WREG = 0xFF

; for an error condition specified in FPFLAGS.

;

;

; Routine Function

;

;

; NRM2424 24 bit normalization of unnormalized 24 bit floating point numbers

;

;

; FLO2424 24 bit integer to 24 bit floating point conversion

;

;

; NRM3224 32 bit normalization of unnormalized 24 bit floating point numbers

;

;

; INT2424 24 bit floating point to 24 bit integer conversion

;

;

; FPA24 24 bit floating point add

;

;

; FPS24 24 bit floating point subtract

;

;

; FPM24 24 bit floating point multiply

;

;

; FPD24 24 bit floating point divide

;



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

;

; 24 bit floating point representation

;

; EXPONENT 8 bit biased exponent

; It is important to note that the use of biased exponents produces

; a unique representation of a floating point 0, given by

; EXP = HIGHBYTE = LOWBYTE = 0x00, with 0 being the only

; number with EXP = 0.

;

; HIGHBYTE 8 bit most significant byte of fraction in sign-magnitude representation,

; with SIGN = MSB, implicit MSB = 1 and radix point to the right of MSB

;

; LOWBYTE 8 bit least significant byte of sign-magnitude fraction

;

; EXPONENT HIGHBYTE LOWBYTE

;

; xxxxxxxx S.xxxxxxx xxxxxxxx

;

; |

; RADIX

; POINT

;



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



; Normalization routine



; Input: 24 bit unnormalized floating point number in AEXP, AARGB0, AARGB1,

; with sign in SIGN,MSB and other bits zero.



; Use: CALL NRM2424 or CALL NRM24



; Output: 24 bit normalized floating point number in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- NORMALIZE( AARG )



;----------------------------------------------------------------------------------------------



NRM2424

NRM24

CLRF TEMP ; clear exponent decrement

MOVF AARGB0,W ; test if highbyte=0

BTFSS _Z

GOTO NORM2424

MOVF AARGB1,W ; if so, shift 8 bits by move

MOVWF AARGB0

BTFSC _Z ; if highbyte=0, result=0

GOTO RES024

CLRF AARGB1

BSF TEMP,3



NORM2424 MOVF TEMP,W

SUBWF EXP,F

BTFSS _Z

BTFSS _C

GOTO SETFUN24



BCF _C ; clear carry bit



NORM2424A BTFSC AARGB0,MSB ; if MSB=1, normalization done

GOTO FIXSIGN24

RLF AARGB1,F ; otherwise, shift left and

RLF AARGB0,F ; decrement EXP

DECFSZ EXP,F

GOTO NORM2424A



GOTO SETFUN24 ; underflow if EXP=0



FIXSIGN24 BTFSS SIGN,MSB

BCF AARGB0,MSB ; clear explicit MSB if positive

RETLW 0



RES024 CLRF AARGB0 ; result equals zero

CLRF AARGB1

CLRF AARGB2 ; clear extended byte

CLRF EXP

RETLW 0





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



; Integer to float conversion



; Input: 24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2



; Use: CALL FLO2424



; Output: 24 bit floating point number in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- FLOAT( AARG )



;----------------------------------------------------------------------------------------------



FLO2424 MOVLW D'23'+EXPBIAS ; initialize exponent and add bias

MOVWF EXP

CLRF SIGN

BTFSS AARGB0,MSB ; test sign

GOTO NRM3224

COMF AARGB2,F ; if & lt; 0, negate and set MSB in SIGN

COMF AARGB1,F

COMF AARGB0,F

INCF AARGB2,F

BTFSC _Z

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F

BSF SIGN,MSB



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



; Normalization routine



; Input: 32 bit unnormalized floating point number in AEXP, AARGB0, AARGB1,

; AARGB2, with sign in SIGN,MSB



; Use: CALL NRM3224



; Output: 24 bit normalized floating point number in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- NORMALIZE( AARG )



;----------------------------------------------------------------------------------------------



NRM3224 CLRF TEMP ; clear exponent decrement

MOVF AARGB0,W ; test if highbyte=0

BTFSS _Z

GOTO NORM3224

MOVF AARGB1,W ; if so, shift 8 bits by move

MOVWF AARGB0

MOVF AARGB2,W

MOVWF AARGB1

CLRF AARGB2

BSF TEMP,3 ; increase decrement by 8



MOVF AARGB0,W ; test if highbyte=0

BTFSS _Z

GOTO NORM3224

MOVF AARGB1,W ; if so, shift 8 bits by move

MOVWF AARGB0

CLRF AARGB1

BCF TEMP,3 ; increase decrement by 8

BSF TEMP,4



MOVF AARGB0,W ; if highbyte=0, result=0

BTFSC _Z

GOTO RES024



NORM3224 MOVF TEMP,W

SUBWF EXP,F

BTFSS _Z

BTFSS _C

GOTO SETFUN24



BCF _C ; clear carry bit



NORM3224A BTFSC AARGB0,MSB ; if MSB=1, normalization done

GOTO NRMRND3224

RLF AARGB2,F ; otherwise, shift left and

RLF AARGB1,F ; decrement EXP

RLF AARGB0,F

DECFSZ EXP,F

GOTO NORM3224A

GOTO SETFUN24 ; underflow if EXP=0



NRMRND3224 BTFSC FPFLAGS,RND

BTFSS AARGB1,LSB

GOTO FIXSIGN24

BTFSS AARGB2,MSB ; round if next bit is set

GOTO FIXSIGN24

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F



BTFSS _Z ; has rounding caused carryout?

GOTO FIXSIGN24

RRF AARGB0,F ; if so, right shift

RRF AARGB1,F

INCF EXP,F

BTFSC _Z ; check for overflow

GOTO SETFOV24

GOTO FIXSIGN24



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



; Float to integer conversion



; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1



; Use: CALL INT2424



; Output: 24 bit 2's complement integer right justified in AARGB0, AARGB1, AARGB2



; Result: AARG & lt; -- INT( AARG )



;----------------------------------------------------------------------------------------------



INT2424

CLRF AARGB2

MOVF EXP,W ; test for zero argument

BTFSC _Z

RETLW 0x00



MOVF AARGB0,W ; save sign in SIGN

MOVWF SIGN

BSF AARGB0,MSB ; make MSB explicit



MOVLW EXPBIAS+D'23' ; remove bias from EXP

SUBWF EXP,F

BTFSS EXP,MSB

GOTO SETIOV24

COMF EXP,F

INCF EXP,F



MOVLW 8 ; do byte shift if EXP & gt; = 8

SUBWF EXP,W

BTFSS _C

GOTO TSHIFT2424

MOVWF EXP

RLF AARGB2,F ; rotate next bit for rounding

MOVF AARGB1,W

MOVWF AARGB2

MOVF AARGB0,W

MOVWF AARGB1

CLRF AARGB0



MOVLW 8 ; do another byte shift if EXP & gt; = 8

SUBWF EXP,W

BTFSS _C

GOTO TSHIFT2424

MOVWF EXP

RLF AARGB2,F ; rotate next bit for rounding

MOVF AARGB1,W

MOVWF AARGB2

CLRF AARGB1



MOVLW 8 ; do another byte shift if EXP & gt; = 8

SUBWF EXP,W

BTFSS _C

GOTO TSHIFT2424

MOVWF EXP

RLF AARGB2,F ; rotate next bit for rounding

CLRF AARGB2

MOVF EXP,W

BTFSS _Z

BCF _C

GOTO SHIFT2424OK



TSHIFT2424 MOVF EXP,W ; shift completed if EXP = 0

BTFSC _Z

GOTO SHIFT2424OK



SHIFT2424 BCF _C

RRF AARGB0,F ; right shift by EXP

RRF AARGB1,F

RRF AARGB2,F

DECFSZ EXP,F

GOTO SHIFT2424



SHIFT2424OK BTFSC FPFLAGS,RND

BTFSS AARGB2,LSB

GOTO INT2424OK

BTFSS _C

GOTO INT2424OK

INCF AARGB2,F

BTFSC _Z

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F

BTFSC AARGB0,MSB ; test for overflow

GOTO SETIOV24



INT2424OK BTFSS SIGN,MSB ; if sign bit set, negate

RETLW 0

COMF AARGB0,F

COMF AARGB1,F

COMF AARGB2,F

INCF AARGB2,F

BTFSC _Z

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F

RETLW 0



IRES024 CLRF AARGB0 ; integer result equals zero

CLRF AARGB1

CLRF AARGB2

RETLW 0



SETIOV24 BSF FPFLAGS,IOV ; set integer overflow flag

BTFSS FPFLAGS,SAT ; test for saturation

RETLW 0xFF ; return error code in WREG



CLRF AARGB0 ; saturate to largest two's

BTFSS SIGN,MSB ; complement 24 bit integer

MOVLW 0xFF

MOVWF AARGB0 ; SIGN = 0, 0x 7F FF FF

MOVWF AARGB1 ; SIGN = 1, 0x 80 00 00

MOVWF AARGB2

RLF SIGN,F

RRF AARGB0,F

RETLW 0xFF ; return error code in WREG







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



; Floating Point Multiply



; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1

; 24 bit floating point number in BEXP, BARGB0, BARGB1



; Use: CALL FPM24



; Output: 24 bit floating point product in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- AARG * BARG



;----------------------------------------------------------------------------------------------



FPM24 MOVF AEXP,W ; test for zero arguments

BTFSS _Z

MOVF BEXP,W

BTFSC _Z

GOTO RES024



M24BNE0 MOVF AARGB0,W

XORWF BARGB0,W

MOVWF SIGN ; save sign in SIGN



MOVF BEXP,W

ADDWF EXP,F

MOVLW EXPBIAS-1

BTFSS _C

GOTO MTUN24



SUBWF EXP,F

BTFSC _C

GOTO SETFOV24 ; set multiply overflow flag

GOTO MOK24



MTUN24 SUBWF EXP,F

BTFSS _C

GOTO SETFUN24



MOK24

MOVF AARGB0,W

MOVWF AARGB2 ; move result to AARG

MOVF AARGB1,W

MOVWF AARGB3

BSF AARGB2,MSB ; make argument MSB's explicit

BSF BARGB0,MSB

BCF _C

CLRF AARGB0 ; clear initial partial product

CLRF AARGB1

MOVLW D'16'

MOVWF TEMP ; initialize counter



MLOOP24 BTFSS AARGB3,LSB ; test next bit

GOTO MNOADD24



MADD24 MOVF BARGB1,W

ADDWF AARGB1,F

MOVF BARGB0,W

BTFSC _C

INCFSZ BARGB0,W

ADDWF AARGB0,F



MNOADD24 RRF AARGB0,F

RRF AARGB1,F

RRF AARGB2,F

RRF AARGB3,F

BCF _C

DECFSZ TEMP,F

GOTO MLOOP24



BTFSC AARGB0,MSB ; check for postnormalization

GOTO MROUND24

RLF AARGB2,F

RLF AARGB1,F

RLF AARGB0,F

DECF EXP,F



MROUND24 BTFSC FPFLAGS,RND

BTFSS AARGB1,LSB

GOTO MUL24OK

BTFSS AARGB2,MSB ; round if next bit is set

GOTO MUL24OK

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F



BTFSS _Z ; has rounding caused carryout?

GOTO MUL24OK

RRF AARGB0,F ; if so, right shift

RRF AARGB1,F

INCF EXP,F

BTFSC _Z ; check for overflow

GOTO SETFOV24



MUL24OK BTFSS SIGN,MSB

BCF AARGB0,MSB ; clear explicit MSB if positive



RETLW 0



SETFOV24 BSF FPFLAGS,FOV ; set floating point underflag

BTFSS FPFLAGS,SAT ; test for saturation

RETLW 0xFF ; return error code in WREG



MOVLW 0xFF

MOVWF AEXP ; saturate to largest floating

MOVWF AARGB0 ; point number = 0x FF 7F FF

MOVWF AARGB1 ; modulo the appropriate sign bit

RLF SIGN,F

RRF AARGB0,F

RETLW 0xFF ; return error code in WREG



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



; Floating Point Divide



; Input: 24 bit floating point dividend in AEXP, AARGB0, AARGB1

; 24 bit floating point divisor in BEXP, BARGB0, BARGB1



; Use: CALL FPD24



; Output: 24 bit floating point quotient in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- AARG / BARG



;----------------------------------------------------------------------------------------------



FPD24 MOVF BEXP,W ; test for divide by zero

BTFSC _Z

GOTO SETFDZ24



MOVF AEXP,W

BTFSC _Z

GOTO RES024



D24BNE0 MOVF AARGB0,W

XORWF BARGB0,W

MOVWF SIGN ; save sign in SIGN

BSF AARGB0,MSB ; make argument MSB's explicit

BSF BARGB0,MSB



TALIGN24 CLRF TEMP ; clear align increment

MOVF AARGB0,W

MOVWF AARGB2 ; test for alignment

MOVF AARGB1,W

MOVWF AARGB3



MOVF BARGB1,W

SUBWF AARGB3, f

MOVF BARGB0,W

BTFSS _C

INCFSZ BARGB0,W

SUBWF AARGB2, f



CLRF AARGB2

CLRF AARGB3



BTFSS _C

GOTO DALIGN24OK



BCF _C ; align if necessary

RRF AARGB0,F

RRF AARGB1,F

RRF AARGB2,F

MOVLW 0x01

MOVWF TEMP ; save align increment



DALIGN24OK MOVF BEXP,W ; compare AEXP and BEXP

SUBWF EXP,F

BTFSS _C

GOTO ALTB24



AGEB24 MOVLW EXPBIAS-1

ADDWF TEMP,W

ADDWF EXP,F

BTFSC _C

GOTO SETFOV24

GOTO DARGOK24 ; set overflow flag



ALTB24 MOVLW EXPBIAS-1

ADDWF TEMP,W

ADDWF EXP,F

BTFSS _C

GOTO SETFUN24 ; set underflow flag



DARGOK24 MOVLW D'16' ; initialize counter

MOVWF TEMPB1



DLOOP24 RLF AARGB3,F ; left shift

RLF AARGB2,F

RLF AARGB1,F

RLF AARGB0,F

RLF TEMP,F



MOVF BARGB1,W ; subtract

SUBWF AARGB1,F

MOVF BARGB0,W

BTFSS _C

INCFSZ BARGB0,W

SUBWF AARGB0,F



RLF BARGB0,W

IORWF TEMP,F



BTFSS TEMP,LSB ; test for restore

GOTO DREST24



BSF AARGB3,LSB

GOTO DOK24



DREST24 MOVF BARGB1,W ; restore if necessary

ADDWF AARGB1,F

MOVF BARGB0,W

BTFSC _C

INCF BARGB0,W

ADDWF AARGB0,F

BCF AARGB3,LSB



DOK24 DECFSZ TEMPB1,F

GOTO DLOOP24



DROUND24 BTFSC FPFLAGS,RND

BTFSS AARGB3,LSB

GOTO DIV24OK

BCF _C

RLF AARGB1,F ; compute next significant bit

RLF AARGB0,F ; for rounding

RLF TEMP,F



MOVF BARGB1,W ; subtract

SUBWF AARGB1,F

MOVF BARGB0,W

BTFSS _C

INCFSZ BARGB0,W

SUBWF AARGB0,F



RLF BARGB0,W

IORWF TEMP,W

ANDLW 0x01



ADDWF AARGB3,F

BTFSC _C

INCF AARGB2,F



BTFSS _Z ; test if rounding caused carryout

GOTO DIV24OK

RRF AARGB2,F

RRF AARGB3,F

INCF EXP,F

BTFSC _Z ; test for overflow

GOTO SETFOV24



DIV24OK BTFSS SIGN,MSB

BCF AARGB2,MSB ; clear explicit MSB if positive



MOVF AARGB2,W

MOVWF AARGB0 ; move result to AARG

MOVF AARGB3,W

MOVWF AARGB1



RETLW 0



SETFUN24 BSF FPFLAGS,FUN ; set floating point underflag

BTFSS FPFLAGS,SAT ; test for saturation

RETLW 0xFF ; return error code in WREG



MOVLW 0x01 ; saturate to smallest floating

MOVWF AEXP ; point number = 0x 01 00 00

CLRF AARGB0 ; modulo the appropriate sign bit

CLRF AARGB1

RLF SIGN,F

RRF AARGB0,F

RETLW 0xFF ; return error code in WREG



SETFDZ24 BSF FPFLAGS,FDZ ; set divide by zero flag

RETLW 0xFF



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



; Floating Point Subtract



; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1

; 24 bit floating point number in BEXP, BARGB0, BARGB1



; Use: CALL FPS24



; Output: 24 bit floating point sum in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- AARG - BARG



;----------------------------------------------------------------------------------------------



FPS24 MOVLW 0x80

XORWF BARGB0,F



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



; Floating Point Add



; Input: 24 bit floating point number in AEXP, AARGB0, AARGB1

; 24 bit floating point number in BEXP, BARGB0, BARGB1



; Use: CALL FPA24



; Output: 24 bit floating point sum in AEXP, AARGB0, AARGB1



; Result: AARG & lt; -- AARG - BARG



;----------------------------------------------------------------------------------------------



FPA24 MOVF AARGB0,W ; exclusive or of signs in TEMP

XORWF BARGB0,W

MOVWF TEMP



CLRF AARGB2 ; clear extended byte

CLRF BARGB2



MOVF AEXP,W ; use AARG if AEXP & gt; = BEXP

SUBWF BEXP,W

BTFSS _C

GOTO USEA24



MOVF BEXP,W ; use BARG if AEXP & lt; BEXP

MOVWF AARGB4 ; therefore, swap AARG and BARG

MOVF AEXP,W

MOVWF BEXP

MOVF AARGB4,W

MOVWF AEXP



MOVF BARGB0,W

MOVWF AARGB4

MOVF AARGB0,W

MOVWF BARGB0

MOVF AARGB4,W

MOVWF AARGB0



MOVF BARGB1,W

MOVWF AARGB4

MOVF AARGB1,W

MOVWF BARGB1

MOVF AARGB4,W

MOVWF AARGB1



USEA24 MOVF BEXP,W ; return AARG if BARG = 0

BTFSC _Z

RETLW 0x00



MOVF AARGB0,W

MOVWF SIGN ; save sign in SIGN

BSF AARGB0,MSB ; make MSB's explicit

BSF BARGB0,MSB



MOVF BEXP,W ; compute shift count in BEXP

SUBWF AEXP,W

MOVWF BEXP

BTFSC _Z

GOTO ALIGNED24



MOVLW 8

SUBWF BEXP,W

BTFSS _C ; if BEXP & gt; = 8, do byte shift

GOTO ALIGNB24

MOVWF BEXP

MOVF BARGB1,W ; keep for postnormalization

MOVWF BARGB2

MOVF BARGB0,W

MOVWF BARGB1

CLRF BARGB0



MOVLW 8

SUBWF BEXP,W

BTFSS _C ; if BEXP & gt; = 8, BARG = 0 relative to AARG

GOTO ALIGNB24

MOVF SIGN,W

MOVWF AARGB0

RETLW 0x00



ALIGNB24 MOVF BEXP,W ; already aligned if BEXP = 0

BTFSC _Z

GOTO ALIGNED24



ALOOPB24 BCF _C ; right shift by BEXP

RRF BARGB0,F

RRF BARGB1,F

RRF BARGB2,F

DECFSZ BEXP,F

GOTO ALOOPB24



ALIGNED24 BTFSS TEMP,MSB ; negate if signs opposite

GOTO AOK24

COMF BARGB2,F

COMF BARGB1,F

COMF BARGB0,F

INCF BARGB2,F

BTFSC _Z

INCF BARGB1,F

BTFSC _Z

INCF BARGB0,F



AOK24

MOVF BARGB2,W

ADDWF AARGB2,F

MOVF BARGB1,W

BTFSC _C

INCFSZ BARGB1,W

ADDWF AARGB1,F

MOVF BARGB0,W

BTFSC _C

INCFSZ BARGB0,W

ADDWF AARGB0,F



BTFSC TEMP,MSB

GOTO ACOMP24

BTFSS _C

GOTO NRMRND3224



RRF AARGB0,F ; shift right and increment EXP

RRF AARGB1,F

RRF AARGB2,F

INCFSZ AEXP,F

GOTO NRMRND3224

GOTO SETFOV24



ACOMP24 BTFSC _C

GOTO NRM3224 ; normalize and fix sign



COMF AARGB2,F

COMF AARGB1,F ; negate, toggle sign bit and

COMF AARGB0,F ; then normalize

INCF AARGB2,F

BTFSC _Z

INCF AARGB1,F

BTFSC _Z

INCF AARGB0,F



MOVLW 0x80

XORWF SIGN,F

GOTO NRM24



;******************************* end of FP24.A16 ************************************