Hallo, eine 16bit Binärzahl soll in BCD umgewandelt werden. Dafür gibt es von Atmel die Routine AVR204, die in Assembler so aussieht: ;*********************************************************************** *** ;* ;* "bin2BCD16" - 16-bit Binary to BCD conversion ;* ;* This subroutine converts a 16-bit number (fbinH:fbinL) to a 5-digit ;* packed BCD number represented by 3 bytes (tBCD2:tBCD1:tBCD0). ;* MSD of the 5-digit number is placed in the lowermost nibble of tBCD2. ;* ;* Number of words :25 ;* Number of cycles :751/768 (Min/Max) ;* Low registers used :3 (tBCD0,tBCD1,tBCD2) ;* High registers used :4(fbinL,fbinH,cnt16a,tmp16a) ;* Pointers used :Z ;* ;*********************************************************************** *** ;***** Subroutine Register Variables .equ AtBCD0 =13 ;address of tBCD0 .equ AtBCD2 =15 ;address of tBCD1 .def tBCD0 =r13 ;BCD value digits 1 and 0 .def tBCD1 =r14 ;BCD value digits 3 and 2 .def tBCD2 =r15 ;BCD value digit 4 .def fbinL =r16 ;binary value Low byte .def fbinH =r17 ;binary value High byte .def cnt16a =r18 ;loop counter .def tmp16a =r19 ;temporary value ;***** Code bin2BCD16: ldi cnt16a,16 ;Init loop counter clr tBCD2 ;clear result (3 bytes) clr tBCD1 clr tBCD0 clr ZH ;clear ZH (not needed for AT90Sxx0x) bBCDx_1:lsl fbinL ;shift input value rol fbinH ;through all bytes rol tBCD0 ; rol tBCD1 rol tBCD2 dec cnt16a ;decrement loop counter brne bBCDx_2 ;if counter not zero ret ; return bBCDx_2:ldi r30,AtBCD2+1 ;Z points to result MSB + 1 bBCDx_3: ld tmp16a,-Z ;get (Z) with pre-decrement ;---------------------------------------------------------------- ;For AT90Sxx0x, substitute the above line with: ; ; dec ZL ; ld tmp16a,Z ; ;---------------------------------------------------------------- subi tmp16a,-$03 ;add 0x03 sbrc tmp16a,3 ;if bit 3 not clear st Z,tmp16a ; store back ld tmp16a,Z ;get (Z) subi tmp16a,-$30 ;add 0x30 sbrc tmp16a,7 ;if bit 7 not clear st Z,tmp16a ; store back cpi ZL,AtBCD0 ;done all three? brne bBCDx_3 ;loop again if not rjmp bBCDx_1 ;*********************************************************************** *** Das ganze habe ich auf einen Atmega8 angepasst und die Umwandlung klappt auch fast. Allerdings stehen in den Nibbles nicht nur Werte von null bis neun, sondern Werte von null bis F. Mache ich etwas falsch? Oder steckt in der Routine ein Bug? Holger
Ja, das war dann die Binaer zu Hex Wandlung. Die hat den Vorteil, dass man nur 2 Digits fuer eine Byt braucht, und den Nachteil, dass man als Nicht-embedded-Ingenieur schwer damit klar kommt. Auch Kunden haben damit ihre Muehe. :-)
anscheinend fehlt der Korrekturteil ab subi... , der die Zahlen von A bis F korrigiert. Ist eventuell durch die Bemerkung "For AT90...." dieser Teil stillgelegt worden ? Ich selbst habe diese Routine schon mehrfach benutzt, um die 10 Bit des AD-wandlers dezimal anzuzeigen.
Hallo Peter, genau das ist mein Ziel. Es soll eine 10bit Zahl vom AD-Wandler in eine Dezimalzahl umgewandelt werden, die auf einem LC Display ausgegeben wird. Diese speziellen Anweisungen für den AT90xxx habe ich bereits herausgenommen. Das mit den fehlenden Korrekturroutinen fiel mir auch auf. Aber da der Quelltext direkt von Atmel stammt und für den Zweck bestimmt sei, probierte ich ihn so aus. Immerhin bekommt man ja in jedem Nibble die Werte 0 bis F. Also funktioniert es irgendwie. Nur nicht bis zum Ende... Kannst du deine Variante der Umwandlungsroutine zur Verfügung stellen? Wäre sehr hilfreich. Holger
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.