Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial Internet of Things >> Eingebettet

Union in C-Sprache zum Packen und Entpacken von Daten

Informationen zum Packen und Entpacken von Daten mit Unions in der Sprache C.

Erfahren Sie mehr über das Packen und Entpacken von Daten mit Unions in der Sprache C.

In einem früheren Artikel haben wir besprochen, dass die ursprüngliche Anwendung von Unions einen gemeinsamen Speicherbereich für sich gegenseitig ausschließende Variablen erstellt hatte. Im Laufe der Zeit haben die Programmierer Unions jedoch häufig für eine ganz andere Anwendung verwendet:das Extrahieren kleinerer Datenteile aus einem größeren Datenobjekt. In diesem Artikel werden wir uns diese spezielle Anwendung von Gewerkschaften genauer ansehen.

Verwendung von Verbindungen zum Verpacken/Entpacken von Daten

Die Mitglieder einer Union werden in einem gemeinsamen Speicherbereich gespeichert. Dies ist die Schlüsselfunktion, die es uns ermöglicht, interessante Bewerbungen für Gewerkschaften zu finden.

Betrachten Sie die folgende Vereinigung:

union { uint16_t Wort; struct { uint8_t byte1; uint8_t byte2; };} u1; 

In dieser Union gibt es zwei Elemente:Das erste Element, „Wort“, ist eine 2-Byte-Variable. Das zweite Element ist eine Struktur aus zwei Ein-Byte-Variablen. Die zwei Bytes, die der Union zugewiesen sind, werden von ihren beiden Mitgliedern geteilt.

Der zugewiesene Speicherplatz kann wie in Abbildung 1 unten gezeigt aussehen.

Abbildung 1

Während sich die Variable „word“ auf den gesamten zugewiesenen Speicherplatz bezieht, beziehen sich die Variablen „byte1“ und „byte2“ auf die Ein-Byte-Bereiche, die die Variable „word“ bilden. Wie können wir diese Funktion nutzen? Angenommen, Sie haben zwei Ein-Byte-Variablen „x“ und „y“, die kombiniert werden sollen, um eine einzelne Zwei-Byte-Variable zu erzeugen.

In diesem Fall können Sie die obige Vereinigung verwenden und den Strukturelementen „x“ und „y“ wie folgt zuweisen:

u1.byte1 =y;u1.byte2 =x; 

Jetzt können wir das „word“-Element der Union lesen, um eine 2-Byte-Variable zu erhalten, die aus „x“- und „y“-Variablen besteht (siehe Abbildung 2).

Abbildung 2

Das obige Beispiel zeigt die Verwendung von Unions zum Packen von zwei Ein-Byte-Variablen in eine einzelne Zwei-Byte-Variable. Wir könnten auch das Gegenteil tun:Schreiben Sie einen Zwei-Byte-Wert in „word“ und entpacken Sie ihn in zwei Ein-Byte-Variablen, indem Sie die „x“- und „y“-Variablen lesen. Das Schreiben eines Werts in ein Mitglied einer Union und das Lesen eines anderen Mitglieds davon wird manchmal als „Daten-Punning“ bezeichnet.

Die Endianness des Prozessors

Bei der Verwendung von Unions zum Packen/Entpacken von Daten müssen wir auf die Endianness des Prozessors achten. Wie in Robert Keims Artikel über Endianness diskutiert wird, gibt dieser Begriff die Reihenfolge an, in der die Bytes eines Datenobjekts im Speicher abgelegt werden. Ein Prozessor kann Little-Endian oder Big-Endian sein. Bei einem Big-Endian-Prozessor werden Daten so gespeichert, dass das Byte mit dem höchstwertigen Bit die niedrigste Speicheradresse hat. In Little-Endian-Systemen wird das Byte mit dem niederwertigsten Bit zuerst gespeichert.

Das in Abbildung 3 dargestellte Beispiel veranschaulicht die Little-Endian- und Big-Endian-Speicherung der Sequenz 0x01020304.

Abbildung 3. Bild mit freundlicher Genehmigung von IAR.

Lassen Sie uns den folgenden Code verwenden, um mit der Vereinigung des vorherigen Abschnitts zu experimentieren:

#include <stdio.h>#include <stdint.h>int main(){ union { struct{ uint8_t byte1; uint8_t byte2; }; uint16_t Wort; } u1; u1.byte1 =0x21;u1.byte2 =0x43; printf("Wort ist:%#X", u1.word);return 0;} 

Wenn ich diesen Code ausführe, erhalte ich die folgende Ausgabe:

Wort ist:0X4321

Dies zeigt, dass das erste Byte des Shared Memory Space („u1.byte1“) verwendet wird, um das niederwertigste Byte (0X21) der Variablen „word“ zu speichern. Mit anderen Worten, der Prozessor, den ich zum Ausführen des Codes verwende, ist Little Endian.

Wie Sie sehen, kann diese spezielle Anwendung von Unions ein implementierungsabhängiges Verhalten aufweisen. Dies sollte jedoch kein ernsthaftes Problem darstellen, da wir bei einer solchen Low-Level-Codierung normalerweise die Endianness des Prozessors kennen. Falls wir diese Details nicht kennen, können wir den obigen Code verwenden, um herauszufinden, wie die Daten im Speicher organisiert sind.

Alternative Lösung

Anstelle von Unions können wir auch die bitweisen Operatoren verwenden, um das Packen oder Entpacken von Daten durchzuführen. Zum Beispiel können wir den folgenden Code verwenden, um zwei Ein-Byte-Variablen „byte3“ und „byte4“ zu kombinieren und eine einzelne Zwei-Byte-Variable („word2“) zu erzeugen:

word2 =(((uint16_t) byte3) <<8 ) | ((uint16_t) byte4); 

Vergleichen wir die Ausgabe dieser beiden Lösungen im Little-Endian- und im Big-Endian-Fall. Betrachten Sie den folgenden Code:

#include <stdio.h>#include <stdint.h>int main(){union { struct { uint8_t byte1; uint8_t byte2; }; uint16_t Wort1; } u1; u1.byte1 =0x21;u1.byte2 =0x43;printf("Wort1 ist:%#X\n", u1.word1); uint8_t byte3, byte4;uint16_t word2;byte3 =0x21;byte4 =0x43;word2 =(((uint16_t) byte3) <<8 ) | ((uint16_t) byte4);printf("Wort2 ist:%#X \n", Wort2); Rückgabe 0;} 

Wenn wir diesen Code für einen Big-Endian-Prozessor wie TMS470MF03107 kompilieren , die Ausgabe ist:

Wort1 ist:0X2143

Wort2 ist:0X2143

Wenn wir es jedoch für einen Little-Endian-Prozessor wie STM32F407IE kompilieren , die Ausgabe ist:

Wort1 ist:0X4321

Wort2 ist:0X2143

Während das unionsbasierte Verfahren ein hardwareabhängiges Verhalten zeigt, führt das auf der Verschiebeoperation basierende Verfahren ungeachtet der Prozessor-Endianness zum gleichen Ergebnis. Dies liegt daran, dass wir bei letzterem Ansatz dem Namen einer Variablen einen Wert zuweisen („word2“) und der Compiler sich um die Speicherorganisation des Geräts kümmert. Bei der unionsbasierten Methode ändern wir jedoch den Wert der Bytes, die die Variable „word1“ bilden.

Obwohl die unionsbasierte Methode ein hardwareabhängiges Verhalten aufweist, hat sie den Vorteil, dass sie besser lesbar und wartungsfreundlicher ist. Aus diesem Grund ziehen es viele Programmierer vor, Unions für diese Anwendung zu verwenden.

Ein praktisches Beispiel für „Data Punning“

Bei der Arbeit mit gängigen seriellen Kommunikationsprotokollen müssen wir möglicherweise das Packen oder Entpacken der Daten durchführen. Betrachten Sie ein serielles Kommunikationsprotokoll, das während jeder Kommunikationssequenz ein Datenbyte sendet/empfängt. Solange wir mit Variablen mit einer Länge von einem Byte arbeiten, ist es einfach, die Daten zu übertragen, aber was ist, wenn wir eine Struktur beliebiger Größe haben, die über die Kommunikationsverbindung gehen soll? In diesem Fall müssen wir unser Datenobjekt irgendwie als Array von ein Byte langen Variablen darstellen. Sobald wir diese Array-of-Bytes-Darstellung erhalten haben, können wir die Bytes über die Kommunikationsverbindung übertragen. Auf der Empfängerseite können wir sie dann entsprechend verpacken und die ursprüngliche Struktur wieder aufbauen.

Angenommen, wir müssen eine Float-Variable „f1“ über die UART-Kommunikation senden. Eine Float-Variable belegt normalerweise vier Byte. Daher können wir die folgende Union als Puffer zum Extrahieren der vier Bytes von „f1“ verwenden:

union { float f; struct { uint8_t byte[4]; };} u1; 

Der Sender schreibt die Variable „f1“ in das Float-Element der Union. Dann liest es das „Byte“-Array und sendet die Bytes über die Kommunikationsverbindung. Der Empfänger macht das Umgekehrte:Er schreibt die empfangenen Daten in das „Byte“-Array seiner eigenen Union und liest die Float-Variable der Union als empfangenen Wert. Wir könnten diese Technik anwenden, um ein Datenobjekt beliebiger Größe zu übertragen. Der folgende Code kann ein einfacher Test zur Überprüfung dieser Technik sein.

#include <stdio.h>#include <stdint.h>int main(){float f1=5.5; Gewerkschaftspuffer { float f; struct { uint8_t byte[4]; }; }; Union Buffer buff_Tx;Union Buffer buff_Rx;buff_Tx.f =f1;buff_Rx.byte[0] =buff_Tx.byte[0];buff_Rx.byte[1] =buff_Tx.byte[1];buff_Rx.byte[2] =buff_Tx .byte[2];buff_Rx.byte[3] =buff_Tx.byte[3]; printf("Die empfangenen Daten sind:%f", buff_Rx.f); Rückgabe 0;} 

Abbildung 4 unten visualisiert die diskutierte Technik. Beachten Sie, dass die Bytes sequentiell übertragen werden.

Abbildung 4

Schlussfolgerung

Während die ursprüngliche Anwendung von Unions darin bestand, einen gemeinsam genutzten Speicherbereich für sich gegenseitig ausschließende Variablen zu schaffen, haben die Programmierer im Laufe der Zeit Unions für eine völlig andere Anwendung weit verbreitet verwendet:Union zum Packen/Entpacken von Daten. Diese besondere Anwendung von Gewerkschaften beinhaltet das Schreiben eines Wertes an ein Mitglied der Gewerkschaft und das Lesen eines anderen Mitglieds davon.

„Data Punning“ oder die Verwendung von Unions zum Packen/Entpacken von Daten kann zu hardwareabhängigem Verhalten führen. Es hat jedoch den Vorteil, dass es besser lesbar und wartbar ist. Aus diesem Grund bevorzugen viele Programmierer die Verwendung von Unions für diese Anwendung. „Data Punning“ kann besonders hilfreich sein, wenn wir ein Datenobjekt beliebiger Größe haben, das über eine serielle Kommunikationsverbindung gehen soll.

Um eine vollständige Liste meiner Artikel zu sehen, besuchen Sie bitte diese Seite.


Eingebettet

  1. Semaphoren:Versorgungsdienste und Datenstrukturen
  2. Strategie und Lösungen der Armee für zustandsorientierte Instandhaltung
  3. Die Vorteile der Anpassung von IIoT- und Datenanalyselösungen für EHS
  4. Aufbau einer verantwortungsvollen und vertrauenswürdigen KI
  5. Was ist Fog Computing und was bedeutet es für das IoT?
  6. C - Gewerkschaften
  7. Warum Daten und Kontext für die Sichtbarkeit der Lieferkette unerlässlich sind
  8. Für das Flottenmanagement sind KI und IoT zusammen besser
  9. Industrielles AIoT:Kombination von künstlicher Intelligenz und IoT für Industrie 4.0
  10. Litmus und Oden Fuse IIoT-Lösungen für intelligente Fertigung