Sida 2 av 3

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 16:54:06
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 ? :-)

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 17:44:33
av PopUnoNkoK
:)

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 18:01:11
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.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 18:56:38
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.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 21:42:54
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

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 21:47:09
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


Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 21:49:22
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.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 22:13:55
av Marta
Det där är absolut inte AVR, det är för PIC16, men en udda dialekt.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 22:46:33
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)

Re: Separera Hundratal, Tiotal och Ental.

Postat: 18 april 2009, 23:25:49
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... :-)

Re: Separera Hundratal, Tiotal och Ental.

Postat: 19 april 2009, 09:07:27
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

Re: Separera Hundratal, Tiotal och Ental.

Postat: 19 april 2009, 18:50:34
av PopUnoNkoK
Tackar för svaren.

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

MVH Peter F

Re: Separera Hundratal, Tiotal och Ental.

Postat: 20 april 2009, 18:13:27
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.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 20 april 2009, 20:16:17
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.

Re: Separera Hundratal, Tiotal och Ental.

Postat: 21 april 2009, 19:54:24
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 ;)