3.4 数据类型
IEC 61131-3的数据类型分为基本数据类型和导出数据类型两类。数据类型与它在数据存储器中所占用的数据长度有关。
定义数据类型可防止因对数据类型的不同设置而发生出错。数据类型的标准化是编程语言开放性的重要标志。
3.4.1 基本数据类型
基本数据类型是预先定义的标准化数据类型,有布尔型、位串、整数、实数、持续的时间、一天中的时间、日期、日期和时刻、字符串等类型,总计20种,基本数据类型见表3-13。
表3-13 基本数据类型
(续)
1.布尔型(BOOL)
布尔型为位数据,取值为TRUE或FALSE,也可表示为BOOL#1或BOOL#0。布尔型数据表达为{datatype}#{numericvalue}。
例如,布尔型变量赋值时
正确表达:BOOLvariable:=TRUE;或BOOLvariable:=BOOL#1;
错误表达:BOOLvariable:=1;
2.位串(bit string)
位串的数据类型为BYTE、WORD、DWORD和LWORD,基可选2、8、16。位串数据的表达为{datatype}#base#{numericvalue}。
例如,位串变量赋值时
正确表达:bitstringvariable:=WORD#16#3;
错误表达:bitstringvariable:=3;
不能直接比较两个位串数据的大小,可以用数据转换指令将它们转换为整数类型的数据,再进行比较。
3.整数(Integer)
整数的数据类型有SINT、INT、DINT、LINT、USINT、UINT、UDINT、ULINT。基可选2、8、10、16,即一个整数可定义为二进制、八进制、十进制、十六进制数。整数数据的表达为{datatype}#base#{numericvalue}。十进制数,为表示负数,可在数值前添加“-”,如-15。若省略“基”,写为{datatype}#{numericvalue},则默认基为10(十进制数)。数据类型不允许省略。
例如,为单字整数变量赋值-1时
正确表达:intvariable:=INT#2#1000000000000001;
intvariable:=INT#8#100001;
intvariable:=INT#10#-1;或intvariable:=INT#-1;
intvariable:=INT#16#8001;错误表达:intvariable:=-1;
在数值中单一的下划线字符“”是没有意义的,只增加可读性,例如,2#11111111表示二进制11111111。
不能对整数型的数据直接进行逻辑运算,可以用数据转换指令转换为位串型数据,再进行逻辑处理。
4.实数(Real number)
实数的数据类型有REAL、LREAL。基为10,表示十进制数。实数数据的表达为{data type}#base#{numericvalue},可省略“基”,写为{datatype}#{numericvalue}。若省略数据类型,写为{numericvalue},则默认数据类型为LREAL。
例如,实数变量赋值3.14时
正确表达:realvariable:=REAL#3.14;
错误表达:intvariable:=3.14;
实数也称为浮点数,在计算机中用二进制数来表示,通常为32位或64位,分别叫作REAL或LREAL。
在数据的位数有限的情况下,用定点数表示的数的范围小。当用浮点数表示一个实数时,小数点的位置可变,随着小数点位置的改变,指数的数值也随之改变。因此,在有效数字的位数有限的情况下,不仅浮点数的范围可以比定点数的范围大得多,而且也可以保持数据的有效精度。
对浮点数的表示法,美国电气与电子工程师协会(IEEE)制定的标准已被众多计算机制造商采用。下面以浮点数的IEEE754格式为例,介绍浮点数的表示法。
(1)浮点数的IEEE754格式
浮点数的IEEE754标准格式可表示为:
REAL数值=(-1)s2e-127(1.f)
LREAL数值=(-1)s2e-1023(1.f)
式中各符号的意义是:
s:符号
e:指数
f:尾数(小数点后面的有效数字)
浮点数的格式如下:
REAL(32位)
LREAL(64位)
以REAL数为例,介绍各部分的含义:
符号s占1位,取值为0表示正数,1表示负数。
指数e占8位,取值为0~255,实际指数是e减去127的差,结果为-127~128。
尾数f占23位,二进制浮点数的尾数部分满足2.0>1.f≥1.0。
例如,某REAL数表示如下:
符号s为1,表示该数据是负数;
指数e为27=128,实际指数为128-127=1;
尾数f为(222+221)×2-23=0.75,实际尾数为1+0.75=1.75;
该REAL数据值为-21×1.75=-3.5。
(2)用浮点数表示的数据范围
REAL和LREAL数据的取值范围见表3-14,非常接近于0的值不能表示。
表3-14 REAL和LREAL数据的取值范围
浮点数的数据范围如图3-59所示。
图3-59 浮点数的数据范围
(3)特殊数据NaN、±∞、±0的浮点数格式
浮点数表示的特殊数据见表3-15。
表3-15 浮点数表示的特殊数据
(4)用浮点数表示非标准数据
非标准数据是绝对值极小而不能表示为标准数据的实数。
非标准数据的浮点数表示为:
REAL(-1)s×2-126×(尾数×2-23)
LREAL(-1)s×2-1022×(尾数×2-52)
以REAL数为例,介绍各部分的含义:
●符号s为0表示正数,1表示负数。
●指数e为0,实际指数为-126。
●尾数f用1~(223-1)表示,在实际尾数0.f中,设定位23为0(这也是一种规定),二进制数的小数点要紧跟在它的后面。
例如,某非标准的REAL数如下:
符号s为1,表示该数是负数;
指数e为0,实际指数为-126;
尾数f为(222+221)×2-23=0.75,实际尾数为0+0.75=0.75;
该REAL数据值为-2-126×0.75,是一个绝对值极小的数值。
(5)数据处理
浮点数表达的只是一个近似值。因此,浮点数和它的真值有差别。浮点数有效数字的位数是有限的。因此,当完成浮点数运算时要采取以下措施。
1)四舍五入
如果实际值超过尾数的有效数字,按照下列规则四舍五入处理:
●结果是浮点数所能表示的最接近的值。
●当浮点数运算结果中的数字个数超过内部处理表达式中的有效数字时,若结果近似于两个内部浮点表达式中的一个,则使用较接近的值。若结果介于两个内部浮点表达式的中间,可四舍五入,以便使尾数的最后一个数字为0。
2)上溢出、下溢出
上溢出将根据结果的符号以+∞或-∞输出。下溢出将根据结果的符号以+0或-0输出。
如果浮点数转换为整数时出现上溢出,那么结果值可能不正确。
非法计算将导致出现NaN(不是一个数)。
当实际值的绝对值大于浮点数所能表示的最大值时,发生上溢。当实际值的绝对值小于浮点数所能表示的最小值时,发生下溢。
●如果发生上溢且实际值为正数,则计算的结果为+∞。如果发生下溢且实际值为负数,则计算的结果为-∞。
●如果发生下溢且实际值为正数,则计算的结果为+0。如果发生下溢且实际值为负数,则计算的结果为-0。
(6)特殊数据计算
特殊数据包括0、∞、NaN,处理时注意以下事项:
按照下面的原则完成涉及特殊数据(也就是,+∞,-∞,+0,-0和NaN)的计算
●+∞和-∞相加的结果为NaN。
●同样符号的两个∞值相减的结果为NaN。
●+0或-0与∞相乘的结果为NaN。
●+0/+0、-0/-0或∞/∞的结果为NaN。
●+0和-0的和为+0。
●+0减+0或-0减-0的结果为+0。相同符号的0之差为+0。
●任何涉及NaN数据的四则运算的结果为NaN。如果有一个操作数为NaN,结果将为NaN。
●比较指令(例如Cmp指令)认为+0和-0一样大。+0和-0进行比较时按相等处理。
●如果将NaN与其他数据比较,结果永远不相等。
5.持续时间(Duration)
持续时间用于表达一个事件经过的时间。
持续时间用TIME#{day}d{hour}h{minutes}m{seconds}s{milliseconds}ms表示,式中TIME可简化为T。
持续时间前半部分为标识符TIME(或T)及分界符#,后半部分是用天、小时、分、秒和毫秒或其任意组合表示的持续时间,如TIME#3d4h5m6s。
持续时间标识符TIME或T,因字母的大小写具有相同意义,因此,持续时间标识符也可表示为time或t。其中,TIME或time称为长前缀,T或t称为短前缀。
表示时间单位天、小时、分、秒和毫秒等字母的大小写具有相同意义。因此,T#12.3S与T#12.3s等价。
由于下划线没有意义,因此持续时间数值可用下划线分隔。例如,T#1d2h3m表示持续时间为1天2小时3分,它与T#1d2h3m具有相同的含义。
持续时间的时间单位有天(d)、小时(h)、分(m)、秒(s)、毫秒(ms)。可以用小数表示持续时间,如T#12.3s、T#4.5d。可以任意指定时间表示的顺序,如T#1h1d也是合法的。
持续时间的数值允许有负值,如T#-23.4h14.5m,但不允许表示为-T#23.4h14.5m。持续时间具有超载属性,即允许数据超过有效的时间范围。例如,T#25h80m中25小时已超过1天24小时的有效时间范围。同样,80分钟也超出了分钟的有效时间范围,但这样的表示是允许的,编程系统会自动将它转换为不超过有效时间范围的数据,即它与T#1d2h10m是等价的。
6.一天中的时间(Time of Day)
一天中的时间用于表示在一天中的时间,也称为时刻,例如,当前时间等。
一天中的时间用时刻标识符、分界符#和时刻表示。表达式为TIMEOFDAY#{hour}:{minutes}:{seconds},或TOD#{hour}:{minutes}:{seconds}。
TIMEOFDAY或timeofday是时刻标识符的长前缀,TOD或tod是时刻标识符的短前缀。例如,TIMEOFDAY#12:34:56和TOD#12:34:56是等效的。
时刻文字中,时刻的分界符用冒号,不用下划线。例如,TOD#12:34:56.25表示在12时34分56.25秒。TOD#123456.25是错误的时刻表示。
时刻单位是时、分、秒,没有毫秒单位,但可用小数表示时刻。例如TOD#12:34:56.25中56.25表示56.25秒。由于时刻是一天中的时间,因此,不需要天的时间单位。
时、分和秒的时间数据不能缺省,当最小时间单位没有时,可省略,例如,TOD#12表示12时。
7.日期(Date)
日期用于表示当天是某年某月某日。日期用日期标识符、分界符#和日期表示,表达式为DATE#{year}-{mouth}-{day}或D#{year}-{mouth}-{day}。
年、月、日的开始可以加一个或多个0,例如2005年5月10日,可表示为D#2005-05-10或D#2005-5-10。
日期标识符的长前缀用DATE或date表示,短前缀用D或d表示。因此,D#2008-08-08与DATE#2008-08-08等价。
日期文字中,日期的分界用连字符号“-”,不用冒号“:”或下划线“”。此外,由于表示日期,因此,年、月和日的数据不能缺省。例如,不能表示为D#08-08。
8.日期和时刻(Date and Time)
日期和时刻用于表示某年某月某日某时某分某秒某毫秒的时间。表达式为DATEAND TIME#{year}-{mouth}-{day}-{hour}:{minutes}:{seconds},也可以简写为DT#{year}-{mouth}-{day}-{hour}:{minutes}:{seconds}。
由于它既有日期,又有时刻,因此,需注意时间之间分隔符的不同。
1)年、月和日的分界符,与日期分界符相同,用连字号“-”分界。
2)时、分、秒和毫秒的分界符,与时刻分界符相同,用冒号“:”分界。
3)日期和时刻之间用连字号“-”分界。例如,DT#2008-05-12-14:28:04表示2008年5月12日14时28分04秒。
需要指出的是,以上介绍的4种时间类型的数据表达式中的标识符,其包含的字母的大小写意义相同。例如,Dt#2005-05-19-21:05:8.25表示日期和时刻,toD#15:36:22.25表示一天中的时间等。
9.字符串(Text Strings)
字符串(Text Strings)由单字节字符组成。
单字节字符串由一系列通用的字符表示,或由$'、$''、$与十六进制数字等组成。它们用单引号在其前后标识,如'ABC'、''、'$''、'$'''、'$C4'等。当美元符号与两个十六进制数组成3字节字符串时,应将该字符串的两个十六进制数组成的数对应解释为8位字符码的十六进制数。例如,'$0A'表示LF字符的长度为1的串,它与字符'$L'等效。
用美元符号和单或双引号等组合形成一些特殊字符,具有特定含义,见表3-16。
表3-16 特殊字符
字符串可以是空串,如",单字节字符串用单引号开始,可表示为STRING#' YES '或'YES'。
10.数据类型转换
程序根据数据类型进行适当的操作。例如,赋值表达式的左边和右边通常使用相同的数据类型。然而,在某些情况下,根据需要为变量赋值不同数据类型的数据,例如:
为了将Var1的值赋给Var3,数据必须转换。这种转换的类型称为数据类型转换,或简称为“类型转换”。
数据类型转换通过执行专用的数据类型转换指令来完成,或在赋值和指令中自动转换。
3.4.2 导出数据类型
NJ系列控制器使用的导出数据类型有:结构体、联合体、枚举体。
1.结构体(Structure)
结构体是一种导出数据类型,它将相同或不同类型的数据组合成一个有机的整体,以便于引用。这些组合在一个整体中的数据是互相联系的。例如,描述一个盒子大小的指标有三项:长度(Length)、宽度(Width)、高度(Height),如果将Length、Width、Height分别定义为互相独立的简单变量,是难以反映它们之间的内在联系的。应当将它们组织成一个组合项,在这个组合项中包含若干个相同或不同类型的数据项。根据以上描述,定义一个“BOX”的结构体,它有Length、Width、Height 3个成员。设定一个结构体变量Box1,如图3-60所示,可以这样访问Box1的各个成员:
Box1.Length
Box1.Width
Box1.Height
生成结构体的步骤如下。
1)在数据类型表中生成结构体数据类型
指定数据类型名称、成员和数据类型。
图3-60 结构体变量Box1
可以看出定义两个结构体:RGB和ITEM,ITEM中的成员Color是一个结构体变量,类型为已定义的结构体RGE。
2)指定变量的名称和结构体数据类型,在变量表中登记变量
以上登记了变量Desk、数组ARRAY[0..1],Desk的数据类型为RGB,ARRAY[0..1]的数据类型为ITEM。
如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级地找到最低的一级成员。只能对最低的成员进行赋值或存取及运算。例如,对于上面定义的结构体数组元素Chairs[1],这样访问其成员
Chairs[1].Color.red
Chairs[1].Color.green
Chairs[1].Color.blue
结构体规格见表3-17。
表3-17 结构体规格
可以设置数组,其元素为结构体。也可以设置一个结构体,其成员为数组。
某些指令可以将结构体变量作为其参数。例如,结构体变量的成员和结构体变量都可以作为MOVE指令的参数。
以下是未使用结构体和使用结构体处理数据的对比:
成员变量可以像普通变量一样进行各种运算,根据其类型决定可以进行的运算。
一个结构体变量可以直接赋值给另一个具有相同结构的结构体变量。
2.共用体(Unions)
有时需要使几种不同类型的变量存放到同一段内存单元中。例如,可以将一个16个元素的BOOL数组、2个BYTE变量或一个WORD变量放在同一个地址开始的内存单元中,如图3-61所示,以上3个变量在内存中占的字节数不同,但都从同一地址开始存放。也就是使用覆盖技术,几个变量互相覆盖。这种使几个不同的变量共占同一段内存的结构,称为“共用体”类型的结构,共用体也称为联合体。
图3-61 共用体
生成结构体的步骤如下。
1)在数据类型表中生成共用体数据类型。
指定数据类型名称和共用体成员的不同数据类型。
2)指定变量的名称和共用体数据类型,在变量表中登记变量。
这里,OUT16ACCESS定义为共用体数据类型。这个共用体的成员是一个有16个成员的BOOL数组和一个字变量。变量OUTPUT登记为OUT16ACCESS的数据类型。可以读写变量OUTPUT,OUTPUT作为任意16位的BOOL值和一个WORD值。
Output.BoolData[12]
Output.ByteData[0]
Output.WordData
共用体规格见表3-18。
表3-18 共用体规格
共用体使用时注意:共用体的初始值总是为0;不能传送共用体;不能对POUs指定共用体作为参数。
3.枚举体(Enumerations)
如果一个变量只有几种可能的值,可以定义为枚举类型。所谓“枚举”是指将变量的值一一列举出来。变量的值只限于列举出来的值的范围内。
生成枚举体(ENUM)的步骤如下。
1)在枚举体表中生成枚举体数据类型。
为枚举体设置枚举元素和它们的值。
2)指定变量的名称和枚举体数据类型,在变量表中登记变量。
这里,Color定义为枚举体数据类型。设置3个枚举元素:red、yellow和green。与这些枚举元素相关联的数值为:red=0、yellow=1、green=2。变量DiscColor登记为Color类型。现在,对变量DiscColor可以在三种不同的元素red、yellow和green中选择,相应地又可以为变量DiscColor写出对应的值0、1、2。
枚举体使用时注意以下问题:
1)枚举体元素名称由单字节字母数字型字符组成,不区分大小写。禁用字符的规定与变量名相同。如果不止一次指定相同的枚举体元素,会发生编译错误。如果指定的枚举体元素与用户程序中的变量重名,或者指定的枚举体元素已存在于另一个枚举体,也会出现编译错误。
2)枚举体元素取值的有效范围:-2147483648~2147483647之间的整数。值不必连续。如果指定相同的值超过一次,编译会出错。不能比较枚举体变量长度的大小,只能测试判断枚举体元素是否相同。
3)枚举体元素数目:1~2048个。
3.4.3 数组
数组是按照顺序排列的一组数据的集合。数组中的每一个元素都属于同一个数据类型,可以为整型、字符型、实型等基本数据类型,也可以为结构体、共用体、枚举体等导出数据类型。
数组名定名的规则和变量名相同,遵循标识符定名规则。
数组中的元素用一个统一的数组名和下标来唯一地确定。下标放在数组名后,使用单字节方括号括起来,可以为整数常量或变量,在ST中可用整数表达式表示。
生成数组的步骤如下。
1)在变量表的数据类型列输入“A”,从可选的数据类型名称列表中选择ARRAY[?..?]OF?。
2)在“[?..?]”部分,对应左边的问号,输入数组的第一个元素的序号,对应右边的问号,输入数组的最后一个元素的序号。接下来,在“OF?”部分,对应问号输入数据类型,并登记变量。
这里,定义INT数组变量abc,共有5个元素,如下所示。
数组变量规格见表3-19。
除了一维数组,还可以以同样的方式定义二维、三维数组,数组元素的表示用与维数相同的同样数目的下标。数组最多三维。
表3-19 数组变量规格
两维数组如下所示:
三维数组如下所示:
可以设置数组,其元素为结构体。也可以设置结构体,其成员为数组。
元素为结构体的数组如下:
成员为数组的结构体如下:
有些指令将数组变量作为参数传递,为此,仅指定数组变量的名称作为输入参数。
例如,可用MOVE指令传送单个数组元素,也可传送一个数组。