Separera Hundratal, Tiotal och Ental.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sodjan
EF Sponsor
Inlägg: 43245
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av sodjan »

> Skiit åxå att det bara kom en massa kodexempel i Högnivå språk.

Jo, men det har ju även nämnts att flera av dom inte är speciellt bra och
sannolikt genererar ganska "dålig" kod. Just detta är nog ett fall där man med
fördel kodar en liten effektiv ASM rutin till det hela. Och nu när du vet
hur man kan göra, så är det ju inget problem, eller hur ? :-)
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av PopUnoNkoK »

:)
Användarvisningsbild
Icecap
Inlägg: 26628
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av Icecap »

Att hitta en ASM-rutin som delar med 10 och har resten kvar i ett register lär knappast bli ett problem, om man sedan kan använda den rakt av är en annan sak.

Alltså är det bara att leta (kolla på piclist).

Och ska du skriva ut värdet i C är det ganska enkelt:
printf(Buffer, "%3d", Temperaturen);
Detta skriver ut värdet i variabeln "Temperaturen" med 3 platser. Behövs det fyll det upp med mellanslag.
bearing
Inlägg: 11670
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av bearing »

Men om han ändå ska skriva en egen rutin är det väl ändå onödigt att bland in division. Måste ju vara både enklare och snabbare att göra som i bos exempel.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av jesse »

>Skiit åxå att det bara kom en massa kodexempel i Högnivå språk.

Fanns det inga bra assembler-exempel på den länken som jag angav då?

t.ex. denna "binary to BCD":

Kod: Markera allt

From binary to BCD

; Bin2ToBcd5
; ==========
; converts a 16-bit-binary to a 5-digit-BCD
; In: 16-bit-binary in rBin1H:L, Z points to first digit
;   where the result goes to
; Out: 5-digit-BCD, Z points to first BCD-digit
; Used registers: rBin1H:L (unchanged), rBin2H:L (changed),
;   rmp
; Called subroutines: Bin2ToDigit
;
Bin2ToBcd5:
	push rBin1H ; Save number
	push rBin1L
	ldi rmp,HIGH(10000) ; Start with tenthousands
	mov rBin2H,rmp
	ldi rmp,LOW(10000)
	mov rBin2L,rmp
	rcall Bin2ToDigit ; Calculate digit
	ldi rmp,HIGH(1000) ; Next with thousands
	mov rBin2H,rmp
	ldi rmp,LOW(1000)
	mov rBin2L,rmp
	rcall Bin2ToDigit ; Calculate digit
	ldi rmp,HIGH(100) ; Next with hundreds
	mov rBin2H,rmp
	ldi rmp,LOW(100)
	mov rBin2L,rmp
	rcall Bin2ToDigit ; Calculate digit
	ldi rmp,HIGH(10) ; Next with tens
	mov rBin2H,rmp
	ldi rmp,LOW(10)
	mov rBin2L,rmp
	rcall Bin2ToDigit ; Calculate digit
	st z,rBin1L ; Remainder are ones
	sbiw ZL,4 ; Put pointer to first BCD
	pop rBin1L ; Restore original binary
	pop rBin1H
	ret ; and return

;
; Bin2ToDigit
; ===========
; converts one decimal digit by continued subraction of a
;   binary coded decimal
; Used by: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc
; In: 16-bit-binary in rBin1H:L, binary coded decimal in
;   rBin2H:L, Z points to current BCD digit
; Out: Result in Z, Z incremented
; Used registers: rBin1H:L (holds remainder of the binary),
;   rBin2H:L (unchanged), rmp
; Called subroutines: -
;
Bin2ToDigit:
	clr rmp ; digit count is zero
Bin2ToDigita:
	cp rBin1H,rBin2H ; Number bigger than decimal?
	brcs Bin2ToDigitc ; MSB smaller than decimal
	brne Bin2ToDigitb ; MSB bigger than decimal
	cp rBin1L,rBin2L ; LSB bigger or equal decimal
	brcs Bin2ToDigitc ; LSB smaller than decimal
Bin2ToDigitb:
	sub rBin1L,rBin2L ; Subtract LSB decimal
	sbc rBin1H,rBin2H ; Subtract MSB decimal
	inc rmp ; Increment digit count
	rjmp Bin2ToDigita ; Next loop
Bin2ToDigitc:
	st z+,rmp ; Save digit and increment
	ret ; done
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7443
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av Marta »

Ett exempel i assembler, om än en mycket speciell dialekt. Finns på Piclist i original, men enligt mitt tycke med något otydliga kommentarer.

Klarar endast 0..255, men det borde kunna räcka till detta ändamål om den endast skall visa hela grader.

Kod: Markera allt

.
******	CONVERT BINARY TO BCD
*
*	IN: A=BINARY NUMBER
*	OUT: BCDACC=PACKED BCD PLUS 100:TH DIGIT IN BCDACC.100
*
*	ORIGINAL CODE BY SCOTT DATTELO
*	CONVERTED AND RECOMMENTED BY MARTA
*
BINBCD	LOD BCDACC,A		USE AS SCRATCH
	STZ BCDACC.100		CLEAR 100:TH
	SWN A=BCDACC		THIS GIVES 1 FOR 16, 2 FOR 32..
	*			..4 FOR 64 AND 8 FOR 128
	ADD A,BCDACC		ADD IN 0 TO 9 OF THE BINARY NUMBER..
	*			..1 FOR 16 IS GARBAGE, COMPENSATED LATER ON
	AND A,#b0000_1111	MASK OUT LOW NIBBLE, CARRY PRESERVED IN HC
	SFC HC			WAS THERE A HALF CARRY
	ADD A,#$16		YES- ADD IN AS BCD
	SFC HC			DID LOW DIGIT OVERFLOW?
	ADD A,#$06		YES-ADD IN BCD ADJUSTMENT

	*			BCD ADJUSTMENT TO ASSURE NO OVERFLOW NEXT
	ADD A,#$06		TRY ADD IN BCD ADJUSTMENT
	SFS HC			BCD WRAP OVER?
	ADD A,#-$06		NO-UNADJUST

	SBR BCDACC,4		IS THERE A 16 BIT?
	ADD A,#$16-1+$6 	YES-ADD IN MINUS GARBAGE 1 FROM ABOVE..
	*			..ALSO TRY BCDADJ (THE $6 TERM)
	SFS HC			BCD WRAP OVER?
	ADD A,#-$06		NO-UNADJUST

	*			THESE ONLY ON HIGH NIBBLE, BCD ADJ NEVER NEEDED
	SBR BCDACC,5		ADD IN 10:TH OF 32
	ADD A,#$30
	SBR BCDACC,6		ADD IN 10:TH OF 64
	ADD A,#$60

	*			DO 128 BIT
	SBR BCDACC,7		IS THERE A 128 BIT?
	ADD A,#$20		ADD IN 10:TH OF 128

	ADD A,#$60		TRY BCD ADJUST HIGH NIBBLE
	ROL BCDACC.100		ROTATE IN EVENTUAL CARRY AS 100:TH
	SBS BCDACC.100,0	WAS THERE A BCD OVERFLOW?
	ADD A,#-$60		NO-UNADJUST

	SBR BCDACC,7		ADD IN 100:TH OF 128..
	INC BCDACC.100		..BY INCREMENTING 100:TH DIGIT
	LOD BCDACC,A		SAVE TWO LOWEST BCD DIGITS
	RTS			DONE

Senast redigerad av Marta 18 april 2009, 21:49:27, redigerad totalt 1 gång.
bearing
Inlägg: 11670
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av bearing »

AVR-assembler hjälper nog inte en PIC-kille. Det är väldigt stor skillnad faktiskt, både i syntax, instruktionsuppsättning och processoruppbyggnad.
Användarvisningsbild
Marta
EF Sponsor
Inlägg: 7443
Blev medlem: 30 mars 2005, 01:19:59
Ort: Landskrona
Kontakt:

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av Marta »

Det där är absolut inte AVR, det är för PIC16, men en udda dialekt.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av jesse »

Jaså, handlade det om PIC, det såg jag inte. :doh: Blandade nog ihop rubrikerna på trådarna för jag var övertygad om att han hade en ATmega8.

Om det nu gäller en PIC - varför inte skriva det i frågan då? Eller är PIC default om man inte säger att det gäller AVR eller nåt annat? Frågeställarens namn får jag till PUNK - inte PIC. Och som alla vet - AVR är punk! 8)
sodjan
EF Sponsor
Inlägg: 43245
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av sodjan »

> Jaså, handlade det om PIC, det såg jag inte.

För algoritmerna så ser jag att det spelar någon större roll.
Om det hade varit viktigt så hade det nog kommit frågor om det
tidigt i tråden. I princip gör man likadant oavsett om det är
AVR, PIC eller något annat.

Men visst har du rätt i att det hade varit bättre om processormodellen
hade angivits, om än inte helt avgörande... :-)
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av jesse »

Du har helt rätt, Sodjan. Egentligen borde man kunna diskutera en sådan algoritm helt oberoende av vilken pryl man råkar använda. Det blir mer generellt , oberoende av språk och processor och därmed intressant för fler personer.

Den algoritm jag länkade till i AVR assembler skulle kunna se ut ungefär så här i pseudokod:

Kod: Markera allt

A är 16 bitars tal - det tal som ska visas
B är 16 bitars tal
C är adresspekare till plats i ram-minne (eller pekare i Array)
siffra är ett 8-bitars tal. (BCD)
efter avslutad omvandling innehåller
(C) 5 st BCD-siffror t.ex. 00123

sätt C till adress
Läs in talet i A 
sätt B till 10000
beräkna siffra ; (subrutin)
spara siffra i (C)
inc C 
sätt B till 1000
beräkna siffra ; (subrutin)
spara siffra i (C)
inc C
sätt B till 100
beräkna siffra ; (subrutin)
spara siffra i (C)
inc C
sätt B till 10
beräkna siffra ; (subrutin)
spara siffra i (C)
inc C
spara låga byte av A i (C) ; sista siffran

; subrutin
beräkna_siffra:
sätt siffra till 0
loop:
är A<B ? { exit loop }
A=A-B
inc siffra
end loop
PopUnoNkoK
Inlägg: 789
Blev medlem: 10 december 2007, 12:40:08
Ort: Piteå

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av PopUnoNkoK »

Tackar för svaren.

Ska försöka skriva en egen "rutin" med hjälp av era svar.

MVH Peter F
bos
Inlägg: 2311
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av bos »

bearing skrev:Måste ju vara både enklare och snabbare att göra som i bos exempel.
sprintf() är förstås bekvämast men då blir man av med löjligt mycket programminne också, och cykelantalen blir femsiffriga...

Jag satt just med denna tråds problem för två veckor sedan och försökte leta fram den mest optimala lösningen; lite kod, lågt antal cykler. Subtraktionsmetoden, den jag visade koden på, slog alla andra varianter med god marginal.
blueint
Inlägg: 23238
Blev medlem: 4 juli 2006, 19:26:11
Kontakt:

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av blueint »

Vill bara säga att mitt exempel var avsett att illustrera principen. Dom andra exemplena kanske är skrivna i högnivåspråk. Men illustrerar principen bra. Vilket assemblerkod sällan gör. Den blir lätt grötig fort.
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Re: Separera Hundratal, Tiotal och Ental.

Inlägg av v-g »

Brukar själv köra lite olika varianter, är det EN byte så är det bara att köra på med minusmetoden den är enkel att förstå och antalet cykler är inte särskilt många samt att man enkelt kodar den själv.

För flersiffriga prylar är det ju såklart lite svårare men på piclist finns rätt många exempel och jag har alltid hittat en som passat specifikt för mina ändamål. Dock är det inte alltid bara klipp och klistra men det är ju på felsökningen man lär sig ;)
Skriv svar