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 ;-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.