Wie erstelle ich einen Nullen- und Einsenzähler?

Ich versuche, mit dem AVR ATmega328P einen Nullen- und Einsenzähler in Assembler zu schreiben.

Um zwischen den Einsen und Nullen zu wählen, habe ich einen Schalter in PC5.

Für den Eingang gibt es 8 Schalter, die mit PORTB und einer mit einem Pin in PORTC verbunden sind.

Die Bits sind so:

  • PC1 (höchstwertiges Bit)
  • PB7
  • ... PB0(niederwertigstes Bit)

Für die Ausgabe muss ich die Nullen oder die Einsen auf eine 7-Segment-Anzeige schicken.

Ignoriere SW2

Ich versuche, PORTB zu lesen, verwende eine Maske (ANDI), um das niedrigstwertige Bit zu erhalten, vergleiche, ob es eins oder niedriger (Null) ist, füge eins zu einem Register hinzu, je nachdem, ob es Null oder eins zu einem anderen Register ist, wenn es eins ist, verschiebe das Eintrag (LSR), um die Überprüfung fortzusetzen, und so weiter.

Das Auslesen des Steuerschalters und das Drucken der Anzeige sind kein Problem, aber ich fand einige Umstände, wo es etwas kompliziert wird. Wie kann man zum Beispiel in einem Register den Wert von PORTB und den Pin in PORTC verketten?

Ich versuche, einen Zyklus zu verwenden, und irgendwann müsste ich prüfen, ob ich bereits die 9 Bits habe und sie die Zählung senden, sollte ich einen Zähler verwenden?

Ich hatte nach einfacheren Möglichkeiten gesucht, dieses Problem zu implementieren, aber keine relevanten Informationen gefunden.

Begin:
    IN R23, PINB
Jump:
    ANDI R23, 0x01
    CPI R23,0x01
    BRLO Zero
    BREQ One
Shift:
    IN R23, PINB
    LSR R23
    RJMP Jump
Zero:
    INC R18
    INC R16 //counter??
    RJMP Shift
One:
    INC R17
    INC R16//counter??
    RJMP Shift

Die Gegenidee ist nicht abgeschlossen, nur ein Beispiel, wo die Verwirklichung wäre. Für den Zähler (INC R16) fehlt mir auch das Bit in PC0. Ich konnte nach dem Lesen von PORTB lesen, aber ich habe versucht, eine elegantere Implementierung zu verwenden. Ich weiß, dass ich am Anfang den Zähler überprüfen muss, um zu sehen, ob es fertig ist, und die Ausgabe senden muss, wenn dies der Fall ist.

Vielen Dank für die Hilfe. (:

Antworten (3)

Das LSB zu untersuchen, es als 0 oder 1 zu klassifizieren, dann eins nach rechts zu verschieben und zum nächsten Bit zu wechseln, klingt nach einer vernünftigen Strategie. Es ist nicht klar, woran Sie genau festhalten, aber Ihr grundlegender Ansatz macht Sinn.

Eine andere Möglichkeit, dies zu tun, wenn die Geschwindigkeit sehr wichtig wäre, besteht darin, die 8 Bits als Index in einer Tabelle zu verwenden, die Ihnen dann explizit sagt, wie viele Nullen und wie viele Einsen im Byte enthalten sind. Eigentlich muss es Ihnen nur einen davon sagen. Der andere ist 8-N.

Wenn man einen Bytewert b hat, kann man schnell die Anzahl der gesetzten Bits mit der folgenden Strategie zählen:

  1. Beginnen Sie mit b = ((b & 0xAA)>1) + (b & 0xAA);. Die Bits 6–7 von bhalten nun einen Zwei-Bit-Wert, der die Anzahl der gesetzten Bits in {6,7} enthält, die gesetzt wurden; Bits 4-5 geben an, wie viele Bits in {4,5} gesetzt wurden usw.
  2. Dann durchführen b = ((b & 0xCC)>>2) + (b & 0x33);. Die Bits 4-7 von benthalten nun einen Vier-Bit-Wert, der die Anzahl der gesetzten Bits in {4,5,6,7} enthält, und die Bits 0-3 enthalten einen Vier-Bit-Wert, der die Anzahl der gesetzten Bits in { enthält. 0,1,2,3}.
  3. Schließlich enthält b = (b >> 4) + (b & 0x0F).Now bdie Gesamtzahl der gesetzten Bits.

Der Ansatz ist auch für 16-Bit- oder 32-Bit-Mengen geeignet; bei 16-Bit-Mengen sind vier Schritte erforderlich, bei 32-Bit-Mengen fünf.

Sie haben nicht genug Ruf, um einen Kommentar abzugeben. Aber könnten Sie einfach alle Eingaben summieren, wird das Ergebnis eine Anzahl von Einsen sein.