2016-06-21
一直想写关于S7-1200VARIANT数据类型的使用,正好昨天看见一个帖子“variant数据类型如何做指针寻址?”,借这机会谈一下我在这方面的体会,希望能给大家以帮助。
S7-1200/1500相比S7-300/400,增加了一个重要的数据类型VARIANT,手册这样写:“Variant 数据类型可以指向不同数据类型的变量或参数。Variant指针可以指向结构和单独的结构元素。 Variant 指针不会占用存储器的任何空间。”。看上去和ANY指针有异曲同工之处,在TIA PORTAL手册给出了它们的不同:
我是这么理解的,之所以出现Variant,是因为S7-1200/1500出现了优化块访问这种方式,而P#这种方式无法适应现在的优化块。
对于S7-1200,在V13SP1之前,Variant数据类型除了程序自带的库,基本无法使用。
在V13SP1出现后,增加了若干和Variant相关的指令,其中最有用的我觉得就是MOVE_BLK_VARIANT和Serialize/Deserialize,其他的只是一些判断比较,只有这两个能真正的从Variant提取变量。(VariantGet/VariantPut不提,只能复制完全一样的变量,目前为止没发现太多价值的2个指令)
MOVE_BLK_VARIANT:可以看做S7-1200版的非优化的SFC20。输入输出不限定于优化或是非优化。非优化块之间的复制(如果不写成符号寻址)无所不能,但是只要出现优化块只能是数组或单个变量。输入输出可以是数组名也可以是ANY指针,还可以是单个变量(不一定是数组中的元素),但要求输入输出数组元素或者ANY指针的数据类型一致。通常是用来复制数组的部分元素,也可以解决Variant类型的逐个元素复制,配合循环非常好用。
Serialize/Deserialize:主要用于任意块和非优化块(BYTE数组或BYTE类型的ANY指针)之间的转换。对于这种方法来说,既可以在程序中直接使用,也可以做成通用块(需要一个较大的非优化块),既可以在LAD使用,也可以在SCL使用,还不用考虑Serialize的输入和Deserialize的输出是非优化还是优化块,可以弥补MOVE_BLK_VARIANT不能覆盖的优化UDT的复制转化。和MOVE_BLK_VARIANT类似,利用Variant类型的逐个元素复制,配合循环能实现很多功能。
举个常见的例子,从模拟量模块读入连续多个变量并转化成工程量,在这之前,主要方法是在SCL中用POLK_BLK写,有了这两个指令就不需要了,见下面的例子:
配合数组元素比较类型和元素个数的指令,可以实现程序的通用性。
在这里还需要多说一句:除了EQ_TYPE,EQ_ElemType外,S7-1200中任意非优化变量写成任意ANY指针格式,指令都会将其认作数组。例如一个REAL数组,写成P#INT就会被认为为2倍元素个数的INT数组,例如一个TIME类型,写成P#DWORD,会认为是一个元素的DWORD数组。这点非常有用,根据这个可以轻松实现各种类型的复制,这就是前述MOVE_BLK_VARIANT非优化块之间的复制(如果不写成符号寻址)无所不能的原因。当然AT也可以实现,只是提供一种思路。
有了这些铺垫,就可以回答最前面帖子“variant数据类型如何做指针寻址?”的答案了:
这只是和MB_MASTER相关的程序,大体在这里。在外部实参可以填写任意长度的UDT数组,从而实现程序的通用性。用Serialize/Deserialize也可以实现,就不列举了。
这三个指令功能还很多,有待大家挖掘。
最后再补充一下关于DB_ANY这个类型,这个类型除了DB_ANY_TO_UINT和UINT_TO_DB_ANY以外,几乎和VARIANT捆绑在了一起,我觉得用途不大,毕竟每个VARIANT都是一个DB块,这样往往需要大量的DB块,使用不太方便,不如在一个DB块内建UDT的数组或是一堆UDT来的便捷,当然这是仁者见仁的事,在TIA PORTAL手册P387倒是给出了一个这样的例子,有兴趣的同学可以去看一下。
评论10
楼主 2016/6/21 10:10:11
很不错的心得体会,仁者见仁智者见智,工控巨头西门子引领PLC编程语言的发展。个人觉得这类似C++将C的指针整合成智能指针(《C++ Primer Plus》第六版有不错的介绍)。
楼主 2016/6/24 9:36:43
楼主,运动控制里面有个READ_PARAM这个功能块,Parameter这个引脚就是VARIANT(real)。
但是如果将READ_PARAM封装到FB里面去之后,Parameter这个引脚从FB外面给进来就会出错了。
VARIANT需要好好学习
楼主 2016/6/27 17:25:07
摘抄了一些CSDN上关于变体数据类型年代已久的金句。
1:使用VARIANT来传递参数意味着非强类型语言(例如VBScript)能够调用使用强类型语言(C++)实现的方法。2:VC98,Delphi 2.0均引入了变体类型,能支持所有简单的数据类型,例如整型、浮点型、字符串、布尔型、日期和时间、货币以及Delphi特有的OLE自动化对象等。
3:Variant可以表达不均匀的数组(数组的长度是可变的,它的数据元素能表达前面介绍过的任何一种类型,也可包括另一个Variant数组)。
4:VB中Variant 变量能够存储所有系统定义类型的数据。如果把它们赋予Variant变量,则不必在这些数据的类型间进行转换; Visual Basic 会自动完成任何必要的转换。
楼主 2016/7/4 19:18:31
摘抄了一些CSDN上关于变体数据类型年代已久的金句。
1:使用VARIANT来传递参数意味着非强类型语言(例如VBScript)能够调用使用强类型语言(C++)实现的方法。2:VC98,Delphi 2.0均引入了变体类型,能支持所有简单的数据类型,例如整型、浮点型、字符串、布尔型、日期和时间、货币以及Delphi特有的OLE自动化对象等。
3:Variant可以表达不均匀的数组(数组的长度是可变的,它的数据元素能表达前面介绍过的任何一种类型,也可包括另一个Variant数组)。
4:VB中Variant 变量能够存储所有系统定义类型的数据。如果把它们赋予Variant变量,则不必在这些数据的类型间进行转换; Visual Basic 会自动完成任何必要的转换。