TC3: Auf einzelnes Byte eines INT zugreifen.

Beiträge
6.636
Reaktionspunkte
1.607
Zuviel Werbung?
-> Hier kostenlos registrieren
Man kann in TwinCAT ja über das Konstrukt Bytevar.x auf einzelne Bits zugreifen, aber kann man auch über ein anderes Konstrukt auf das High-Byte und Low-Byte eines Integer zugreifen? Das es mit MEMCPY geht ist klar, aber ich suche nach einem anderen weg, so in der Art:

Code:
Byte[0] := Integervar.B0
 
Nö - geht nicht (https://infosys.beckhoff.de/content/1033/tc3_plc_intro/136395403.html).
Was möglich wäre eine Funktion mit mehren Ausgängen zu schaffen (3rd Edition der IEC) und da drinnen deinen qualifizierten Code zu verstecken.
Möglich bei Codesys3/TwinCAT3. Allerdings musst du bzgl. Syntax selber dir selber helfen bei der Definition/im Aufruf da dir die Editoren da nicht zu Hilfe eilen.

Function hat somit nur den Vorteil das du sie nicht instanziieren musst.

Guga
 
Hi,
dafür kannst Du wunderbar eine Union nehmen.
Eine Union ist aufgebaut wie eine Struktur nur das alle Elemente den gleichen Speicher haben.
So kannst Du die Integer-Zahl auch als Byte-Array betrachten.
Anbei mal einen Screenshot.
union.jpg
Hoffe das hilft Dir weiter.
VG
 
Hallo,
erstmal Danke an alle die geantwortet haben.
@olivertt82: Die Union ist mir noch nicht so geläufig, daher übersehe ich diese Möglichkeit immer. Ich denke sie wird es.
@Harald: Sorry, ich war wieder zu sparsam mit meinen Angaben, es geht um die Problematik mit dem großen und dem kleinen Indianer ;) und da hilft Deine Lösung leider nicht, weil das Vorzeichen verlorengeht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Unions sind ein grosser Fortschritt. Aber Vorsicht beim Einpacken von Structs in Unions, da kann einem das 8 Byte-Alignment schnell einen Streich spielen. Solche Structs am besten mit {attribute 'pack_mode' := '1'} deklarieren, um sicher zu sein, dass alle Variablen dort stehen, wo man sie haben möchte. Und wenn eine Union mit unterschiedlich grossen Elementen persistent sein soll, das grösste Element als letztes in der Union deklarieren, um sicherzustellen, dass beim Einschalten alle Bytes geladen werden.
 
Das Byte alignment kann Dir aber auch bei Structs ohne Union in die Suppe spucken. Bei meinem Kunden werden Daten per Array of Byte via Netzwerkvar übertragen und dann per MEMCPY in eine Struktur kopiert, da habe ich auch schon böse Überraschungen erlebt.

Von irgendwas mit Internetzugang gesendet
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
Byte[0] := INT_TO_BYTE(Integervar);
Byte[1] := INT_TO_BYTE(Integervar/256);
@Harald: Sorry, ich war wieder zu sparsam mit meinen Angaben, es geht um die Problematik mit dem großen und dem kleinen Indianer ;) und da hilft Deine Lösung leider nicht, weil das Vorzeichen verlorengeht.
:confused: Wo geht da etwas verloren?
Der von mir gezeigte Code isoliert lediglich das Low-Byte bzw. das High-Byte, und das sogar unabhängig davon welche Endianess verwendet wird.

Macht TC3 bei INT_TO_BYTE noch weitere Konvertierungen als nur das Reduzieren auf das Low-Byte? Dann kannst Du TC3 vielleicht so "überzeugen":
Code:
Byte[0] := SINT_TO_BYTE(INT_TO_SINT(Integervar));
Byte[1] := SINT_TO_BYTE(INT_TO_SINT(Integervar/256));


Ein Byte hat kein Vorzeichen - auch dann nicht wenn es aus dem Zugriff auf eine Union entsteht.

Die Union-Lösung ist eigentlich schon zu umständlich und funktioniert außerdem Endianness-abhängig (und Alignment-abhängig). Für die Union-Lösung sind 3 Speicherzugriffe nötig (Int-Variable lesen + auf Union-Speicher speichen + Byte aus der Union lesen), meine Lösung benötigt nur 1 Speicherzugriff.

Harald
 
Die Union-Lösung ist eigentlich schon zu umständlich und funktioniert außerdem Endianness-abhängig (und Alignment-abhängig). Für die Union-Lösung sind 3 Speicherzugriffe nötig (Int-Variable lesen + auf Union-Speicher speichen + Byte aus der Union lesen), meine Lösung benötigt nur 1 Speicherzugriff.
Nicht, wenn statt der Int-Variablen von vornherein eine Union aus Int und Array of Byte oder Byte-Struct deklariert wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Geht's vielleicht so:
Code:
Byte[0] := INT_TO_BYTE(Integervar);
Byte[1] := INT_TO_BYTE(Integervar/256);

Harald
Dieser Vorschlag führt beim High-Byte leider zu fatalen Rundungsfehlern. Statt Integervar/256 ein SHR(Integervar, 8 ) und es klappt.
 
Zuletzt bearbeitet:
Dieser Vorschlag führt beim High-Byte leider zu fatalen Rundungsfehlern. Statt Integervar/256 ein SHR(Integervar, 8 ) und es klappt.
:confused:
"INT_TO_BYTE(Integervar/256)" sollte exakt das selbe Ergebnis wie "INT_TO_BYTE(SHR(Integervar, 8 ))" liefern. Das Ergebnis von "Integervar/256" und "SHR(Integervar, 8 )" unterscheidet sich zwar bei negativen Integervar im High-Byte - das High-Byte wird aber durch das INT_TO_BYTE ignoriert/entfernt.

Hast Du mal ein Beispiel oder Screenshot von so einem fatalen Rundungsfehler?

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
"INT_TO_BYTE(Integervar/256)" sollte exakt das selbe Ergebnis wie "INT_TO_BYTE(SHR(Integervar, 8 ))" liefern.
:oops: Das ist leider nicht richtig.
Die Ganzzahldivision "Integervar/256" bei negativen Zahlen "rundet" in die "falsche" Richtung und liefert da nur dann das High-Byte, wenn das Low-Byte = 0 ist.

Dieser Vorschlag führt beim High-Byte leider zu fatalen Rundungsfehlern. Statt Integervar/256 ein SHR(Integervar, 8 ) und es klappt.
Du hast recht, das High-Byte muß mit SHR(Integervar, 8 ) ins Low-Byte gebracht werden.

(Oder das Low-Byte muß vor der Division auf 0 gesetzt werden (Integervar AND 16#FF00). Oder man muß dem ST-Compiler beibringen eine UINT-Division auszuführen - ob/wie das geht weiß ich allerdings nicht; bei Integer könnte man eine DInt-Division ausführen.)

Harald
 
Hallo Harald,
Schlafstörungen oder was?
Hab gerade den Test gemacht und dann erst gesehen, dass sich das eigentlich erledigt hat. Für alle die es dennoch interessiert über was Harald und ich hier diskutieren, hier mal zwei Screenshots.
INT_TO_BYTE_01.jpg
INT_TO_BYTE_02.jpg
Man kann auf diesen erkennen, dass bei einer Division durch 256 und einem Low-Byte <> 0 aufgerundet wird (16#FF wird zu 16#00). Bei der Nutzung von SHR funktioniert es wie gewollt.
 
Zurück
Oben