Verarbeiten von Binärdaten

wisi

Level-1
Beiträge
14
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich bräuchte etwas Unterstützung beim Verarbeiten/Zerlegen von binären Daten, vorzugsweise in ST.

Meine Hardware ist ein Beckhoff CX9000.

Ich bekomme von einem Schnittstellenmodul eine binäre Zeichenfolge, die ich in ein Array von Bytes (nennen wir es ByteArray) schreibe. Nun weiß ich, dass sich in den Bytes 137-141 ein 40bit unsigned INT (LSB ist hier hinten, d.h. Byte 141) versteckt. Wie kriege ich die Zahl am elegantesten und vor allem performantesten in eine Variable? Wegen der Länge kommt meines Erachtens nur ein LREAL in Frage, weil es keine Ganzzahltypen mit mehr als 32bit gibt (zumindest sind die in Twincat nicht implementiert).

Mein Ansatz wäre demnach (wenn 'wert' meine LREAL-Variable ist):

Code:
wert := BYTE_TO_LREAL(ByteArray[137]) * 4294967296 + BYTE_TO_LREAL(ByteArray[138]) * 16777216 + BYTE_TO_LREAL(ByteArray[138]) * 65536 + BYTE_TO_LREAL(ByteArray[138]) * 256 + BYTE_TO_LREAL(ByteArray[141])

Geht das irgendwie eleganter bzw. ist das in Sachen Performance ideal so? Ich muss nämlich mehrere solcher "Umwandlungen" vornehmen.

Besten Dank für Eure Hilfe
Christian
 
In der TcUtilities.lib sind 64 Bit-Integertypen definiert und auch ein paar Fukionen zum Rechnen mit diesen Typen. Ich habe selbst noch nicht damit gearbeitet, aber vielleicht ist etwas für Dich dabei.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wandlungen

Wenn das System keine Ganzzahl Daten > 32 Bit unterstützt, wird es schwierig. LREAL hat bestimmt den geforderten Dymamik Bereich aber nicht die Auflösung an signifikanten Stellen.

Im angegebenen Beispiel muss man schon einmal darauf achten, dass die Multiplikationen mit 2 power (n * 8) ebenfalls einen Überlauf produzieren.

Wenn man das ganze für einen exakten Zählerstand braucht, muss man sich alles selber schreiben, z.B eine Struct der Art:
TYPE WORD64 :
STRUCT
dwM : DWORD := 0; // hier kommen die Oberen 32 Bit hin
dwL : DWORD := 0; // hier kommen die Unteren 32 Bit rein
END_STRUCT
END_TYPE

Dann beim aufdröseln der Telegramme nicht nach REAL casten sondern nach DWORD und nicht multiplizieren sondern schieben.

value.dwM := ByteArray[137];
value.dwL := ByteArray[138];
value.dwL := SHL (value.dwL, 8) + ByteArray[139];
value.dwL := SHL (value.dwL, 8) + ByteArray[140];
value.dwL := SHL (value.dwL, 8) + ByteArray[141];

Dann ggf. die Grundrechenarten +,-,*,/ für diesen datentyp neu schreiben.


Wenn Rundungen zugelassen sind, bietet sich in etwa folgende Strategie an:

Wenn im signifikantesten Byte nix drin ist, alles als DWORD rechnen, sonst wie oben und erst jetzt nach LREAL wandeln.
 
Hallo RobiHerb,

Wenn das System keine Ganzzahl Daten > 32 Bit unterstützt, wird es schwierig. LREAL hat bestimmt den geforderten Dymamik Bereich aber nicht die Auflösung an signifikanten Stellen.

Stimmt. Für meine 40bit Ganzzahl sollte es aber noch reichen, oder? 2^40 = 1099511627776 hat 13 Stellen, dass müsste sich mit LREAL noch darstellen lassen.

Im angegebenen Beispiel muss man schon einmal darauf achten, dass die Multiplikationen mit 2 power (n * 8) ebenfalls einen Überlauf produzieren.

Das versteh ich nicht. Wo wäre in meinem Beispiel ein Überlauf zu finden?

Wenn man das ganze für einen exakten Zählerstand braucht, muss man sich alles selber schreiben, z.B eine Struct der Art:
TYPE WORD64 :
STRUCT
dwM : DWORD := 0; // hier kommen die Oberen 32 Bit hin
dwL : DWORD := 0; // hier kommen die Unteren 32 Bit rein
END_STRUCT
END_TYPE

Gut, so ähnlich ist das in der erwähnten TcUtilities.lib gelöst. Dort gibt's so einen Datentyp "T_ULARGE_INTEGER", der auch so deklariert ist.

Dann beim aufdröseln der Telegramme nicht nach REAL casten sondern nach DWORD und nicht multiplizieren sondern schieben.
...
Dann ggf. die Grundrechenarten +,-,*,/ für diesen datentyp neu schreiben.

Tja, hier verließen sie ihn. Wie würde man sowas basteln? In dem Zusammenhang verstehe ich die Implementierung von "T_ULARGE_INTEGER" nicht ... ich kann nämlich nicht sehen, wozu der Datentyp gut ist, d.h. ich finde keine Funktionen oder FB's, die ihn unterstützen. Die Grundrechenarten sind ja wohl auch nicht verfügbar.


Wenn Rundungen zugelassen sind, bietet sich in etwa folgende Strategie an:

Wenn im signifikantesten Byte nix drin ist, alles als DWORD rechnen, sonst wie oben und erst jetzt nach LREAL wandeln.

Für mich wäre alternativ auch interessant, wie man die 64bit Ganzzahl in einen Dezimal-String wandeln kann. Gibt's dafür vielleicht eine Routine/Algorithmus?

Besten Dank
Christian
 
Habe auch gerade gesehen, dass die Rechenfunktionen nur für den vorzeichenbehafteten T_LARGE_INTEGER definiert sind. Aber der würde es bei 40 Bit ja auch tun.
 
Zurück
Oben