Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Temperature Sensor DS18B20 Display Fahrenhiet

Status
Not open for further replies.
As he is working in assembler I thought it best to avoid both multiply and divide. The above uses just shifts and addition.

But using an 8x16 (sign extended) multiply routine might not make the program much more complicated. The algorithm for three decimal digits is pretty simple, and you can always ignore any unwanted digits;

Code:
;
;  BC2DF - binary °C*16 to decimal °F*1000 (3 decimal places)
;
;  °F*1000 = 225 * TempH:TempL / 2 + 32000
;
;  Bcd2:0 packed bcd output -067000 to +257000 (°F*1000)
;
;                  TempH:L Neg Output   Display
;     ==========================================
;     125.0000°C   h'07D0'  0  257000  257.000°F 
;     100.0000°C   h'0640'  0  212000  212.000°F
;      77.0000°C   h'04D0'  0  170600  170.600°F
;      25.0000°C   h'0190'  0  077000   77.000°F
;      22.0000°C   h'0160'  0  071600   71.600°F
;       0.5000°C   h'0008'  0  032900   32.900°F
;       0.0625°C   h'0001'  0  032112   32.112°F
;       0.0000°C   h'0000'  0  032000   32.000°F
;     - 0.0625°C   h'FFFF'  0  031887   31.887°F
;     - 0.1250°C   h'FFFE'  0  031775   31.775°F
;     - 5.0000°C   h'FFB0'  0  023000   23.000°F
;     -10.0000°C   h'FF60'  0  014000   14.000°F
;     -17.0625°C   h'FEEF'  0  001287    1.287°F
;     -17.6875°C   h'FEE5'  0  000162    0.162°F
;     -17.7500°C   h'FEE4'  0  000050    0.050°F
;     -17.8125°C   h'FEE3'  1  000062  - 0.062°F
;     -25.0000°C   h'FE70'  1  013000  -13.000°F
;     -55.0000°C   h'FC90'  1  067000  -67.000°F
;
;
        radix   dec
BC2DF
        movlw   225             ; multiplier = 225                |B0
        call    Mult8x16        ; multiplicand = TempH:TempL      |B0
        rlf     Prod2,W         ; divide by 2 (preserve sign)     |B0
        rrf     Prod2,F         ;                                 |B0
        rrf     Prod1,F         ;                                 |B0
        rrf     Prod0,F         ;                                 |B0
        movlw   High(32000)     ; add 32000 (0x7D00) to product   |B0
        addwf   Prod1,F         ;                                 |B0
        skpnc                   ;                                 |B0
        incf    Prod2,F         ;                                 |B0
        call    AbsFunc         ; make positive, setup NegFlag    |B0
        goto    Bin2bcd         ; output is 6 digit packed BCD    |B0
;
Here's an 8x16 multiply routine that I modified for "sign extended" operation. Please note that the 16 bit multiplicand equates to the 16 bit raw temperature variable and the variable is unchanged after the multiplication.

Code:
;
;  Sign Extended 8 x 16 Multiply 
;
;  Mult * Mul2H:L -> sign extended Prod2:0 (24 bit)
;  Multiplier 'Mult' destroyed, Multiplicand 'Mul2H:L' unchanged
;
;  21 words,  98 to 138 cycles
;
Mult8x16
        movwf   Mult            ; save multiplier                 |B0
        clrf    Prod2           ; product MSB                     |B0
        clrf    Prod1           ;                                 |B0
        clrf    Prod0           ;                                 |B0
        bsf     Prod0,7         ; set counter = 8                 |B0
mloop   rrf     Mult,F          ; multiplier >>= 1                |B0
        bnc     mnext           ;                                 |B0
        movf    Mul2L,W         ; multiplicand lo (equ TempL)     |B0
        addwf   Prod1,F         ;                                 |B0
        movf    Mul2H,W         ; multiplicand hi (equ TempH)     |B0
        skpnc                   ;                                 |B0
        incf    Mul2H,W         ;                                 |B0
        addwf   Prod2,F         ;                                 |B0
mnext   rlf     Prod2,W         ; preserve the sign bit (b23)     |B0
        rrf     Prod2,F         ;                                 |B0
        rrf     Prod1,F         ;                                 |B0
        rrf     Prod0,F         ;                                 |B0
        bnc     mloop           ;                                 |B0
        return                  ;                                 |B0
;
Regards, Mike
 
Last edited:
Hi Jake,

Your bin_to_dec_f routine looks like a nice extension of your original and very novel 8 bit routine from long ago. Unfortunately it's going to be incredibly slow. You might consider using the -10 value in WREG as a divisor of 10 instead of using a divisor of 1 (which I also suggested for your original 8 bit routine).

Code:
;
;  Jake's modified 13+ bit 0000..9999 bin-to-dec algorithm
;
;   input: binh:binl -> 0x0000..0x270F (0..9999)
;  output: thou -> 0..9
;          huns -> 0..9
;          tens -> 0..9
;          ones -> 0..9
;
;  19 words, 4 or 5 variables, 14..8330 cycles  (Mike, K8LH)
;
        radix   dec
bin2dec
        clrf    thou            ;
        movlw   -10             ; wreg = -10
resHuns movwf   huns            ; set huns = -10
resTens movwf   tens            ; set tens = -10
div10z  addwf   binl,F          ; binl = binl - 10, borrow?
        skpc                    ; no, skip, else
        decf    binh,F          ; decrement hi byte
        btfsc   binh,7          ; negative? no, skip, else
        goto    b2dwrap         ; wrap up (borrow/underflow)
        incfsz  tens,F          ; tens overflow? yes, skip, else
        goto    div10z          ; loop
        incfsz  huns,F          ; huns overflow? yes, skip, else
        goto    resTens         ; reset 'tens' & loop
        incf    thou,F          ; bump 'thou'
        goto    resHuns         ; reset 'huns' & 'tens' & loop
b2dwrap subwf   huns,F          ; fix huns
        subwf   tens,F          ; fix tens
        subwf   binl,W          ; fix ones
        movwf   ones            ;
 ;
While this modified version of your routine is much faster, it's still pretty slow compared to some of the alternatives. If that becomes an issue, please let us know.

Good luck on your project.

Regards, Mike
 
Last edited:
I just tried Mike's (Pommie's) algorithm and it's "the cat's meow". This is a clever, simple, and elegant solution in something like 23 words of program memory, before you add your abs() and bin2dec() functions;

Code:
;
;  Pommie's brilliant DS18B20 Celsius to Fahrenheit algorithm
;
;     10F = 18C + 320 = 16C + 2C + 320 = 16C + 16C/8 + 320
;
;     (remember that raw TempH:TempL value is 16C)
;
        radix   dec
c_to_f
        rlf     TempH,W         ; preserve sign bit (b15)
        rrf     TempH,W         ;
        movwf   binh            ;
        rrf     TempL,W         ;
        movwf   binl            ;
        rlf     binh,W          ; preserve sign bit (b15)
        rrf     binh,F          ;
        rrf     binl,F          ;
        rlf     binh,W          ; preserve sign bit (b15)
        rrf     binh,F          ;
        rrf     binl,F          ;
;
;  16C (TempH:TempL) + 2C (binh:binl) -> binh:binl
;
        movf    TempL,W         ;
        addwf   binl,F          ;
        movf    TempH,W         ;
        skpnc                   ;
        incf    TempH,W         ;
        addwf   binh,F          ;
;
;  add 320
;
        movlw   low(320)        ;
        addwf   binl,F          ;
        movlw   high(320)       ;
        skpnc                   ;
        addlw   1               ;
        addwf   binh,F          ;
;
;  get absolute value, set NegFlag
;
        bcf     NegFlag         ;
        btfss   binh,7          ; negative? yes, skip, else
        goto    bin2dec         ; branch
        bsf     NegFlag         ;
        comf    binl,F          ;
        comf    binh,F          ;
        incf    binl,F          ;
        skpnz                   ;
        incf    binh,F          ;
;
;  bin-to-dec function
;
 
Last edited:
Mike, for rounding purposes you need to add 4 before the shift. So it becomes 16C + (16C+4)/8 +320.

I had a look back at my attempt at the whole algorithm and I can't see why it didn't work. Maybe I missed something.

Code:
	movlw	4			;add 4
        addwf   TEMPLO_C, W             ; Copy Celsius Temperature Data into Fahrenheit Registers for conversion
	andlw	b'11111000'		;ensure carry stays clear later
        MOVWF   TEMPLO_F                ; 
        MOVF    TEMPHI_C, W             ; 
	btfsc	STATUS,C
	incf	TEMPHI_C,W		; allow for carry
        MOVWF   TEMPHI_F                ; 
 
	bcf	STATUS,C		;do divide
	rrf	TEMPH_F,f
	rrf	TEMPL_F,f
	rrf	TEMPH_F,f
	rrf	TEMPL_F,f
	rrf	TEMPH_F,f
	rrf	TEMPL_F,f
 
	movlw	b'11100000'		;do sign extend
	btfsc	TEMPH_C,7
	iorwf	TEMPHI_F,f
 
	movfw	TEMPL_C			;add original temp
	addwf	TEMPL_F,f
	btfsc	STATUS,C
	incf	TEMPH_F,f
	movfw	TEMPH_C
	addwf	TEMPH_F,f
 
	movlw	low(.320)		;add 320
	addwf	TEMPL_F,f
	btfss	STATUS,C
	incf	TEMPH_F,f
	movlw	high (.320)
	addwf	TEMPH_F,f

Mike.
 
Mike (Pommie),

I thought you might enjoy seeing your algorithm/method in assembly language on the little TI Launchpad board with MSP430 processor. Working with 16 bit registers is a treat. It uses 22 words of program memory, including the binary_to_bcd routine, and runs in about 100 cycles;

Regards, Mike

Code:
;*****************************************************************************
;  MSP430 DS18B20 Celsius to Fahrenheit Converter (raw °C data equals °C*16)
;
;  F*10 = C*18 + 320 = C*16 + C*2 + 320 = C*16 + (C*16 / 8) + 320
;
;     packed bcd output -0670 to +2570 (°F*10)
;
;                   Temp  Neg   PBCD   Display
;     ========================================
;     125.0000°C   0x07D0  0   0x2570  257.0°F 
;     100.0000°C   0x0640  0   0x2120  212.0°F
;      77.0000°C   0x04D0  0   0x1706  170.6°F
;      25.0000°C   0x0190  0   0x0770   77.0°F
;      22.0000°C   0x0160  0   0x0716   71.6°F
;       0.5000°C   0x0008  0   0x0329   32.9°F
;       0.0625°C   0x0001  0   0x0321   32.1°F
;       0.0000°C   0x0000  0   0x0320   32.0°F
;     - 0.0625°C   0xFFFF  0   0x0319   31.9°F
;     - 0.1250°C   0xFFFE  0   0x0318   31.8°F
;     - 5.0000°C   0xFFB0  0   0x0230   23.0°F
;     -10.0000°C   0xFF60  0   0x0140   14.0°F
;     -17.0625°C   0xFEEF  0   0x0013    1.3°F
;     -17.6875°C   0xFEE5  0   0x0002    0.2°F
;     -17.7500°C   0xFEE4  0   0x0001    0.1°F
;     -17.8125°C   0xFEE3  1   0x0001  - 0.1°F
;     -25.0000°C   0xFE70  1   0x0130  -13.0°F
;     -55.0000°C   0xFC90  1   0x0670  -67.0°F
;
c2f                             ; 15 words, 14 or 20 cycles
        mov.w   R12, R14        ; copy raw C16 word to R14 (1)
        add.w   #4, R14         ; rounding for 1 dec place (1)
        rra.w   R14             ;                          (1)
        rra.w   R14             ;                          (1)
        rra.w   R14             ;                          (1)
        add.w   R12, R14        ; R14 = C16 + C2           (1)
        add.w   #320, R14       ; R14 = C16 + C2 + 320     (2)
        bic.b   #1, &flags      ; clear 'neg' flag         (4)
        jge     b2d             ; neg? no, branch, else    (2)
        bis.b   #1, &flags      ; set 'neg' flag and       (4) 
        inv.w   R14             ; two's complement it      (1)
        inc.w   R14             ;                          (1)
;
;  bin to 4-digit packed bcd, 0x0000..0x270F -> 0x0000..0x9999
;
b2d                             ; 7 words, 82 cycles
        clr.w   R12             ;                          (1)
        mov.w   #1, R13         ;                          (1)
blp     rla.w   R14             ;                          (1)
        dadd.w  R12, R12        ; build packed bcd result  (1)
        rla.w   R13             ;                          (1)
        jnz     blp             ;                          (2)
;
;  print °F result
;
 
Last edited:
Hi Mike,

That looks like an interesting processor and the 16 bit registers definitely make things easier.

Shouldn't you be out letting of fire crackers and having fun?

Mike.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top