Forum: Mikrocontroller und Digitale Elektronik Binär zu BCD Umwandlung mit AVR204 und Atmega8


von Holger M. (schrammel)


Lesenswert?

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

von 2919 (Gast)


Lesenswert?

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. :-)

von peter-neu-ulm (Gast)


Lesenswert?

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.

von Holger M. (schrammel)


Lesenswert?

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

von peter-neu-ulm (Gast)


Angehängte Dateien:

Lesenswert?

Ich versuchs mal, siehe Anhang

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
Noch kein Account? Hier anmelden.