Bitmanipulation – Invertieren, UND- und ODER Verknüpfungen

Das GREETBoard Projekt schreitet langsam voran und die Dinge, die ich mit dem AVR ATMega32 machen kann, werden in Zukunft komplexer. Vor allem die Arbeit mit dem Portexpander Modul (PCF8574) verlangt langsam aber sicher nach Kenntnissen über die Bitmanipulation. Allein das Wort “Bitmanipulation” hat mich bisher abgeschreckt, aber für die kommenden Aufgaben, blieb mir nichts anderes übrig, als mich in diese Materie einzulesen. Dabei hat mir die Seite von Mikrocontroller.net sehr geholfen.

Grundsätzlich geht es einfach und allein darum, Bits, bzw. Bitmuster durch bestimmte Verknüpfungen zu verändern. Dabei werden zwei Bitmuster miteinander kombiniert, so dass als Ergebnis ein anderes Bitmuster herauskommt. Angenommen, es handelt sich um ein 8-Bitmuster, dann werden die beiden Muster Bit für Bit miteinander kombiniert. Also zuerst Bit 0 des ersten Bitmusters mit dem Bit 0 des zweiten Bitmusters, usw. Die nächsten Beispiele beleuchten dies genauer.

Die UND Verknüpfung

Bei dieser Operation werden zwei Bitmuster derart kombiniert, dass wenn beide Bits 1 sind, das Ergebnis auch 1 ist und nur dann. Ist Bit 2 des ersten Bitmusters = 1 UND Bit 2 des zweiten Bitmusters =1, dann ist das Bit 2 des Ergebnis-Bitmusters auch = 1. Der Operator für diese Verknüpfung ist das: &

Beispiel:

  1001 1100 (Bitmuster1)
& 1010 0111 (Bitmuster2)
= 1000 0100

Wie man sieht, haben die beiden Bitmuster nur bei zwei Bits jeweils eine 1 stehen. Und nur in diesem Fall wird auch das Ergebnis an diesem Bit eine 1 haben.

Als C-Befehle würde dies wie folgt aussehen:

Variante 1)  Ergebnis = Bitmuster1 & Bitmuster2;
Variante 2)  A &= Bitmuster2;

Variante 1 führt die UND Verknüpfung durch und speichert das Ergebnis in der Variable Ergebnis. Die andere Variante Verknüpft die Variable A mit dem Bitmuster2 und speichert das Ergebnis gleich wieder in der Variable A.

Die ODER Verknüpfung

Die Bedingung der ODER Verknüpfung lautet, es muss entweder das eine ODER das andere Bit gesetzt sein. Ist Bit 2 des ersten Bitmusters = 1 ODER Bit 2 des zweiten Bitmusters =1, dann ist das Bit 2 des Ergebnis-Bitmusters auch = 1. Der Operator für diese Verknüpfung ist das: |

Beispiel:

  1001 1100 (Bitmuster1)
& 1010 0111 (Bitmuster2)
= 1011 1111

Als C-Befehle würde dies wie folgt aussehen:

Variante 1)  Ergebnis = Bitmuster1 | Bitmuster2;
Variante 2)  A |= Bitmuster2;

Variante 1 führt die ODER Verknüpfung durch und speichert das Ergebnis in der Variable Ergebnis. Die andere Variante Verknüpft die Variable A mit dem Bitmuster2 und speichert das Ergebnis gleich wieder in der Variable A.

Invertieren

Das ein oder andere Mal kann es nützlich sein, den Zustand der Bits eines Bitmusters umzukehren. Dadurch werden Bits mit dem Wert 0 zu 1 und anders herum. Der Operator für diese Aktion ist das ~

~ 1001 1100
= 0110 0011

Der entsprechende C-Befehl lautet:

Bitmuster1 = ~Bitmuster1

Dies invertiert das Bitmuster1 und speichert es unter dem gleichen Bitmuster-Namen ab

 

Eine bessere Schreibweise

Die oben dargestellte Schreibweise funktioniert sehr gut und ist auch nicht falsch. Für eine etwas bessere Übersichtlichkeit wird jedoch eine etwas andere Schreibweise empfohlen.

Die bessere UND Verknüpfung

Angenommen alle Bits, außer Bit 1 und Bit 5 in einem 8-Bitmuster (A) sollen auf o gesetzt werden, dann würde ich dafür eine UND Verknüpfung nutzen. Also:

A &= 0x22;   //0x22 => 00100010

Es ist jedoch auch möglich, jedes einzelne zu manipulierende Bit separat anzugeben. Dafür wird der Operator << herangezogen, der das zu manipulierende Bit im Muster um n Stellen verschiebt (1 << n).  Ich versuche es an einem Beispiel zu erklären.

A &= (      Bitmuster      );
A &= ( (1 << 1) | (1 << 5) );

Innerhalb der äußeren Klammern wird das Bitmuster erzeugt, mit dem A manipuliert werden soll. Dazu wird mit der ersten inneren Klammer die erste „1“ auf Stelle eins, im zu erstellenden Bitmuster, verschoben (0000 0010). Die zweite innere Klammer ist mit der ersten UND verknüpft und sie schiebt eine weitere 1 auf Bits fünf (0010 0010 = 0x22). Dieses so erstellte Bitmuster wird dann zur UND Verknüpfung benutzt.

Die bessere ODER Verknüpfung

Auch hier ist die weiter oben erklärte Schreibweise möglich, sie kann aber ebenfalls übersichtlicher gestaltet werden.

A |= (      Bitmuster      );
A |= ( (1 << 1) | (1 << 5) );

Auch hier wird innerhalb der äußeren Klammern das Bitmuster erzeugt, dass zur Manipulation dienen soll. Und wieder wird dieses Muster mit einer 1 bei Bit 1 und Bit 5 „geladen“ (0010 0010).

Wird diese Schreibart beim Setzen und Löschen von Ports herangezogen, dann wird anstatt n eine Abkürzung für den Pin benutzt. Soll also Pin B2 gesetzt werden, dann wird dies folgendermaßen gemacht

PortB |= ( (1 << PB2 );

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.