Home     Contact     Forum     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science     RSS     Terms of services     Privacy policy  
   
 Home     Forum     Projects     Experiments     Circuits     Theory     BLOG     PIC Tutorials     Time for Science   

Author Topic: Need routine for digital display for PIC 16F84  (Read 8839 times)

0 Members and 1 Guest are viewing this topic.

Alex

  • Guest
Need routine for digital display for PIC 16F84
« 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?

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Need routine for digital display for PIC 16F84
« Reply #1 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

Alex

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #2 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

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Need routine for digital display for PIC 16F84
« Reply #3 on: March 02, 2008, 02:36:42 AM »
you better start ordering!

tpone

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #4 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!

kostas

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #5 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?

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Need routine for digital display for PIC 16F84
« Reply #6 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

ScubaCap

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #7 on: March 02, 2008, 16:14:24 PM »
As i was saying... a page with all of them gathered...

Alex

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #8 on: March 02, 2008, 23:09:44 PM »
Man i love you! What can i say! Thanx!  :-* :-* :-* :-*

Mosquito

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #9 on: March 03, 2008, 00:43:49 AM »
Is this just an expression of admiral or is it deeper?
Lol

just kidding  :P :P

Alex

  • Guest
Re: Need routine for digital display for PIC 16F84
« Reply #10 on: March 03, 2008, 11:59:20 AM »
 :P :P :P

kam

  • Administrator
  • Hero Member
  • *****
  • Posts: 1849
Re: Need routine for digital display for PIC 16F84
« Reply #11 on: March 03, 2008, 12:21:45 PM »
 ;)




 ;D