Binär zu BCD Wandlung

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Binär zu BCD Wandlung

      Hallo Zusammen,

      es gibt ja den Befehl MAKEBCD() und BCD(). Allerdings kann ich damit nicht ohne weiteres z.B. einen INTEGER Wert, z.B. 120, in dessen BCD-Wert wandeln. Jetzt habe ich mir ein bissel was zusammengezimmert, bin aber nicht sicher ob ich das so brauche. Die Anforderung wäre, Integer als Übergabewert und ein DWord zurück. Mit DWord bekommt man 8 Stellen untergebracht - das wäre dann gepacktes BCD-Format.

      Gibt es bereits in BASCOM verfügbare Wege die ich nicht kenne?

      Danke Euch,

      Uwe
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Hab es jetzt so gelöst, ist aber langsam:

      BASCOM-Quellcode

      1. FUNCTION Bin2BCD(ByRef hexVal As Integer) As DWord
      2. Bin2BCD = 0
      3. WHILE hexVal >=10000
      4. hexVal=hexVal - 10000
      5. Bin2BCD = Bin2BCD + &H10000
      6. WEND
      7. WHILE hexVal >=1000
      8. hexVal=hexVal - 1000
      9. Bin2BCD = Bin2BCD + &H1000
      10. WEND
      11. WHILE hexVal >=100
      12. hexVal=hexVal - 100
      13. Bin2BCD = Bin2BCD + &H100
      14. WEND
      15. WHILE hexVal >=10
      16. hexVal=hexVal - 10
      17. Bin2BCD = Bin2BCD + &H10
      18. WEND
      19. WHILE hexVal >=10
      20. hexVal=hexVal - 10
      21. Bin2BCD = Bin2BCD + &H10
      22. WEND
      23. Bin2BCD = Bin2BCD + hexVal
      24. END FUNCTION
      Alles anzeigen
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Statt While-Schleifen kannst du auch teilen und hast dann direkt die Ziffer.
      Dann mit Mod und Teilen weiter:


      BASCOM-Quellcode

      1. $regfile = "m16def.dat"
      2. $crystal = 8000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 32
      6. Dim Wert As Word
      7. Dim Erg As Dword
      8. Dim Temp As Word
      9. Wert = 65432
      10. Temp = Wert / 10000
      11. Erg = Temp * 65536
      12. Temp = Wert Mod 10000
      13. Temp = Temp / 1000
      14. Temp = Temp * 4096
      15. Erg = Erg + Temp
      16. Temp = Wert Mod 1000
      17. Temp = Temp / 100
      18. Temp = Temp * 256
      19. Erg = Erg + Temp
      20. Temp = Wert Mod 100
      21. Temp = Temp / 10
      22. Temp = Temp * 16
      23. Erg = Erg + Temp
      24. Temp = Wert Mod 10
      25. Erg = Erg + Temp
      26. Print Hex(erg)
      Alles anzeigen

      monkye schrieb:

      Die Anforderung wäre, Integer als Übergabewert und ein DWord zurück. Mit DWord bekommt man 8 Stellen untergebracht - das wäre dann gepacktes BCD-Format.
      mich würde mal dein Problem interessieren. Ich glaube nämlich, dass du den falschen Ansatz hast (Kanonen/Spatzen) ;)
    • > mich würde mal dein Problem interessieren. Ich glaube nämlich, dass du den falschen Ansatz hast (Kanonen/Spatzen)

      @Michael, wie kommst Du zu Deinem Glauben?

      Die Aufgabe besteht darin, eine ganze Reihe von Messwerten im BCD Format per LaCrosse Protokoll via Funk zu übertragen. Diese Messwerte liegen im Zahlenbereich (Integer) -200....35000.
      Zum einen soll Flash gespart werden, deshalb der Verzicht auf Divisionen, zu langsam soll es auch nicht sein. Aktuell noch nicht zeitkritisch.

      Verständlich geworden?
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • monkye schrieb:

      Verständlich geworden?
      nein. Aber ich werf mal Google an.

      Lacrosse ist laut Google eine Sportart, hier hätte eine Erklärung sicher geholfen, ich hole das mal nach:
      fredboboss.free.fr/articles/tx29.php/

      monkye schrieb:

      Zum einen soll Flash gespart werden, deshalb der Verzicht auf Divisionen, zu langsam soll es auch nicht sein. Aktuell noch nicht zeitkritisch.
      Ich denke nicht, dass das einen großen Unterschied beim Flash-Verbrauch macht.
      Programmier doch mal ein einfaches Stück, so wie mein Beispiel in #6, da können wir das sehen.
      Ich kenne auch keine bezahlbaren Temperatursensoren, bei denen die Geschwindigkeit eine Rolle spielen würde. So eine Berechnung ist eigentlich lange fertig, bevor die Temperatur sich merklich ändert.

      P.S.:

      monkye schrieb:

      wie kommst Du zu Deinem Glauben?
      Aus der Fülle der Möglichkeiten, die ich sehe und aus der Erfahrung heraus, wie Einsteiger Probleme zu lösen versuchen ;)
    • Michael schrieb:

      Ich kenne auch keine bezahlbaren Temperatursensoren, bei denen die Geschwindigkeit eine Rolle spielen würde. So eine Berechnung ist eigentlich lange fertig, bevor die Temperatur sich merklich ändert.

      P.S.:

      Es geht nicht nur um Temperaturen, dazu Kontakte, Luftdruck. Zudem arbeite ich mit Sensoren die auch "hören", also auf Anforderung senden.

      Für das LaCrosse Protokoll habe ich Dir mal diesen Link beigefügt: f6fbb.org/domo/sensors/
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Pluto25 schrieb:

      So langsam ist es nicht (377 Clocks) Michael s Version braucht da über 3200
      Ich habe das jetzt mal in 2 vergleichbare Codestücke eingepflegt.
      Die Varianten unterscheiden sich nicht so stark, wie man denkt, beides hat Vor- und Nachteile.
      Die While-Wend Version benötigt 2473 Takte , die Mod-Division braucht 2657 Takte jeweils für den Durchlauf der Loop.
      Das kann jeder selber im Simulator prüfen, deshalb häng ich das unten an.

      Der Taktbedarf steigt mit größer werdender Zahl, einfach weil mehr While-Schleifen durchgeführt werden müssen, die Division ist da recht konstant, egal wie groß die Zahl.
      Der Flashbedarf ist etwa 1/4 weniger mit 758 zu 980.

      BASCOM-Quellcode: While-Wend

      1. $regfile = "m16def.dat"
      2. $crystal = 8000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 32
      6. $sim
      7. Dim Bin2bcd As Dword
      8. Dim Wert As Word
      9. Do
      10. Wert = 59999
      11. Bin2bcd = 0
      12. While Wert >= 10000
      13. Wert = Wert - 10000
      14. Bin2bcd = Bin2bcd + &H10000
      15. Wend
      16. While Wert >= 1000
      17. Wert = Wert - 1000
      18. Bin2bcd = Bin2bcd + &H1000
      19. Wend
      20. While Wert >= 100
      21. Wert = Wert - 100
      22. Bin2bcd = Bin2bcd + &H100
      23. Wend
      24. While Wert >= 10
      25. Wert = Wert - 10
      26. Bin2bcd = Bin2bcd + &H10
      27. Wend
      28. While Wert >= 10
      29. Wert = Wert - 1
      30. Bin2bcd = Bin2bcd + 1
      31. Wend
      32. Bin2bcd = Bin2bcd + Wert
      33. Print Hex(bin2bcd)
      34. Loop
      Alles anzeigen


      BASCOM-Quellcode: Mod-Division

      1. $regfile = "m16def.dat"
      2. $crystal = 8000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 32
      6. Dim Wert As Word
      7. Dim Erg As Dword
      8. Dim Temp As Word
      9. Do
      10. Wert = 59999
      11. Temp = Wert / 10000
      12. Erg = Temp * 65536
      13. Temp = Wert Mod 10000
      14. Temp = Temp / 1000
      15. Temp = Temp * 4096
      16. Erg = Erg + Temp
      17. Temp = Wert Mod 1000
      18. Temp = Temp / 100
      19. Temp = Temp * 256
      20. Erg = Erg + Temp
      21. Temp = Wert Mod 100
      22. Temp = Temp / 10
      23. Temp = Temp * 16
      24. Erg = Erg + Temp
      25. Temp = Wert Mod 10
      26. Erg = Erg + Temp
      27. Print Hex(erg)
      28. Loop
      Alles anzeigen
    • Es geht doch noch schneller und mit weniger Flash.

      610 Bytes mit einer Taktanzahl von 1577 pro Durchlauf.

      BASCOM-Quellcode: Mod-Makebcd-Overlay

      1. $regfile = "m16def.dat"
      2. $crystal = 8000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 32
      6. $sim
      7. Dim Wert As Word
      8. Dim Erg As Dword
      9. Dim Tbyte(4) As Byte At Erg Overlay
      10. Dim Temp As Word
      11. Do
      12. Wert = 59999
      13. Temp = Wert / 10000
      14. Tbyte(3) = Temp
      15. Temp = Wert Mod 10000
      16. Temp = Temp / 100
      17. Tbyte(2) = Makebcd(temp)
      18. Temp = Wert Mod 100
      19. Tbyte(1) = Makebcd(temp)
      20. Print Hex(erg)
      21. Loop
      Alles anzeigen
    • Klasse, da kann nicht nur ich partizipieren. Da habe ich wohl den Sportsgeist geweckt

      Habe gestern schon eine stark optimierte Variante von Peter Dannegger im MC-Forum entdeckt. Ist quasi handgestrickt in ASM.

      Jetzt ist mir noch die AVR204 über den Weg gelaufen, die auch stark optimiert ist und zwei Formen bietet, einmal Flash- und einmal Speed-optimiert.

      Mal gucken ob noch alles in den ATTINY85 passt. Es kommen BMP180, DHT22 und ein Display zum Einsatz. Der Sender wird nur bei Bedarf zugeschaltet. Ein Pin bleibt noch für einen Reedkontakt oder Hallsensor.
      Aus datenschutzrechtlichen Gründen befindet sich die Kontaktdaten auf der Rückseite dieses Beitrages.
    • Hallo monkye,
      ich habe auch noch mal etwas rumgespielt und versucht, bzgl Speicherplatz und Speed was rauszuholen.
      Ist für den Attiny85. Da der auch noch 3 GPIO Register hat, habe ich in der schnellsten Variante die auch eingesetzt.

      BASCOM-Quellcode

      1. 'need_for_speed=0, use_gpior=0 378 Byte flash, 900 Takte
      2. 'need_for_speed=0, use_gpior=1 346 Byte flash, 781 Takte
      3. 'need_for_speed=1, use_gpior=0 692 Byte flash, 472 Takte
      4. 'need_for_speed=1, use_gpior=1 632 Byte flash, 421 Takte
      5. $regfile = "attiny85.dat"
      6. $crystal = 8000000
      7. $hwstack = 64
      8. $swstack = 32
      9. $framesize = 32
      10. $sim
      11. Const Need_for_speed = 1
      12. Const Use_gpior = 1
      13. Dim Wert As Word
      14. #if Use_gpior = 1
      15. Tbyte3 Alias Gpior2
      16. Tbyte2 Alias Gpior1
      17. Tbyte1 Alias Gpior0
      18. #else
      19. Dim Tbyte3 As Byte
      20. Dim Tbyte2 As Byte
      21. Dim Tbyte1 As Byte
      22. #endif
      23. Dim Temp As Word
      24. Dim Tempb As Byte At Temp Overlay
      25. Wert = 59999
      26. Do
      27. Temp = Wert
      28. Tbyte1 = 0
      29. Tbyte2 = 0
      30. Tbyte3 = 0
      31. #if Need_for_speed = 1
      32. While Temp >= 40000
      33. Temp = Temp - 40000
      34. Tbyte3 = Tbyte3 + 4
      35. Wend
      36. While Temp >= 20000
      37. Temp = Temp - 20000
      38. Tbyte3 = Tbyte3 + 2
      39. Wend
      40. #endif
      41. While Temp >= 10000
      42. Temp = Temp - 10000
      43. Incr Tbyte3
      44. Wend
      45. #if Need_for_speed = 1
      46. While Temp >= 4000
      47. Temp = Temp - 4000
      48. Tbyte2 = Tbyte2 + 64
      49. Wend
      50. While Temp >= 2000
      51. Temp = Temp - 2000
      52. Tbyte2 = Tbyte2 + 32
      53. Wend
      54. #endif
      55. While Temp >= 1000
      56. Temp = Temp - 1000
      57. Tbyte2 = Tbyte2 + 16
      58. Wend
      59. #if Need_for_speed = 1
      60. While Temp >= 400
      61. Temp = Temp - 400
      62. Tbyte2 = Tbyte2 + 4
      63. Wend
      64. #endif
      65. While Temp >= 200
      66. Temp = Temp - 200
      67. Tbyte2 = Tbyte2 + 2
      68. Wend
      69. While Tempb >= 100
      70. Tempb = Tempb - 100
      71. Incr Tbyte2
      72. Wend
      73. #if Need_for_speed = 1
      74. While Tempb >= 40
      75. Tempb = Tempb - 40
      76. Tbyte1 = Tbyte1 + 64
      77. Wend
      78. While Tempb >= 20
      79. Tempb = Tempb - 20
      80. Tbyte1 = Tbyte1 + 32
      81. Wend
      82. #endif
      83. While Tempb >= 10
      84. Tempb = Tempb - 10
      85. Tbyte1 = Tbyte1 + 16
      86. Wend
      87. Tbyte1 = Tbyte1 + Tempb
      88. Loop
      89. End
      Alles anzeigen
    • Nun denn, hier mein Beitrag. Mehr gibt's aber heute nicht mehr um diese Zeit. Und ja, das Ergebnis ist ein Dword a_168_f7ffb399

      Ich habe mal den Shift und addiere 3 Algorithums implementiert, den habe ich auch noch nicht versucht und fand ihn eine nette und vor allen Dingen kompakte Alternative. Auch wenn er nicht der Schnellste ist.
      Das Ergebnis ist ganz okay. Gepackt in eine Funktion, bringt es der Code vom Aufruf bis zur Rückehr stets auf 510 Takte. Würde man noch auf die Funktionsvewaltung verzichten und Blödsinn anstellen, wie z.B. die Iteration zu halbieren, gingen da sicher auch noch einige Takte ab. Vielleicht fällt mir ja auch morgen noch mehr Potential auf, ist ja immer so.


      222 bytes ROM 510 cycles

      BASCOM-Quellcode

      1. $regfile = "attiny85.dat"
      2. $crystal = 8000000
      3. $hwstack = 64
      4. $swstack = 32
      5. $framesize = 32
      6. declare function uint2bcd(byreg r16 as word) as dword
      7. dim Temp as integer
      8. dim dw as dword
      9. temp = 12057
      10. dw = uint2bcd (temp)
      11. 'print hex(dw)
      12. end
      13. function uint2bcd(byreg r16 as word) as dword
      14. $asm
      15. ldi R25,16
      16. clr R20
      17. Clr R21
      18. Clr R22
      19. rjmp uint2bcd_1
      20. uint2bcd_loop:
      21. MOV R24,R20
      22. Andi R20,&H0F
      23. Andi R24,&HF0
      24. CPI R20, 5
      25. BRLO +2
      26. SUBI R20,-3
      27. CPI R24, 80
      28. BRLO +2
      29. SUBI R24,-48
      30. OR R20,R24
      31. MOV R24,R21
      32. Andi R21,&H0F
      33. Andi R24,&HF0
      34. CPI R21, 5
      35. BRLO +2
      36. SUBI R21,-3
      37. CPI R24, 80
      38. BRLO +2
      39. SUBI R24,-48
      40. OR R21,R24
      41. CPI R22,5
      42. BRLO +2
      43. SUBI R22,-3
      44. uint2bcd_1:
      45. lsl R16
      46. Rol R17
      47. rol R20
      48. rol R21
      49. ROl R22
      50. dec r25
      51. brne uint2bcd_loop
      52. uint2bcd_exit:
      53. ldd r26 , y + 0
      54. ldd r27 , y + 1
      55. ST X+,R20
      56. ST X+,R21
      57. ST X+, R22
      58. clr R20
      59. St X, R20
      60. $end asm
      61. end function
      Alles anzeigen