Ich bitte euch um Hilfe

Dieses Thema im Forum "Allgemeines" wurde erstellt von Ernst, 10. Oktober 2018.

  1. Ernst

    Ernst Mitglied

    Registriert seit:
    4. Oktober 2009
    Beiträge:
    49
    Zustimmungen:
    5
    Punkte für Erfolge:
    8
    Grüßt euch

    Seit dem Tod von meiner Frau kurz vor den letzen Weihnachten habe ich endlich wieder Mut gefunden etwas zu basteln wobei ich aber Hilfe bräuchte. Es geht darum eine Zahl zwischen 0 bis 450 mit dem Atmega 8 durch 16 zu teilen. Ich habe zwar im Net schon etliches gefunden aber keine Anleitung in Assembler die auch Nachkommastellen ausgibt. Vielleicht kann mir jemand helfen.

    Gruß Ernst
     
  2. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Durch sechzehn zu teilen ist für 'nen AVR 'nen Klacks. Einfach viermal nach rechts schieben. Sollen dabei auftretende Nachkommastellen berücksichtigt werden, müssen diese in ein entsprechendes Nachkommabyte gerollt werden. Deine 450 erforden bereits zwei Bytes, sonst könnte man mit "SwapMovDoppelandi" tricksen.
    Aber entweder verstehst Du binäre Nachkommastellen nicht (ganz), oder Du willst das noch irgendwie … wandeln? … ausgeben?

    Wenn nötig, erklär ich später mehr...
     
  3. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Also erstmal grundsätzliches:
    Die AVR arbeiten binär, wenn das Komma nach rechts geschoben wird (bzw die Zahl nach Links) wird verdoppelt, wenn es nach links geschoben wird (bzw die Zahl nach rechts) wird halbiert. Basis Zwei.
    Im Dezimalsystem (Basis Zehn) verzehnfachst/zehntelst Du genauso.
    Wenn Du (analog zu Deinem binären Problem) dezimal die ... Sagen wir 1287651 durch 10000 teilen solltest, würdest Du einfach das Komma vier Stellen nach links schieben (bzw die Zahl selbst viermal eine Stelle nach Rechts).
    Ergäbe 128,7651.
    Was bedeutet das mit den Nachkommastellen nun? Die "7" sind sieben zehntel (also 7*10-1), die "6" sechs hundertstel (also 6*10-2) usw.
    Binär ist es genau dasselbe, nur eben auf Basis Zwei.
    Um durch sechzehn zu teilen, schiebst Du die Zahl viermal nach rechts. Als Beispiel einfach mal die 450dez.
    Wäre binär 111000010
    Komma um vier Stellen verschoben: 11100,0010
    11100binär entspricht 28dezimal.
    und 0,001binär ist "null halbe" plus "null viertel" plus "ein achtel"
    also 11100,0010binär ist 28 und einachtel ... 28,128 dezimal.

    Um ein Byte durch sechzehn zu teilen, müßte also viermal geschoben werden. Das dabei jeweils ins Carry fallende letzte Bit müßte je in ein Nachkommabyte gerollt werden (ignorieren wir mal das neunte Bit):
    11000010 -LSR-> 01100001 Carry=0, ROR->0
    01100001 -LSR-> 00110000 Carry=1, ROR->10
    00110000 -LSR-> 00011000 Carry=0, ROR->010
    00011000 -LSR-> 00001100 Carry=0, ROR->0010
    Erfordert acht Instruktionen. Viermal je ein Shift und ein Rotate. Das neunte Bit bräuchte ein weiters Byte, also je ein weiteres Rotate - zusammen 12 Instruktionen.
    Ok, soweit die stupide Rechnung - jetzt zu den Tricks.
    Nach den vier Shifts/Rotates befinden sich die vier vorher linken Bits rechts im selben Byte, und die vier vorher rechten links in einem anderen Byte.
    Der AVR kann die Nibbles eines Bytes mit einer Instruktion tauschen - SWAP
    Aus 11000010 wird 00101100.
    Das wird in das Nachkommabyte kopiert (MOV)
    Also 00101100 00101100.
    Jetzt werden im Vorkommabyte die ersten vier, und im Nachkommabyte die letzten vier Bits wegmaskiert. Je mit ANDI.
    Ergibt 0000110 00100000.
    Fertig nach vier (statt acht) Instruktionen.

    Ok, und mit neun Bits (bis max 12 Bits)?


    CodeBox Assembler
    ;verwendet werden drei Register HByte, Lbyte und Nachkommabyte
    SWAP Lbyte ;Nibbles tauschen
    MOV Nachkommabyte, Lbyte ;Kopieren
    ANDI Nachkommabyte, 0xF0 ;unteres Nibble im Nachkommabyte löschen
    ANDI Lbyte, 0x0F ;dito oberes Nibble im Lbyte
    SWAP Hbyte ;unteres Nibble nach oben tauschen
    ADD Lbyte, Hbyte ;und auf Lbyte addieren

    Fertig nach sechs (statt zwölf) Instruktionen.

    Was meintest Du jetzt mit "ausgeben"?
     
  4. Ernst

    Ernst Mitglied

    Registriert seit:
    4. Oktober 2009
    Beiträge:
    49
    Zustimmungen:
    5
    Punkte für Erfolge:
    8
    Grüßt euch
    Einen herzlichen Dank für die Hilfe die hat mir geholfen.
    Gruß Ernst
     
  5. Ernst

    Ernst Mitglied

    Registriert seit:
    4. Oktober 2009
    Beiträge:
    49
    Zustimmungen:
    5
    Punkte für Erfolge:
    8
    Grüßt euch
    Einen herzlichen Dank für die Hilfe es klappt so wie ich wollte.
    Mit Ausgeben meinte ich das die Zahlen auf einen 2 X 16 Display angezeigt werden.
    Gruß Ernst
     
  6. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    3.009
    Zustimmungen:
    51
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Nach der Code-Box aus #3 hast Du ein Byte mit dem Vorkomma-Anteil und eins mit dem Nachkomma-Anteil. Binär.
    Du kannst die natürlich auch als Byte darstellen - vermutlich willst Du sie aber dezimal darstellen. Also mußt Du sie einerseits stellenweise in eine Dezimalzahl überführen, und dann in die entsprechende ASCII, die Du an das alphanumerische (?) Display senden kannst. zwischen den beiden Bytes schummelst Du das Komma.

    Zum Vorkomma-Byte:
    Nach der Division durch sechzehn kannst Du höchstens 28,125 haben, also 28 im Vorkomma-Byte.
    Theoretisch müßtest Du durch zehn teilen, um die Zehner zu erhalten (28 / 10 = 2). Ist die Divisionsroutine effizient, liefert sie Dir nebenbei den Rest, mit dem Du weitere Dezimalstellen gewinnen kannst. Da es hier nur noch die Einer wären (8), wärst Du fertig. Ist die Divisionsroutine weniger effizient, könntest Du den Rest mittels Modulo-Division berechnen (28 Mod 10 = 8).

    In der Praxis würde man in einer Schleife sooft zehn subtrahieren, bis der Rest kleiner Zehn wird. "Sooft" wären dann die Zehner, Der Rest die Einer.
    Damit hättest Du den Vorkommaanteil in seine Dezimalstellen zerhackt - Binary Coded Digits.
    Und wie machst Du da ASCIIs draus?
    Indem Du einfach 'ne ASCII-Null (0x30) draufaddierst. Oder noch besser: "Sooft" vor dem Zählen mit 0x30 initialisierst, und dann eben jedesmal, wenn Du vom Dividenten zehn abziehen kannst "sooft" inkrementierst.

    Du hast also "Zehner" und "Einer" gesendet, anschließend noch das Komma (0x2C).

    Nun der Nachkommaanteil:
    Theoretisch könntest Du hier ebenso versuchen "zehntel", "hundertstel" usw abzuziehen - allerdings wirst Du feststellen, daß diese sich mit einem Byte nicht darstellen lassen.

    Aber Du kannst das Nachkommabyte einfach mit Zehn multiplizieren. Zehn entspricht &B00001010 - also nur zwei Einsen drin. Du mußt also das mit zehn zu multiplizierende Byte einmal nach links schieben (16bit), in zwei Register kopieren, dann noch zweimal linksschieben, und draufaddieren. Das höherwertige Register enthält danach das Zehnfache, also die "Zehntel" als Dezimalstelle, das andere den Rest. Wenn Du mit dem das ganze wiederholst, erhälst Du die hundertstel usw. Addierst Du auf das höhere Register 0x30, steht da wieder der entsprechende ASCII, den Du an Dein Display senden kannst.

    Bei 'nem Mega-Controller kannst Du natürlich auch den Multiplikationsbefehl nutzen.

    Wie sieht Deine Lösung aus?

    P.S.: Bei Deinem konkreten Fall (max 450, wobei das Low-Nibble den Nachkomma-Anteil stellt (also 1/16 entspricht)) kann man das Bit-Geschubse natürlich noch deutlich … optimieren, denk ich.
    Bin noch dran...
     
    #6 LotadaC, 14. Oktober 2018
    Zuletzt bearbeitet: 14. Oktober 2018
  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren und die Seite optimal für dich anzupassen. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden