Hallo,
nachdem ich mit so ziemlich allen Assembler-Lösungen, die ich dazu
gefunden habe, nicht so recht klar gekommen bin (teilweise erschließt
sich mir einfach die Funktion des Codes nicht) hab ich mich hingesetzt
und selber eine Routine gestrickt:
; Konvertierung Binaer-->BCD
; Binaerwert wird in temp uebergeben
BIN_to_BCD:
clr pulses5 ; Zehntausender
clr pulses4 ; Tausender
clr pulses3 ; Hunderter
clr pulses2 ; Zehner
clr pulses1 ; Einer
BIN_to_BCD5:
cpi temp, 0x2710 ; mit 10000 vergleichen
brlo BIN_to_BCD4 ; <10000 --> BIN_to_BCD4
subi temp, 0x2710 ; 10000 abziehen
inc pulses5 ; Huderterstelle erhoehen
rjmp BIN_to_BCD5 ; nochmal
BIN_to_BCD4:
cpi temp, 0x03E8 ; mit 1000 vergleichen
brlo BIN_to_BCD3 ; <1000 --> BIN_to_BCD3
subi temp, 0x03E8 ; 1000 abziehen
inc pulses4 ; Huderterstelle erhoehen
rjmp BIN_to_BCD4 ; nochmal
BIN_to_BCD3:
cpi temp, 0x0064 ; mit 100 vergleichen
brlo BIN_to_BCD2 ; <100 --> BIN_to_BCD2
subi temp, 0x0064 ; 100 abziehen
inc pulses3 ; Huderterstelle erhoehen
rjmp BIN_to_BCD3 ; nochmal
BIN_to_BCD2:
cpi temp, 0x000A ; mit 10 vergleichen
brlo BIN_to_BCD1 ; <10 --> BIN_to_BCD1
subi temp, 0x000A ; 10 abziehen
inc pulses2 ; Zehnerstelle erhoehen
rjmp BIN_to_BCD2 ; nochmal
BIN_to_BCD1:
mov pulses1, temp ; den Rest noch in
Einerstelle schieben
ret ; wieder zurueck
Im Ergebnis soll also in jedem pulses1-5-Register eine Stelle der Zahl
stehen. Solange der Eingabewert maximal 0xF ist klappt das auch
wunderbar. Sobald größere Werte konvertiert werden sollen kommt
teilweise nur noch Mist raus. Bei 0x15 wird z. Bsp. 10005 ausgegeben.
Wo liegt mein Denkfehler? Hat jemand einen Tipp?
Moin Uwe,
habe zwar noch keine praktische Erfahrung mit der AVR-Programmierung,
aber ich denke, es liegt am CPI. Die Anweisung lässt nur 8-Bit
Konstanten zu:
CPI Compare with Immediate
Description:
This instruction performs a compare between register Rd and a constant.
The register is not changed. All conditional
branches can be used after this instruction.
Operation:
(i) Rd - K
Syntax: Operands: Program Counter:
(i) CPI Rd,K 16 = d = 31, 0= K = 255 PC ← PC + 1
Mich wundert dann allerdings, dass es überhaupt läuft bzw. sich
kompilieren lässt (grübel). Klär mich mal auf.
Achim.
Hallo Uwe,
ich bin geneigt, Dein Posting als Aprilscherz aufzufassen. Du schreibst
überall von Binär, arbeitest im Programm aber mit Dezimalwert. Falls
das kein Scherz ist, erkläre doch bitte noch einmal, was Du überhaupt
machen möchtest. Meinst Du nun eine Umwandlung von Binär (nur Nullen
und Einsen) nach BCD oder von Dezimal (unser "normales" Zahlensystem)
nach BCD? Und wieviele Stellen soll der Eingangswert maximal haben?
Davon abgesehen, hat Achim natürlich recht. So geht es auf keinen
Fall.
Gruß, Frank
Also ich will folgendes machen:
Ich habe einen Zählerwert in einem Register (temp), z. Bsp. 34567. Den
möchte ich gern in seine einzelnen Zahlen zerlegen, so das jede Stelle
in einem Register steht.
Und nein, es ist kein Aprilscherz. Mir schwirrt nur langsam der Kopf
vor lauter Zahlen und Konvertierungen.
Das cpi und subi nur 8 Bit können hab ich mittlerweile in der
Befehlsreferenz auch rausgefunden und und ebtsprechend auf cp und sub
mit zusätzlicher Variablen geändert.
Aber so langsam dämmerts mir. Irgendwie hab ich wohl den Denkfehler
gehabt, das die Register r16-r31 16-bittig sind, aber es sind ja nur 8
:-( Hab ich wohl mit den Timer-Registern verwürfelt.
Ich werde mich wohl mal ausgiebig mit 16-Bit-Subtraktion befassen
müssen...
Hallo,
"Ich habe einen Zählerwert in einem Register (temp), z. Bsp. 34567."
Ein Register wie temp ist ein Arbeitsregister und hat als maximalen
Wert 255, also 8 bit.
r16 bis r31 sind genauso wie r0 bis r15 alle 8-Bit-Register, denn der
AVR ist ein 8-Bit MC.
R24,25
r26,27
r28,29
R30,31
sind Doppelregiser und eigen sich auch für 16-Bit Operationen. Dies am
besten in der Befehlslisten nochmal genau nachlesen.
Die obersten drei Registerpaare heißen auch X, Y, Z.
GRuß
@Chris: Das sind zwar Doppelregister, aber da bekomme ich Vergleiche mit
cp und Subtraktionen mit sub nicht hin. Wenn ich die Doku richtig
verstanden habe geht das wohl auch nicht mit Doppelregistern.
@Alle: Ich habe es nun anders gelöst (siehe Anhang).
Das Lowbyte wird wie gehabt in Digit 1/2/3 umgesetzt.
Das Highbyte wird bitweise nach rechts geschoben und danach Carry
ausgewertet, wenn Carry gesetzt ist wird per Subroutinen die jeweilige
Wertigkeit des Bits (256, 512, ...) zu den vorhandenen BCD-Werten
byteweise dazuaddiert (also z.Bsp. bei 256: erst 6 zu BCD1, dann 5 zu
BCD2, dann 2 zu BCD3) incl. Beachtung der jeweiligen Overflows >=10.
Ist zwar alles ziemlich aufwendig, code- und rechenintensiv, aber a) es
funktioniert und b) ich begreife es. Wenn ich in ein paar Jahren dann
richtig fit in Assembler bin kann ich es ja nochmal überarbeiten ;-)