Konvertera binärtal till Decimaltal på display?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Klas-Kenny
Inlägg: 11843
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Konvertera binärtal till Decimaltal på display?

Inlägg av Klas-Kenny »

Jag har funderat över det ett tag, om jag har tex. ett värde från ADC, 0000 0000 - 1111 1111, och vill skriva ut det som decimaltal 0 - 255 på en display av någon typ, tex. 3st 7-seg eller en HD44780, hur gör man detta enklast med en PIC (PIC16Fxxx, Assembly)?

Första jag kunde tänka mig är Lookup-table, men hur ska man kunna returnera de tre tecken (tre byte) som krävs för att skriva det som dec? Och det borde väl finnas effektivare metoder är en 256 rader lång lookup-table?
Användarvisningsbild
petterMAN
Inlägg: 125
Blev medlem: 27 december 2007, 16:46:09
Ort: Umeå

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av petterMAN »

Jag har löst detta i assembler tidigare genom att först räkna antal hundratal, tiotal och ental.
Skriver ett exempel nedan i någon slags pseudokod( :vissla: ):

Kod: Markera allt

hundratal=0
tiotal=0
ental=0
var=255
loop1:
IF var >= 100 {
   INC hundratal
   var=var-100
   GOTO loop1
}
loop2:
IF var >= 10 {
   INC tiotal
   var=var-10
   GOTO loop2
}
loop3:
IF var >= 1 {
   INC ental
   var=var-1
   GOTO loop3
}
sedan är det bara att lägga till ASCII offset för tecknet 0 och skriva ut (förutsatt alfanumerisk LCD).
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

> Jag har funderat över det ett tag, om jag har tex. ett värde från ADC, 0000 0000 - 1111 1111,
> och vill skriva ut det som decimaltal 0 - 255

Hur skulle du göra med enbart papper och penna ?
Gör sen på i princip samma sätt...

Hur många gånger kan jag minska ADC värdet med 100 utan
att det blir < 0 ? Antalet gånger är din 100-talssiffra. Spara resten.

Hur många gånger kan jag minska resten med 10 utan
att det blir < 0 ? Antelt gånger är din 10-talssiffra. Spara resten.

Resten är nu din entalssiffra.

Klart !

Kod: Markera allt

loop3:
IF var >= 1 {
   INC ental
   var=var-1
   GOTO loop3
Väldigt onödigt, eller hur ? :-)
Det hela kan ersättas med

Kod: Markera allt

ental = var
"ental" kommer *alltid* att bli detsamma som "var"...
Användarvisningsbild
petterMAN
Inlägg: 125
Blev medlem: 27 december 2007, 16:46:09
Ort: Umeå

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av petterMAN »

Haha självklart!:) Får skylla på tidpunkten :oops:
Användarvisningsbild
Klas-Kenny
Inlägg: 11843
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av Klas-Kenny »

>Hur skulle du göra med enbart papper och penna ?
"128+64+32+16+8+4+2+1 = 255", känns inte som att det hjälper så mycket just här? :wink:

Ett snabbt utkast taget ur huvudet:

Kod: Markera allt

kolla_hundratal
movlw 0x64
subwf ADC,f
incf hundratal,f
btfss STATUS,C
goto kolla_hundratal
addwf ADC,f

kolla_tiotal
movlw 0x0A
subwf ADC,f
incf tiotal,f
btfss STATUS,C
goto kolla_tiotal
addwf ADC,f

movfw ADC
movwf ental


Skulle någonting sådant kunna fungera?

Tack för bra svar!
Nu har jag lite att fundera på innan jag somnar, godnatt :D
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

> movlw 0x64
> movlw 0x0A

Varför inte d'100' resp d'10' ?
Är inte det mycket tydligare ?

Men annars så ser det ju spontant inte helt fel ut.
Kör det i MPSIM så ser du direkt om det fungerar.
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av bos »

Klas-Kenny skrev:Jag har funderat över det ett tag, om jag har tex. ett värde från ADC, 0000 0000 - 1111 1111, och vill skriva ut det som decimaltal 0 - 255 på en display av någon typ, tex. 3st 7-seg eller en HD44780, hur gör man detta enklast med en PIC (PIC16Fxxx, Assembly)?
Jag byggde en batteritestare nyligen. Den använder en PIC12F689 som matar ut seriedata till en 74LS164, som i sin tur matar två LED-segment. Här är relevanta delar av koden, som du kan stjäla bäst du vill:

Kod: Markera allt

; Bit-structure for the serial stream to the 74LS164
#define LED_A  b'11111110'
#define LED_B  b'11111101'
#define LED_C  b'11111011'
#define LED_D  b'11110111'
#define LED_E  b'11101111'
#define LED_F  b'11011111'
#define LED_G  b'10111111'
#define LED_DP b'01111111'

; Building blocks for the segments
#define ZERO  LED_A & LED_B & LED_C & LED_D & LED_E & LED_F
#define ONE   LED_B & LED_C
#define TWO   LED_A & LED_B & LED_G & LED_E & LED_D
#define THREE LED_A & LED_B & LED_G & LED_C & LED_D
#define FOUR  LED_B & LED_C & LED_G & LED_F
#define FIVE  LED_A & LED_C & LED_D & LED_F & LED_G
#define SIX   LED_A & LED_G & LED_C & LED_D & LED_E & LED_F
#define SEVEN LED_A & LED_B & LED_C
#define EIGHT LED_A & LED_B & LED_C & LED_D & LED_E & LED_F & LED_G
#define NINE  LED_A & LED_B & LED_C & LED_D & LED_F & LED_G

...
loop:
        call    read_adc
        movfw   ADC_VALUE
        call    split_ones_tenths     ; split value to TENS and ONES

        movfw   TENS           
        call    number_to_led
        andlw   LED_DP                ; the left LED should have its dot lit
        call    spi_output            ; send data to the '164
        movlw   LED1                  ; hold the data on LED1 for a fixed amount of time
        call    led_delay

        movfw   ONES
        call    number_to_led
        call    spi_output
        movlw   LED2
        call    led_delay

        goto    loop

...

; Convert decimal values to "LED segment"-format
; Used for the '164
number_to_led
        addwf   PCL
        retlw   ZERO
        retlw   ONE
        retlw   TWO
        retlw   THREE
        retlw   FOUR
        retlw   FIVE
        retlw   SIX
        retlw   SEVEN
        retlw   EIGHT
        retlw   NINE


; This function split an integer into 'tens' and 'ones'. This is
; achieved by subtracting 10 from the value until a Borrow occurs.
split_ones_tenths
        clrf    TENS
        movlw   .10
remove_10
        subwf   resultat                            ; Remove 10
        incf    TENS
        btfsc   STATUS, C                           ; Borrow?
         goto    remove_10                          ; No, continue

        addwf   resultat                            ; Yes, correct the values.
        decf    TENS

        ; Copy the remainder, and we're done.
        movfw   resultat
        movwf   ONES
        return


Användarvisningsbild
Klas-Kenny
Inlägg: 11843
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av Klas-Kenny »

Har nu försökt mig på att simulera koden (Första gången jag gör det) i MPSIM, och det fungerar inte alls :?

STATUS,C verkar aldrig ändra sig, så den kommer aldrig ur loopen som kollar hundratal. Kan vara jag som gör fel när jag simulerar i och för sig...

Sen undrar jag hur jag kollar variablers värde i MPSIM? Hittar bara funktionsregisterna.

Hela koden just nu:

Kod: Markera allt

	list		p=16f690		; list directive to define processor
	#include	<P16F690.inc>		; processor specific variable definitions
	
	__CONFIG    _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF


; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.






;***** VARIABLE DEFINITIONS
cblock
	ADC
	ental
	tiotal
	hundratal
endc




;**********************************************************************
	ORG		0x000			; processor reset vector

main
	movlw	0xFF
	movwf	ADC

kolla_hundratal
	incf		 hundratal,f
	movlw		d'100'
	subwf		ADC,f
	btfss		STATUS,C
	goto		 kolla_hundratal
	addwf		ADC,f
	decf		 hundratal,f

kolla_tiotal
	movlw		d'10'
	subwf		ADC,f
	incf		 tiotal,f
	btfss		STATUS,C
	goto		 kolla_tiotal
	addwf		ADC,f
	decf		 hundratal,f

	movfw		ADC				;Lägg ental i variabeln ental
	movwf		ental

END 

bos: Tack så mycket!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

> Sen undrar jag hur jag kollar variablers värde i MPSIM? Hittar bara funktionsregisterna.

I WATCH. Du väljer "Add SFR" eller "Add Symbol".
Användarvisningsbild
Klas-Kenny
Inlägg: 11843
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av Klas-Kenny »

I listan brevid "Add SFR" finns ingen av mina variabler, bara funktionsregisterna, och "Add Symbol" går inte att trycka på... :(
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av bearing »

Du kan markera och sedan dra/släppa en variabel från kodrutan in i watch-fönstret.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

> I listan brevid "Add SFR" finns ingen av mina variabler...

Och vad finns i listan bredvid "Add Symbol " ????
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

OK, testade med din kod. Jag har gjort ett par
justeringar och rättat några rena slarvfel...

Fungerar helt OK, får 2, 5 pch 5 i hundratal, tiotal och antal.

Notera också att CBLOCK skapar *konstanter*, så de är inte
speciellt intressanta att se i WATCH, de har alltid samma värde.
Troligtsivis därför de inte visas.

Du hade inte nollat variablerna (CLRF).

Du "backade" hundratal två gånger (slarvfelet).

Kod: Markera allt

   list      p=16f690      ; list directive to define processor
   #include   <P16F690.inc>      ; processor specific variable definitions
   
   __CONFIG    _CP_OFF & _CPD_OFF & _BOR_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _FCMEN_OFF & _IESO_OFF


; '__CONFIG' directive is used to embed configuration data within .asm file.
; The labels following the directive are located in the respective .inc file.
; See respective data sheet for additional information on configuration word.






;***** VARIABLE DEFINITIONS

	udata
ADC       RES 1
ental     RES 1
tiotal 	RES 1
hundratal RES 1

;**********************************************************************
   code      0x000         ; processor reset vector

main
   movlw   0xFF
   movwf   ADC
   clrf    hundratal
   clrf    tiotal
   clrf    ental

kolla_hundratal
   incf       hundratal,f
   movlw      d'100'
   subwf      ADC,f
   btfsc      STATUS,C
   goto       kolla_hundratal
   addwf      ADC,f
   decf       hundratal,f

kolla_tiotal
   movlw      d'10'
   subwf      ADC,f
   incf       tiotal,f
   btfsc      STATUS,C
   goto       kolla_tiotal
   addwf      ADC,f
   decf       tiotal,f

   movfw      ADC            ;Lägg ental i variabeln ental
   movwf      ental

END 
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av sodjan »

En sak till justerade jag...

Det ska vara btfsc, inte btfss.
Kan kännas bakvänt, men stämmer med databladet.
Från sidan där STATUS beskrivs har "C" biten en fotnot :
"Note 1: For Borrow, the polarity is reversed."
Användarvisningsbild
Klas-Kenny
Inlägg: 11843
Blev medlem: 17 maj 2010, 19:06:14
Ort: Växjö/Alvesta

Re: Konvertera binärtal till Decimaltal på display?

Inlägg av Klas-Kenny »

Gör cblock konstanter? Det hade jag inte en aning om, jag har alltid använt cblock tidigare och det har inte varit några problem alls, där lärde man sig någonting nytt!

Tack för all hjälp, som vanligt! :) :tumupp:
Skriv svar