![]() |
![]() |
C++ - Bitfelder (1) |
G.Eichelsdörfer - Staatliche Technikerschule Weilburg |
Es gibt viele Szenarien, in denen es wichtig ist, Informationen so kompakt wie möglich zusammenzustellen. Solche Szenarien sind:
Übertragung von Daten in einem Netzwerk
Um die benötigte Bandbreite möglichst klein zu halten, sollten Informationen möglichst
ohne Redundanz übertragen werden. Redundanz ist nur für Fehlererkennung oder Verschlüsselung
zweckmäßig. Deshalb ist es besser Daten mit unüblichen Wortbreiten in Standard-Wortbreiten
aufzuteilen.
Beispiel:
Sie erfassen Messwerte aus 6 Bit. In der lokalen Verarbeitung ist es effizient,
alle diese Werte in üblichen Variablen (short, int, long, floart, double) zu speichern.
Für die Übertragung ist es jedoch besser, die Werte in Oktetts (8 Bit-Gruppen) unterzubringen.
So können beispielsweise vier Messwerte in drei Oktetts untergebracht werden.
Protokollinformationen bei der Datenübertragung
Die Protokollinformationen bestehen mitunter aus nur einem oder zwei Bits.
Dafür sollten keine 8 oder mehr Bit verschwendet werden.
Deshalb werden mehrere solcher Bitgruppen in Oktetts zusammengefasst.
Steuern und Regeln
Wenn Daten über eine Schnittstelle eingelesen und gegebenenfalls Steuerdaten ausgegeben
werden, so geschieht dies zumeist über parallele Ports (vgl. mit SPS). Über ein Port können
mehrere Sensoren Daten liefern oder mehrere Aktoren angesteuert werden.
Hier liegen häufig kleinere Wortbreiten vor. Mehrere Sensoren/Aktoren teilen sich dann
ein oder mehrere Ports.
In allen solchen Fällen ist es hilfreich so genannte Bitfelder verwenden zu können. In Bitfeldern können gerade so viele Bits reserviert werden wie tatsächlich benötigt werden.
Wie kann man ein Bitfeld deklarieren?
Bitfelder sind immer Komponenten von Verbunden (Structs). Es folgt die Beschreibung der Vorgehensweise, gezeigt an einem Beispiel zur zweidimensionalen Positionierung eines Werkstücks.
Legen Sie einen Verbund an!
struct Pos // Daten zur Positionierung
{};
Entscheiden Sie sich für einen dem Bitfeld zu Grunde zu legenden Datentyp. Dazu sind
ganzzahlige Datentypen wie (unsigned) char, short, int, long geeignet.
In den meisten Fällen ist der Typ unsigned int zweckmäßig, weil damit
keine Probleme mit dem Vorzeichen auftreten können, welches im höchstwertigen Bit
(MSB = most significant bit) abgelegt ist.
In der folgenden Komponente wird jedoch nur ein einziges binäres Signal verwertet,
welches die Information liefert, ob der Referenzpunkt-Sensor erreicht ist (oder nicht).
Dafür ist bool
ein gut geeigneter Typ.
struct Pos // Daten zur Positionierung
{
bool // für das Signal des Referenzpunkt-Sensors in X-Richtung
};
Nun geben Sie der einzutragenden Komponente einen passenden Namen.
struct Pos
{
bool RefX // Sensorsignal am Referenzpunkt
};
Hinter dem Komponentennamen tragen Sie einen Doppelpunkt ein, gefolgt von der Anzahl an
erforderlichen Bits. Schließen Sie die Komponente mit einem Semikolon ab!
struct Pos
{
bool RefX : 1;
};
Nun ist sicher gestellt, das für das Referenzpunktsignal nur ein Bit reserviert wird.
In Y-Richtung gibt es auch einen Referenz-Sensor. Dafür legen Sie eine weitere Komponente
wie oben an.
struct Pos
{
bool RefX : 1;
bool RefY : 1;
};
Bisher wurden im Structtyp Pos genau zwei Bits verbraucht.
Komponenten können auch Wortbreiten von mehreren Bits aufweisen.
Angenommen Sie wollen die 12 Ausgangbits eines Analog-Digital-Umsetzers
(ADU) an einem 16 Bit breiten Port einlesen. Dann legen Sie die Komponente ADU wie folgt fest:
unsigned int ADU : 12;
Falls eine Komponente vom Typ int
mit einem Bit eingesetzt wird,
ist zu beachten, dass dafür die werte 0 und -1 zur Verfügung stehen.
Grund: Das einzige Bit ist zugleich das Vorzeichenbit. Darin bedeutet eine 1,
dass der Wert negativ ist.