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.

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!

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
