自定义数据类型(DUT)
新建自定义数据类型:结构,枚举,引用,子范围,数组,指针。
结构(Structures)
结构声明的语法如下:
TYPE <结构名>:
STRUCT
<变量的声明1>
..
<变量声明n>
END_STRUCT
END_TYPE
<结构名>是一种可以在整个工程中被识别的数据类型,可以像标准数据类型一样使用。
您可以使用互锁结构。唯一的限制是不可以指定结构中变量的地址(不允许使用AT来指定变量的地址)
定义名为Polygonline的结构举例:
TYPE Polygonline:
STRUCT
Start:ARRAY [1..2] OF INT;
Point1:ARRAY [1..2] OF INT;
Point2:ARRAY [1..2] OF INT;
END_STRUCT
END_TYPE
结构的初始化:
结构初始化举例:
Poly_1:polygonline := ( Start:=[3,3], Point1 =[5,2], Point2:=[7,3];
不能以变量作为初始化的值。参见“数组”中结构数组的初始化举例。
结构成员的访问:
您可以使用下述的语法访问结构的成员:
<结构名>.<结构成员名>
因此对于上述的结构“polygonline”,您可以用Poly_1.Start访问结构成员“start”。
枚举(Enumerations)
枚举是由很多字符串常量组成的用户定义数据类型。这些常量称为枚举值。
即使在POU之内声明枚举值,枚举值仍然可以在整个工程范围内被识别。
用户可以通过添加对象对话框建立“DUT”对象来创建一个枚举。
语法:
TYPE <标识符>:(<Enum_0>,<Enum_1>, ...,<Enum_n>) |<base data type>;
END_TYPE
<标识符>变量可以代表枚举值 <Enum_..> 并被初始化为第一个值。这些值与所有的数字类型兼容,也就是说可以像使用整形变量一样对其进行操作。您也可以把数x赋给这个值。如果在声明中枚举值没有被初始化为指定的值,将从0开始递增依次进行初始化。请确保初始化时的初始值在内部元素中递增。运行时将会检查这些值的有效性。
例如:
TYPE TRAFFIC_SIGNAL: (red,yellow, green:=10); (* 每个颜色的初始值是Red=0,Yellow=1,Green=10 *)
END_TYPE
TRAFFIC_SIGNAL1 :TRAFFIC_SIGNAL;
TRAFFIC_SIGNAL1:=0; (* 交通信号的值是Red *)
FOR i:= red TO green DO
i := i + 1;
END_FOR;
IEC 61131-3标准的扩展:
枚举类型的名称可以(作为范围操作符)用来确定需要访问的枚举常量。
因此,您可以在不同枚举中使用相同的常量。
例如:
定义两个枚举:
TYPE COLORS_1: (red, blue);
END_TYPE
TYPE COLORS_2: (green,blue, yellow);
END_TYPE
在POU中使用枚举值Blue:
声明:
colorvar1 : COLORS_1;
colorvar2 : COLORS_2;
实现:
(* 可以这样使用:*)
colorvar1 := colors_1.blue;
colorvar2 := colors_2.blue;
(* 不能这样使用:*)
colorvar1 := blue;
colorvar2 := blue;
可以明确指定枚举所指向的数据类型(默认类型是INT)。
例如:
需要将枚举BigEnum的数据类型指定为DINT:
TYPE BigEnum : (yellow,blue, green:=16#8000) DINT;
END_TYPE
引用(References)
引用是一个对象的别名。这个别名可以通过标识符读写。与指针不同的是,引用所指向的数据将被直接改变,因此引用的赋值和所指向的数据是相同的。设置引用的地址用一个特定的赋值操作完成。一个引用是否指向一个有效的数据(不等于0),可以使用一个专门的操作符来检查,如下所示。
用以下语法声明引用:
语法
<标识符> : REFERENCE TO<数据类型>
声明示例:
ref_int : REFERENCE TO INT;
a : INT;
b : INT;
此时ref_int可以作为整型变量的别名使用
使用示例:
ref_int REF= a; (* 此时ref_int指向a *)
ref_int := 12; (* 此时a的值为12 *)
b := ref_int * 2; (* 此时b的值为24 *)
ref_int REF= b; (* 此时ref_int指向b *)
ref_int := a / 2; (* 此时b的值为6 *)
ref_int REF= 0; ( *引用的显式初始化 *)
子范围(子范围(Subrangetypes) )
子范围是一种用户自定义类型,其值的范围是基本数据类型的一个子集。注意可以使用隐含的范围边界校验(Range boundary checks)。
在DUT中声明子范围。您也可以把一个变量直接声明为子范围:
声明为一个DUT对象的语法如下:
TYPE <名称> : <Inttype>(<ug>..<og>) END_TYPE;
<名称> | 必须是一个有效的IEC标识符。 |
<Inttype> | 是以下数据类型中的一个:SINT、USINT、INT、UINT、DINT、UDINT、BYTE、WORD、DWORD (LINT、ULINT、LWORD)。 |
<ug> | 是一个与基本数据类型相兼容的常量,它设定了范围数据类型的下界。下界本身也属于这个范围。 |
<og> | 是一个与基本数据类型相兼容的常量,它设定了范围数据类型的上界。上界本身也属于这个范围。 |
例如:
TYPE
SubInt : INT (-4095..4095);
END_TYPE
把变量直接声明为子范围:
VAR
i : INT (-4095..4095);
ui : UINT (0..10000);
END_VAR
如果一个(在声明或实现中)被指定为子范围的值不在子范围的界限之内(如令以上声明中的i:=5000),系统将报错。
导致死循环的例子:
VAR
ui : UINT (0..10000);
END_VAR
FOR ui:=0 TO 10000 DO
...
END_FOR
由于校验函数使变量ui的值不会超过10000,故程序永远无法跳出这个FOR循环。
数组(数组(Arrays) )
一维、二维和三维数组属于基本的数据类型。您可以在POU的声明部分或者全局变量表中定义数组。请注意可以使用隐含的边界检查。
语法:
<数组名>:ARRAY[<ll1>..<ul1>,<ll2>..<ul2>] OF <基本数据类型>
ii1, ll2, ll3表示字段范围的最小值,ul1, ul2 and ul3表示字段范围的最大值。字段范围必须是整数。
例如:
card_game: ARRAY [1..13, 1..4] OF INT;
数组的初始化:
数组的完全初始化举例:
arr1 : ARRAY [1..5] OF INT := [1,2,3,4,5];
arr2 : ARRAY [1..2,3..4] OF INT := [1,3(7)]; (* 即1,7,7,7的缩写形式 *)
arr3 : ARRAY [1..2,2..3,3..4] OF INT := [2(0),4(4),2,3];
(* 即0,0,4,4,4,4,2,3的缩写形式 *)
结构数组的初始化举例:
结构定义:
TYPE STRUCT1
STRUCT
p1:int;
p2:int;
p3:dword;
END_STRUCT
END_TYPE
数组初始化:
ARRAY[1..3] OF STRUCT1:= [(p1:=1,p2:=10,p3:=4723),(p1:=2,p2:=0,p3:=299),
(p1:=14,p2:=5,p3:=112)];
数组的部分初始化举例:
arr1 : ARRAY [1..10] OF INT := [1,2];
对于那些没有预先赋值的元素,按照基本数据类型的缺省初始值进行初始化。在上例中,元素[3]到[10]被初始化为0。
数组元素的访问:
在二维数组中访问数组元素,使用下面的语法:
<数组名>[Index1,Index2]
指针(Pointers)
指针用来在应用程序运行时存储变量、程序、功能块、方法和函数的地址。它可以指向上述的任何一个对象以及任意数据类型,包括用户定义数据类型。请注意,您可以使用隐含的指针校验功能。
声明指针的语法如下:
<标识符>: POINTER TO <数据类型 | 功能块 | 程序 | 方法 | 函数>;
取指针地址内容即意味着读取指针当前所指地址中存储的数据。通过在指针标识符后添加内容操作符“^”,可以取得指针所指地址的内容: 请看下面“pt^”的使用示例。
通过地址操作符ADR可以将变量的地址赋给指针。
示例:
VAR
pt:POINTER TO INT; (* 声明一个指针pt *)
var_int1:INT := 5; (* 声明变量var_int1和var_int2 *)
var_int2:INT;
END_VAR
pt := ADR(var_int1); (* 将varint1的地址赋给指针pt *)
var_int2:= pt^; (* 通过取指针pt的地址内容,将var_int1的值5赋给var_int2 *)
建立好自定义数据类型的引用
其中:数组,指针可以在局部和全局变量中独自定义并引用。
自定义数据引用开始前必须声明引用的自定义数据
可以在全局和局部变量中关联引用声明。
在程序中输入引用名后加“.”选择相应的后缀名来使用引用的数据:
对于数据交流量大,数据流多的可以采用该方法来区别和方便的使用数据。
其中:数组,可以是等于一个数据表格,通过寻表找出我们所需要的值;枚举,是我们这个数据可能存在的不同值的可能,当其等于某个值的时候代表这某些值;指针,一般用在间接寻址,从而简化了大量数据的存取赋值等操作(需结合FOR语句来使用),同时也实用与间接性过度值的一些数据应用;子范围,也就是局限了数据的肯能值范围,防止数据超出范围或者不在范围内。
该文仅此记录相关概念,留个存档。相关应用欢迎交流。