Mike - K8LH
Well-Known Member
Just ported DS18B20 (assembly language) math code from 16F' to 18F' (taking advantage of the 18F' hardware multiplier) a couple months ago and thought I'd post it for anyone who might be interested since there is some discussion about the DS18B20 at the moment.
Mike
Please note that the BINL+0..BINL+2 input variables have been equated to Prod0..Prod2 to eliminate several movff instructions.
Caveat! This code simulates fine but I recall there may be a 'bug' in the daw (decimal adjust) instruction.
I use these defines in some 18F' applications for the missing 18F' "skip" instructions. I hope my use of them in one or two places in the above code doesn't mess anyone up.
Mike
Code:
;******************************************************************
;
; CtoC - binary °C*16 to decimal °C*10000 (4 decimal places)
;
; °C*10000 = 625 * T18B20H:L
;
; Bcd3:0 packed bcd output -00550000 to +01250000 (°C*10000)
;
;
; TempH:L Neg Output Display
; ============================================
; 125.0000°C h'07D0' 0 01250000 125.0000°C
; 100.0000°C h'0640' 0 01000000 100.0000°C
; 77.0000°C h'04D0' 0 00770000 77.0000°C
; 25.0000°C h'0190' 0 00250000 25.0000°C
; 22.0000°C h'0160' 0 00220000 22.0000°C
; 0.5000°C h'0008' 0 00005000 0.5000°C
; 0.0625°C h'0001' 0 00000625 0.0625°C
; 0.0000°C h'0000' 0 00000000 0.0000°C
; - 0.0625°C h'FFFF' 1 00000625 - 0.0625°C
; - 0.1250°C h'FFFE' 1 00001250 - 0.1250°C
; - 5.0000°C h'FFB0' 1 00050000 - 5.0000°C
; -10.0000°C h'FF60' 1 00100000 -10.0000°C
; -17.0625°C h'FEEF' 1 00170625 -17.0625°C
; -17.6875°C h'FEE5' 1 00176875 -17.6875°C
; -17.7500°C h'FEE4' 1 00177500 -17.7500°C
; -17.8125°C h'FEE3' 1 00178125 -17.8125°C
; -25.0000°C h'FE70' 1 00250000 -25.0000°C
; -55.0000°C h'FC90' 1 00550000 -55.0000°C
CtoC
movlw high(0xfee5) ; <- movf DS18B20H,W
movwf AH ;
movlw low(0xfee5) ; <- movf DS18B20L,W
movwf AL ;
movlw high(625) ;
movwf BH ;
movlw low(625) ;
movwf BL ;
rcall Mult16x16 ; signed 16x16 multiply
bcf Flags,neg ;
btfss Prod3,7 ; negative?
bra CtoC.1 ; no, branch, else
bsf Flags,neg ;
comf Prod3,F ;
comf Prod2,F ;
comf Prod1,F ;
negf Prod0 ;
bnc CtoC.1 ;
incf Prod1,F ;
skpnz ;
incf Prod2,F ;
skpnz ;
incf Prod3,F ; 65 cycles to this point
CtoC.1
bra Bin2Bcd ;
Code:
;******************************************************************
;
; CtoF - binary °C*16 to decimal °F*10000 (4 decimal places)
;
; °F*10000 = 1125 * DS18B20H:L + 320000
;
; Bcd3:0 packed bcd output -00670000 to +02570000 (°F*10000)
;
;
; TempH:L Neg Output Display
; ============================================
; 125.0000°C h'07D0' 0 02570000 257.0000°F
; 100.0000°C h'0640' 0 02120000 212.0000°F
; 77.0000°C h'04D0' 0 01706000 170.6000°F
; 25.0000°C h'0190' 0 00770000 77.0000°F
; 22.0000°C h'0160' 0 00716000 71.6000°F
; 0.5000°C h'0008' 0 00329000 32.9000°F
; 0.0625°C h'0001' 0 00321125 32.1125°F
; 0.0000°C h'0000' 0 00320000 32.0000°F
; - 0.0625°C h'FFFF' 0 00318875 31.8875°F
; - 0.1250°C h'FFFE' 0 00317750 31.7750°F
; - 5.0000°C h'FFB0' 0 00230000 23.0000°F
; -10.0000°C h'FF60' 0 00140000 14.0000°F
; -17.0625°C h'FEEF' 0 00012875 1.2875°F
; -17.6875°C h'FEE5' 0 00001625 0.1625°F
; -17.7500°C h'FEE4' 0 00000500 0.0500°F
; -17.8125°C h'FEE3' 1 00000625 - 0.0625°F
; -25.0000°C h'FE70' 1 00130000 -13.0000°F
; -55.0000°C h'FC90' 1 00670000 -67.0000°F
CtoF
movlw high(0xfee3) ; <- movf DS18B20H,W
movwf AH ;
movlw low(0xfee3) ; <- movf DS18B20L,W
movwf AL ;
movlw high(1125) ;
movwf BH ;
movlw low(1125) ;
movwf BL ;
rcall Mult16x16 ; signed 16x16 multiply
movlw high(320000) ;
addwf Prod1,F ;
movlw upper(320000) ;
addwfc Prod2,F ;
movlw 0 ;
addwfc Prod3,F ;
bcf Flags,neg ;
btfss Prod3,7 ; negative?
bra CtoF.1 ; no, branch, else
bsf Flags,neg ;
comf Prod3,F ;
comf Prod2,F ;
comf Prod1,F ;
negf Prod0 ;
bnc CtoF.1 ;
incf Prod1,F ;
skpnz ;
incf Prod2,F ;
skpnz ;
incf Prod3,F ; 71 cycles to this point
CtoF.1
bra Bin2Bcd ;
Code:
;******************************************************************
;
; 16 x 16 -> 32 signed multiply (16 bit core)
;
; AL*BL + AH*BH*256*256 + AH*BL*256 + AL*BH*256
;
; 40 words, 43 cycles (including call and return)
;
Mult16x16
movf AL,W ; W = AL |
mulwf BL ; AL * BL
movff PRODL,Prod0 ; -- -- -- LL
movff PRODH,Prod1 ; -- -- MM --
movf AH,W ; W = AH
mulwf BH ; AH * BH * 256 * 256
movff PRODL,Prod2 ; -- HH -- --
movff PRODH,Prod3 ; UU -- -- --
mulwf BL ; AH * BL * 256
movf PRODL,W ;
addwf Prod1,F ; -- -- MM --
movf PRODH,W ;
addwfc Prod2,F ; -- HH -- --
movlw 0 ;
addwfc Prod3,F ; UU -- -- --
movf AL,W ; W = AL
mulwf BH ; AL * BH * 256
movf PRODL,W ;
addwf Prod1,F ; -- -- MM --
movf PRODH,W ;
addwfc Prod2,F ; -- HH -- --
movlw 0 ;
addwfc Prod3,F ; UU -- -- --
SignB
btfss BH,7 ; BH:BL argument negative?
bra SignA ; no, branch, else
movf AL,W ;
subwf Prod2,F ;
movf AH,W ;
subwfb Prod3,F ;
SignA
btfss AH,7 ; AH:AL argument negative?
bra Mulxit ; no, branch, else
movf BL,W ;
subwf Prod2,F ;
movf BH,W ;
subwfb Prod3,F ;
Mulxit
return ;
Caveat! This code simulates fine but I recall there may be a 'bug' in the daw (decimal adjust) instruction.
Code:
;******************************************************************
;
; Bin2Bcd -- 24 bit binary to 8 digit packed BCD (16 bit core)
;
; Number Range: 000000..FFFFFF (0..16,777,215)
;
; 28 words, 537 cycles (including call and return)
;
Bin2Bcd
clrf BCDL+0 ; LSB..MSB
clrf BCDL+1 ;
clrf BCDL+2 ;
clrf BCDL+3 ;
movlw 24 ;
movwf BitCtr ;
ConvertBit
rlcf BINL+0,F ; LSB..MSB
rlcf BINL+1,F ;
rlcf BINL+2,F ;
movf BCDL+0,W ;
addwfc BCDL+0,W ;
daw ;
movwf BCDL+0 ;
movf BCDL+1,W ;
addwfc BCDL+1,W ;
daw ;
movwf BCDL+1 ;
movf BCDL+2,W ;
addwfc BCDL+2,W ;
daw ;
movwf BCDL+2 ;
movf BCDL+3,W ;
addwfc BCDL+3,W ;
daw ;
movwf BCDL+3 ;
decfsz BitCtr,F ;
bra ConvertBit ;
return ;
Code:
#define skpnz btfsc STATUS,Z
#define skpz btfss STATUS,Z
#define skpnc btfsc STATUS,C
#define skpc btfss STATUS,C
Last edited: