TIA Umwandlung negativer Wert von LINT auf LREAL

Zuviel Werbung?
-> Hier kostenlos registrieren
// Insbesondere VZmitBetrag muss DINT, damit der SCL-Compiler das SHR() vorzeichenrichtig einsetzt.
Tut der Compiler das denn wirklich?
Ja, tut er. Für S7-1200/1500. Gilt auch für FUP und KOP. siehe nächsten Beitrag.

Falls der Compiler also (...) bei DINT und Rechtsschieben quasi den AWL-SSD statt des AWL-SRD benutzt,
dann ist Deine Schieberei um 31 Bit nach rechts genial: negative Zahlen liefern 16#FFFFFFFF > ( also -1 ) und 0 oder positive Zahlen liefern durch das OR 1 den Wert 16#00000001.
:cool: genau so ist das beabsichtigt. Und es erspart auch das gesonderte Isolieren des Vorzeichenbits (Ausblenden des Betrags).
btw: man könnte auch um 32 oder mehr Bit schieben, das ändert nichts am Ergebnis.
 
Wie funktioniert SHR?

Aus der TIA 15.1 Hilfe, für SCL/FUP/KOP jeweils gleich.

S7-1200/1500
SHR: Rechts schieben
...
Bei Werten ohne Vorzeichen werden die beim Schieben frei werdenden Bitstellen im linken Bereich des Operanden mit Nullen aufgefüllt. Wenn der angegebene Wert ein Vorzeichen aufweist, werden die freien Bitstellen mit dem Signalzustand des Vorzeichenbits belegt.
Für den Input-Parameter IN sind die Datentypen "Bitfolgen" und "Ganzzahlen" angegeben.


S7-300/400
SHR: Rechts schieben
...
Die beim Schieben frei werdenden Bitstellen im linken Bereich des Operanden werden mit Nullen aufgefüllt.
Für den Input-Parameter IN ist nur der Datentyp "Bitfolgen" angegeben.
Trotzdem kann man auch mit Ganzzahlen programmieren #MyDWord := SHR(IN := #MyDInt, N := 31);
Das wird in TIA widerspruchslos "erfolgreich" übersetzt, ohne irgendeine Warnung! Es werden wie erwartet Nullen eingeschoben. (-1 --> +1)

Nur wenn man für den Baustein die IEC-Prüfung aktiviert, dann wird beim Übersetzen eine Fehlermeldung ausgegeben:
"Parameter der Funktion oder des Funktionsbausteins stimmen nicht mit den übergebenen formalen Parametern überein."


Codesys 2.3
Operator SHR
...
Wenn ein vorzeichenloser Datentyp verwendet wird (BYTE, WORD, DWORD), wird von links mit Nullen aufgefüllt. Bei Vorzeichen-Datentypen wie z.B. INT wird dagegen ein arithmetischer Shift durchgeführt, d.h. es wird mit dem Wert des obersten Bits aufgefüllt.


Codesys 3
Die Codesys Online Referenz zum Operator SHR gibt keinen Hinweis, was beim SHR mit vorzeichenbehafteten Datentypen passiert.
Ob beim Übersetzen Warnungen oder Fehler ausgegeben werden, weiß ich nicht.
Operator ‚SHR‘
...
Die Zielsysteme bewirken Auffüllen mit Nullen

Es gibt ein Add-on "CODESYS Static Analysis"
Das generiert eine Meldung SA0052
SA0052: Unübliche Schiebeoperation
Ermittelt Schiebeoperationen (Bitverschiebung) auf vorzeichenbehaftete Variablen. Bei Schiebeoperationen auf Bitfeld-Datentypen (Byte, DWORD, LWORD, WORD) wird kein Fehler ausgegeben.

Begründung: CODESYS erlaubt Schiebeoperationen auf vorzeichenbehafteten Datentypen. Diese Operationen sind aber unüblich und können verwirrend sein. Die Norm IEC-61131-3 sieht solche Operationen nicht vor und sie sollten vermieden werden, um die Portierbarkeit des Codes auf andere Entwicklungssysteme zu erhöhen.


In der IEC 61131-3 (2003) sind für den Input-Parameter IN nur ANY_BIT-Datentypen vorgesehen.
Bit string functions
SHR
OUT := IN right-shifted by N bits, zero-filled on left

Also Achtung! beim Migrieren oder Portieren von SCL-/ST-/FUP-/KOP-Programmen, die SHR enthalten!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Code:
// Insbesondere VZmitBetrag muss DINT, damit der SCL-Compiler das SHR() vorzeichenrichtig einsetzt.

Betrag := VZmitBetrag AND 16#7FFFFFFF;
VZfaktor := SHR(IN:=VZmitBetrag, N:=31) OR 1;
ZweierKomplementDarstellung := VZfaktor * Betrag;
Wenn man das plattformabhängige SHR nicht verwenden will, dann kann man VZfaktor plattformunabhängig so berechnen:
Code:
VZfaktor := (ROL(IN:=VZmitBetrag, N:=1) AND 1 XOR 1) * 2 - 1;
 
Wenn man das plattformabhängige SHR nicht verwenden will, dann kann man VZfaktor plattformunabhängig so berechnen:
Code:
VZfaktor := (ROL(IN:=VZmitBetrag, N:=1) AND 1 XOR 1) * 2 - 1;
Raffiniert, Harald! VZ-Bit nach BitPosition 0. Hier isolieren und invertieren. Dann um 1 BitPosition nach links schieben (also "verdoppeln"). Dann 1 subtrahieren. Aus negativ wird -1 und aus positiv wird +1. Was will man mehr?
Nübel (= nicht übel)! Aber ich würde es gerne in einer Function mit Aussage-kräftigem Namen verstecken, weil es jedesmal, wenn man diesen Code sieht, zu lange dauert, ihn auf der Zunge zergehen zu lassen. :)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ich würde es gerne in einer Function mit Aussage-kräftigem Namen verstecken, weil es jedesmal, wenn man diesen Code sieht, zu lange dauert, ihn auf der Zunge zergehen zu lassen. :)
Ja, solchen (meist effizienten) Bit-twiddling-Code versteckt man am besten in einer Blackbox (Function) und dokumentiert die Funktion und verwendet sie, ohne noch groß über Details nachzudenken. Wobei du ja der Beweis bist, dass der Code durchaus noch nachvollziehbar ist. :)

Man müsste nur ein klein wenig länger auf das Ergebnis warten. ;)
Ich glaube, dass auch bei S7-1200 und S7-1500 die Ausführungszeit von Schiebe-/Rotier-Operationen unabhängig davon ist, um wieviele Bits geschoben wird (also egal, ob um 1 oder 32 Bitpositionen schieben). Ich denke, der Maschinencode oder Microcode von Schiebeoperationen schiebt nicht wirklich, man kann ja z.B. das Schieben in eine Multiplikation oder Division umformen, deren Ausführungszeit unabhängig vom Wert der Operanden ist. :cool:
 
Zurück
Oben