PCB Heaven

General Category => Digital discussion => Topic started by: Alex on March 01, 2008, 23:04:34 PM

Title: Need routine for digital display for PIC 16F84
Post by: Alex on March 01, 2008, 23:04:34 PM
I use PIC 16F84. I know it is rather old but i had once some tenths of them that accidentally came to me (in a really low price) and i stocked.

So, now i need to display a number from 0 to 254 to 3 7-Seg displays. What i really do is a loop from 0 to the number that i want to show and every time i add a 'unit register' until 10 and then i add a 'decade register' until 10 etc etc etc. This means that if i want to show number 210, i will have to count from 0 to 210 everytime. And this is a laaaaaaaaaaaaag for my PIC.

Does anybody know a clever way to do this? Please?
Title: Re: Need routine for digital display for PIC 16F84
Post by: kam on March 01, 2008, 23:20:32 PM
I know what you mean and i have just what you are looking for here.



Code: [Select]
;********************************
;binary_to_bcd - 8-bits
;
;Input
;  bin  - 8-bit binary number
; A1*16+A0
;Outputs
; hundreds - the hundreds digit of the BCD conversion
; tens_and_ones - the tens and ones digits of the BCD conversion
binary_to_bcd:

        CLRF    hundreds
        SWAPF   bin, W ;w  = A0*16+A1
        ADDWF   bin, W ;w  = A0+A1
        ANDLW   00001111b ;w  = A0+A1 % 16
        SKPNDC ;if A0+A1 > 16
         ADDLW  0x16 ;  w  += 16
        SKPNDC ;if w % 16 > 10
         ADDLW  0x06 ;  w  += 6
        ADDLW   0x06 ;w  += 6
        SKPDC ;if w < 10
         ADDLW  -0x06 ;  w  -= 6

        BTFSC   bin,4
         ADDLW   0x16 - 1 + 0x6
        SKPDC
         ADDLW  -0x06

        BTFSC   bin, 5
         ADDLW  0x30

        BTFSC   bin, 6
         ADDLW  0x60

        BTFSC   bin, 7
         ADDLW  0x20

        ADDLW   0x60
        RLF     hundreds, F
        BTFSS   hundreds, 0
         ADDLW  -0x60

        MOVWF   tens_and_ones
        BTFSC   bin,7
         INCF   hundreds, F
Title: Re: Need routine for digital display for PIC 16F84
Post by: Alex on March 01, 2008, 23:44:19 PM
I will test it tomorrow and if it works, i will buy you a dozen beers!  ;D ;D ;D ;D
Title: Re: Need routine for digital display for PIC 16F84
Post by: kam on March 02, 2008, 02:36:42 AM
you better start ordering!
Title: Re: Need routine for digital display for PIC 16F84
Post by: tpone on March 02, 2008, 10:24:10 AM
Man this is great! It rocks!  :o :o :o :o :o :o

I have a digital thermometer with a 16x2 display and i tested your routine. It is much much much faster than the routine i was using!

It is great!
Title: Re: Need routine for digital display for PIC 16F84
Post by: kostas on March 02, 2008, 13:09:48 PM
And what if you want to have larget numbers? Like 18bits or 24 or 32bit? Can this routine help?
Title: Re: Need routine for digital display for PIC 16F84
Post by: kam on March 02, 2008, 14:58:08 PM
Well...

16bit to 5 digits about 200 words


Code: [Select]
;Takes hex number in NumH:NumL  Returns decimal in ;TenK:Thou:Hund:Tens:Ones
;written by John Payson

;input
;=A3*163 + A2*162 + A1*161 + A0*160
;=A3*4096 + A2*256 + A1*16 + A0
NumH            EQU AD3M        ;A3*16+A2
NumL            EQU AD3L ;A1*16+A0
;share variables
;=B4*104 + B3*103 + B2*102 + B1*101 + B0*100
;=B4*10000 + B3*1000 + B2*100 + B1*10 + B0
TenK            EQU LOOPER      ;B4
Thou            EQU D2 ;B3
Hund            EQU D1 ;B2
Tens            EQU R2 ;B1
Ones            EQU R1 ;B0

swapf NumH,w ;w  = A2*16+A3
        andlw   0x0F     ;w  = A3 *** PERSONALLY, I'D REPLACE THESE 2
        addlw   0xF0 ;w  = A3-16 *** LINES WITH "IORLW b'11110000B' " -AW
        movwf   Thou ;B3 = A3-16
        addwf   Thou,f ;B3 = 2*(A3-16) = 2A3 - 32
        addlw   .226 ;w  = A3-16 - 30 = A3-46
        movwf   Hund ;B2 = A3-46
        addlw   .50 ;w  = A3-46 + 50 = A3+4
        movwf   Ones ;B0 = A3+4

        movf    NumH,w ;w  = A3*16+A2
        andlw   0x0F ;w  = A2
        addwf   Hund,f ;B2 = A3-46 + A2 = A3+A2-46
        addwf   Hund,f ;B2 = A3+A2-46  + A2 = A3+2A2-46
        addwf   Ones,f ;B0 = A3+4 + A2 = A3+A2+4
        addlw   .233 ;w  = A2 - 23
        movwf   Tens ;B1 = A2-23
        addwf   Tens,f ;B1 = 2*(A2-23)
        addwf   Tens,f ;B1 = 3*(A2-23) = 3A2-69 (Doh! thanks NG)

        swapf   NumL,w ;w  = A0*16+A1
        andlw   0x0F ;w  = A1
        addwf   Tens,f ;B1 = 3A2-69 + A1 = 3A2+A1-69 range -69...-9
        addwf   Ones,f ;B0 = A3+A2+4 + A1 = A3+A2+A1+4 and Carry = 0 (thanks NG)

        rlf     Tens,f ;B1 = 2*(3A2+A1-69) + C = 6A2+2A1-138 and Carry is now 1 as tens register had to be negitive
        rlf     Ones,f ;B0 = 2*(A3+A2+A1+4) + C = 2A3+2A2+2A1+9 (+9 not +8 due to the carry from prev line, Thanks NG)
        comf    Ones,f ;B0 = ~(2A3+2A2+2A1+9) = -2A3-2A2-2A1-10 (ones complement plus 1 is twos complement. Thanks SD)
;;Nikolai Golovchenko [golovchenko at MAIL.RU] says: comf can be regarded like:
;;      comf Ones, f
;;      incf Ones, f
;;      decf Ones, f
;;First two instructions make up negation. So,
;;Ones  = -1 * Ones - 1
;;      = - 2 * (A3 + A2 + A1) - 9 - 1
;;      = - 2 * (A3 + A2 + A1) - 10
        rlf     Ones,f ;B0 = 2*(-2A3-2A2-2A1-10) = -4A3-4A2-4A1-20

        movf    NumL,w ;w  = A1*16+A0
        andlw   0x0F ;w  = A0
        addwf   Ones,f ;B0 = -4A3-4A2-4A1-20 + A0 = A0-4(A3+A2+A1)-20 range -215...-5 Carry=0
        rlf     Thou,f ;B3 = 2*(2A3 - 32) = 4A3 - 64

        movlw   0x07 ;w  = 7
        movwf   TenK ;B4 = 7

;B0 = A0-4(A3+A2+A1)-20 ;-5...-200
;B1 = 6A2+2A1-138 ;-18...-138
;B2 = A3+2A2-46 ;-1...-46
;B3 = 4A3-64 ;-4...-64
;B4 = 7 ;7
; At this point, the original number is
; equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's compliment
; binary.  To be precise, all of them are negative
; except TenK.  Now the number needs to be normal-
; ized, but this can all be done with simple byte
; arithmetic.

        movlw   .10 ;w  = 10
Lb1: ;do
        addwf   Ones,f ; B0 += 10
        decf    Tens,f ; B1 -= 1
        btfss   3,0
;skip no carry
         goto   Lb1 ; while B0 < 0
;jmp carry
Lb2: ;do
        addwf   Tens,f ; B1 += 10
        decf    Hund,f ; B2 -= 1
        btfss   3,0
         goto   Lb2 ; while B1 < 0
Lb3: ;do
        addwf   Hund,f ; B2 += 10
        decf    Thou,f ; B3 -= 1
        btfss   3,0
         goto   Lb3 ; while B2 < 0
Lb4: ;do
        addwf   Thou,f ; B3 += 10
        decf    TenK,f ; B4 -= 1
        btfss   3,0
         goto   Lb4 ; while B3 < 0

        retlw   0



16bits to 5 digits faster and always 131 words

Code: [Select]
aar0 = binary number low byte
aar1 = binary number high byte
aac0 = bcd number ones
aac1 = bcd number tens
aac2 = bcd number hundreds
aac3 = bcd number thousands
aac4 = bcd number ten-thousands
 
b16_d5
        swapf   aar0,w ; partial ones sum in low byte
        addwf   aar0,w ;
        andlw   0x0f ;
        skpndc ;
        addlw 0x16 ;
        skpndc ;
        addlw  0x06 ;
        addlw   0x06 ;
        skpdc ;
addlw  -0x06 ; wmax=3:0
;
        btfsc   aar0,4 ; complete ones sum in low byte
        addlw   0x15+0x06
        skpdc
        addlw  -0x06 ; wmax=4:5
movwf aac0 ; save sum in aac0
;
;     8+      4+     2+     1+     8+     4+    2+    1+
;    20
;   100      60     30     15+
;   ----------------------------------------------------
;   128      64     32     16      8      4     2     1
;
        swapf   aar1,w ; partial ones sum in high byte
        addwf   aar1,w ;
        andlw   0x0f ;
        skpndc ;
        addlw 0x16 ;
        skpndc ;
        addlw  0x06 ;
        addlw   0x06 ;
        skpdc ;
addlw  -0x06 ; wmax=3:0
;
btfsc   aar1,0 ; complete ones sum in high byte
        addlw   0x05+0x06
        skpdc
        addlw  -0x06 ; wmax=3:5
;
        btfsc   aar1,4
        addlw   0x15+0x06
        skpdc
        addlw  -0x06 ; wmax=5:0
;
addlw 0x06 ; include previous sum
addwf aac0,w
        skpdc
        addlw  -0x06 ; wmax=9:5, ones sum ended
;
movwf aac0
movwf aac1
swapf aac1,f
movlw 0x0f
andwf aac0,f ; save total ones sum in aac0
andwf aac1,f ; save partial tens sum in aac1
;
;     8+      4+     2+     1+     8+     4+    2+    1+
;                           5+
;    60      80     90     10+                        5+
;   700     300    100     80     40     20    10    50
; 32000   16000   8000   4000   2000   1000   500   200
; ------------------------------------------------------
; 32768   16384   8192   4096   2048   1024   512   256
;
; complete tens sum in low and high byte
rrf aar1,w ; rotate right high byte once
andlw 0x0f ; clear high nibble
addlw 0x06 ; adjust bcd
skpdc
addlw -0x06 ; wmax=1:5
;
addlw 0x06 ; include previous sum
addwf aac1,w
        skpdc
        addlw  -0x06 ; wmax=2:4
;
        btfsc   aar0,5
        addlw   0x03+0x06
        skpdc
        addlw  -0x06 ; wmax=2:7
;
        btfsc   aar0,6
        addlw   0x06+0x06
        skpdc
        addlw  -0x06 ; wmax=3:3
;
        btfsc   aar0,7
        addlw   0x12+0x06
        skpdc
        addlw  -0x06 ; wmax=4:5
;
        btfsc   aar1,0
        addlw   0x25+0x06
        skpdc
        addlw  -0x06 ; wmax=7:0
;
        btfsc   aar1,5
        addlw   0x09+0x06
        skpdc
        addlw  -0x06 ; wmax=7:9
;
        btfsc   aar1,6
        addlw   0x08+0x06
        skpdc
        addlw  -0x06 ; wmax=8:7
;
        btfsc   aar1,7
        addlw   0x06+0x06
        skpdc
        addlw  -0x06 ; wmax=9:3, tens sum ended
;
movwf aac1 ; save total tens sum in aac1
swapf aac1,w
andlw 0x0f ; load partial hundreds sum in w
;
;     8+      4+     2+     1+     8+     4+    2+    1+
;    20+                    5+
;   100+     60+    30+    10+
;   ----------------------------------------------------
;   128      64     32     16      8      4     2     1
;
;     8+      4+     2+     1+     8+     4+    2+    1+
;                           5+
;    60+     80+    90+    10+                        5+
;   700     300    100     80+    40+    20+   10+   50+
; 32000   16000   8000   4000   2000   1000   500   200+
; ------------------------------------------------------
; 32768   16384   8192   4096   2048   1024   512   256
;
; complete hundreds sum in high byte
        btfsc   aar1,1
        addlw   0x05+0x06
        skpdc
        addlw  -0x06 ; wmax=1:4
;
        btfsc   aar1,5
        addlw   0x01+0x06
        skpdc
        addlw  -0x06 ; wmax=1:5
;
        btfsc   aar1,6
        addlw   0x03+0x06
        skpdc
        addlw  -0x06 ; wmax=1:8
;
        btfsc   aar1,7
        addlw   0x07+0x06
        skpdc
        addlw  -0x06 ; wmax=2:5, hundreds sum ended
;
movwf aac2 ; save total hundreds sum in aac2
swapf aac2,w
movwf aac3 ; save partial thousands sum in aac3
movlw 0x0f ; clear high nibble
andwf aac1,f ;
andwf aac2,f ;
andwf aac3,f ;
;
;     8+      4+     2+     1+     8+     4+    2+    1+
;                           5+
;    60+     80+    90+    10+                        5+
;   700+    300+   100+    80+    40+    20+   10+   50+
; 32000   16000   8000   4000   2000   1000   500+  200+
; ------------------------------------------------------
; 32768   16384   8192   4096   2048   1024   512   256
;
; complete thousands sum in low and high byte
rrf aar1,w ; rotate right high byte twice
movwf aac4 ;
rrf aac4,w ;
andlw 0x0f ; clear high nibble
addlw 0x06 ; adjust bcd
skpdc ;
addlw -0x06 ; wmax=1:5
;
addlw 0x06 ; include previous sum
addwf aac3,w
skpdc
addlw -0x06 ; wmax=1:7
;
        btfsc   aar1,6
        addlw   0x16+0x06
skpdc
addlw -0x06 ; wmax=3:3
;
        btfsc   aar1,7
        addlw   0x32+0x06
skpdc
addlw -0x06 ; wmax=6:5, thousands sum ended
;
movwf aac3 ; save total thousands sum in aac3
movwf aac4 ;
swapf aac4,f ; save ten-thousands sum in aac4
movlw 0x0f ; clear high nibble
andwf aac3,f ;
andwf aac4,f ;


And 32bits to 10 digits

Code: [Select]
;******************************************************************
;
; Test program for 32-bit unsigned binary to BCD and BCD to ASCII.
;
;******************************************************************
        title   "32-bit binary to ascii"
        list p=pic16f84,r=dec,n=80,x=off,st=off
        include <p16f84.inc>
        errorlevel -302         ; no bank warnings
errorlevel -305 ; no default dest warnings

#define number 123456789

loadd macro
local m,n,p
p = number / 16777216
movlw p
movwf bin
m = (number - p * 16777216) / 65536
movlw m
movwf bin+1
n = (number - p * 16777216 - m * 65536) / 256
movlw n
movwf bin+2
movlw number - p * 16777216 - m * 65536 - n * 256
movwf bin+3
endm

CBLOCK 0x0c
bin:4 ; 32-bit binary number (unsigned)
bcd:10 ; 10 BC digits or 10 ascii chars
pti,pto ; pointers
ii
temp
cnt
ENDC

loadd ; load test value <number>
call b2bcd ; convert to 32-bit binary to 10 bcd
call bcd2a ; convert 10 bcd to 10 ascii
goto $

;******************************************************************
; Convert the 10 binary coded digits (5 bytes) starting at
; <bcd> into an ascii string also starting at <bcd>. Original
; bcd digits are lost.

bcd2a movlw bcd+9
movwf pto ; destination pointer
movlw bcd+4
movwf pti ; source pointer
movlw 5 ; 5 bytes to process
movwf cnt

bcd2a1 movf pti,w ; get current input pointer
movwf fsr
decf pti,f ; prepare for next
movf indf,w ; get 2 bcds
movwf temp ; save for later
movf pto,w ; get current output pointer
movwf fsr
decf pto,f ; prepare for next
decf pto,f
movf temp,w ; get digits back
andlw 0x0f ; process lsd
addlw "0"
movwf indf ; to output
decf fsr,f
swapf temp,w ; process msd
andlw 0x0f
addlw "0"
movwf indf ; to output
decfsz cnt ; all digits?
goto bcd2a1
return ; yes


;******************************************************************
; Convert 32-bit binary number at <bin> into a bcd number
; at <bcd>. Uses Mike Keitz's procedure for handling bcd
; adjust; Modified Microchip AN526 for 32-bits.

b2bcd movlw 32 ; 32-bits
movwf ii ; make cycle counter
clrf bcd ; clear result area
clrf bcd+1
clrf bcd+2
clrf bcd+3
clrf bcd+4

b2bcd2 movlw bcd ; make pointer
movwf fsr
movlw 5
movwf cnt

; Mike's routine:

b2bcd3 movlw 0x33
addwf indf,f ; add to both nybbles
btfsc indf,3 ; test if low result > 7
andlw 0xf0 ; low result >7 so take the 3 out
btfsc indf,7 ; test if high result > 7
andlw 0x0f ; high result > 7 so ok
subwf indf,f ; any results <= 7, subtract back
incf fsr,f ; point to next
decfsz cnt
goto b2bcd3

rlf bin+3,f ; get another bit
rlf bin+2,f
rlf bin+1,f
rlf bin+0,f
rlf bcd+4,f ; put it into bcd
rlf bcd+3,f
rlf bcd+2,f
rlf bcd+1,f
rlf bcd+0,f
decfsz ii,f ; all done?
goto b2bcd2 ; no, loop
return ; yes

end
Title: Re: Need routine for digital display for PIC 16F84
Post by: ScubaCap on March 02, 2008, 16:14:24 PM
As i was saying... a page with all of them gathered...
Title: Re: Need routine for digital display for PIC 16F84
Post by: Alex on March 02, 2008, 23:09:44 PM
Man i love you! What can i say! Thanx!  :-* :-* :-* :-*
Title: Re: Need routine for digital display for PIC 16F84
Post by: Mosquito on March 03, 2008, 00:43:49 AM
Is this just an expression of admiral or is it deeper?
Lol

just kidding  :P :P
Title: Re: Need routine for digital display for PIC 16F84
Post by: Alex on March 03, 2008, 11:59:20 AM
 :P :P :P
Title: Re: Need routine for digital display for PIC 16F84
Post by: kam on March 03, 2008, 12:21:45 PM
 ;)




 ;D