Ein Teilbereichstyp ist ein Typ, dessen Wertebereich nur eine Teilmenge des Basistyps ist. Die Deklaration kann im Datentypenregister erfolgen, eine Variable kann aber auch direkt mit einem Teilbereichstyp deklariert werden:
Syntax für die Deklaration im Register "Datentypen":
TYPE <Name> : <Inttype> (<ug>..<og>) END_TYPE;
<Name> |
muss ein gültiger IEC-Bezeichner sein, |
<Inttype> |
ist einer der Datentypen SINT, USINT, INT, UINT, DINT, UDINT, BYTE, WORD, DWORD (LINT, ULINT, LWORD). |
<ug> |
Ist eine Konstante, die mit dem Basistyp kompatibel sein muss und die die untere Grenze der Bereichstypen festlegt. Die untere Grenze selbst ist in diesem Bereich enthalten. |
<og> |
Ist eine Konstante, die mit dem Basistyp kompatibel sein muss und die obere Grenze der Bereichstypen festlegt. Die obere Grenze selbst ist in diesem Grundtyp enthalten. |
Beispiel:
TYPE SubInt : INT (-4095..4095); END_TYPE
Direkte Deklaration einer Variablen mit einem Teilbereichstyp:
VAR i : INT (-4095..4095); ui : UINT (0..10000); END_VAR
Wird eine Konstante einem Teilbereichstyp zugewiesen (in der Deklaration oder in der Implementierung), der nicht in diesen Bereich fällt (z. B. 1:=5000), wird eine Fehlermeldung ausgegeben.
Um die Einhaltung von Bereichsgrenzen zur Laufzeit zu überprüfen, müssen die Funktionen CheckRangeSigned oder CheckRangeUnsigned eingeführt werden. In diesen können Grenzverletzungen mit den geeigneten Methoden und Mitteln erfasst werden (z. B. kann der Wert ausgeschnitten oder ein Fehlerflag gesetzt werden). Sie werden implizit aufgerufen, sobald eine Variable als zu einem Teilbereichstyp gehörend geschrieben wird, der entweder aus einem Typ mit oder ohne Vorzeichen besteht.
Beispiel:
Im Falle einer Variablen, die zu einem vorzeichenbehafteten Teilbereichstyp gehört (wie i, oben), wird die Funktion CheckRangeSigned aufgerufen; sie könnte wie folgt programmiert werden, um einen Wert auf den zulässigen Bereich zu trimmen:
FUNCTION CheckRangeSigned : DINT VAR_INPUT value, lower, upper: DINT; END_VAR IF (value < lower) THEN CheckRangeSigned := lower; ELSIF(value > upper) THEN CheckRangeSigned := upper; ELSE CheckRangeSigned := value; END_IF
Beim automatischen Aufruf der Funktion ist der Funktionsname CheckRangeSigned obligatorisch, ebenso die Schnittstellenangabe: Rückgabewert und drei Parameter vom Typ DINT
Beim Aufruf wird die Funktion wie folgt parametrisiert:
-
- Wert: der dem Bereichstyp zuzuordnende Wert
-
- lower: die untere Grenze des Bereichs
-
- upper: die obere Grenze des Bereichs
-
- Rückgabewert: dies ist der Wert, der dem Bereichstyp tatsächlich zugewiesen wird
Eine Zuweisung i:=10*y führt im Beispiel implizit zu Folgendem:
i := CheckRangeSigned(10*y, -4095, 4095);
Selbst wenn y zum Beispiel den Wert 1000 hat, hat i nach dieser Zuweisung nur den Wert 4095.
Dasselbe gilt für die Funktion CheckRangeUnsigned: Funktionsname und Schnittstelle müssen korrekt sein.
FUNCTION CheckRangeUnsigned : UDINT VAR_INPUT value, lower, upper: UDINT; END_VAR




WARNUNG

Wenn keine der Funktionen CheckRangeSigned oder CheckRangeUnsigned vorhanden ist, findet zur Laufzeit keine Typüberprüfung von Teilbereichstypen statt! Die Variable i könnte dann jederzeit einen beliebigen Wert zwischen 32768 und 32767 annehmen!




HINWEIS

Wenn keine der Funktionen CheckRangeSigned oder CheckRangeUnsigned wie oben beschrieben vorhanden ist, kann es zu einer Endlosschleife kommen, wenn ein Teilbereichstyp in einer FOR-Schleife verwendet wird. Dies geschieht, wenn der für die FOR-Schleife angegebene Bereich so groß oder größer ist als der Bereich des Unterbereichstyps!




HINWEIS

Die CheckRangeSigned-Funktion, die in der Check.Lib-Bibliothek enthalten ist, ist nur eine Beispiellösung! Prüfen Sie vor der Verwendung des Bibliotheksbausteins, ob die Funktion wie gewünscht für Ihr Projekt funktioniert, oder implementieren Sie eine entsprechende CheckRange-Funktion direkt als POU im Projekt.
Beispiel:
VAR ui : UINT (0..10000); END_VAR FOR ui:=0 TO 10000 DO ... END_FOR
Die FOR-Schleife wird nie beendet werden, da ui nicht größer als 10000 werden kann.
Achten Sie auch auf die Definition der CheckRange-Funktionen, wenn Sie den inkrementellen Wert einer FOR-Schleife definieren!