从tia 博途 v12,s7-1200 v2.0开始,支持db_any类型。
db_any 数据类型用来标识任意数据块。对于 s7-1200,可以选择访问编程期间尚不可用的数据块。为此,在访问块的块接口中创建一个 db_any 数据类型的块参数。数据块名称或先前分配给数据块名称的 db_any 数据类型的变量将在运行期间传送到此参数。
db_any目前有4种用法以及2个隐藏指令:
1. db_any指向非优化db块,可以在程序中使用db_any.%绝对地址。
这种方法lad和scl都可以使用,这种使用方式类似于s7-300/s7-400的block_db,如图1-2所示。
图1 指令详情
scl的版本,如图2所示。
图2 指令scl版本
使用这种方式时注意:
(1) cpu编译时不检查数据类型,可能会出现如图3所示的错误。所以请一定核实数据类型。
图3 错误的数据类型
(2)不检查地址存在与否。如果调用不存在的地址,cpu会报错如图4所示的区域长度错误,所以敬请注意。
图4 区域长度错误
(3)这种绝对地址是不支持变址,例如%dbw[x]不支持。
(4)不支持对符号名的访问,例如input_1.static_1不支持。
db_any作为输入形参,调用参数的时候三种方式:
(1)在db_any参数引脚填写db块号,如图5所示
图5 参数为db块号
(2)在db_any参数引脚填写db块符号名,如图6所示
图6 参数为db块符号名
(3)在db_any参数引脚填写db_any类型的变量,如图7-8所示
图7 参数为db_any类型变量
图8 db_any类型变量的定义
db_any作为输出、输入输出形参,调用参数的时候只能参考图7的方式。
根据(1)中的程序,计算结果都是一样的,如图9所示。
图9 计算结果
2. tia 博途 v13sp1,s7-1200 v4.0开始,如果db_any指向通过plc数据类型(udt)或者系统数据类型(例如iec_timer等)建立的db块
此时s7-1200在scl中提供了两个指令用于db_any和variant类型之间进行转化,如图10所示,如图11-12所示为指令参数:
图10 指令位置
参数 声明 数据类型 说明
in input db_any 待读取的数据块
err output int 错误信息
ret_val return variant variant类型参数
图11 db_any_to_variant参数
参数 声明 数据类型 说明
in input variant variant类型参数
err output int 错误信息
ret_val return db_any 待写入的数据块
图12 variant_to_db_any指令参数
对于这两个指令,注意:
1. db_any类型实参一定是通过plc数据类型(udt)或者系统数据类型建立的db块,否则指令会报错。
2. variant类型指向的变量类型,一定要和db_any指向的建立db块的数据类型相同,否则指令会报错。
3. db_any_to_variant是目前s7-1200唯一可以初始化fc/fb/ob的temp中的variant变量的指令,如果运行正确,则可以使用后续variant处理指令,例如variantget,move_blk_variant,serialize等。
4. 同(3),variant_to_db_any所使用的variant输入,如果来自于fc/fb/ob的temp中的variant变量,也一定是通过db_any_to_variant初始化过的才可以。
5. 如果形参类型是variant的fc/fb/指令,在实参填写了db块,要求该db一定是基于udt或者系统数据类型建立,并且fc/fb/指令将按照udt或者系统数据类型来处理该变量,例如:
这种用法是正确的,输入是udt_1类型建的db,右边是udt_1类型的变量,如图13所示。
图13 正确使用
这种用法是不正确的,输入是udt_1类型建的db,右边是db_any类型的变量,如图14所示。
图14 错误使用
这种方法的使用场合:
如果每种产品有大量数据,有很多种产品,每种产品的数据都是相同结构。可以基于相同结构建立udt,每一种产品基于udt建立db(也可以在一个db中建立udt的数组,但是从变量名处就无法分清哪种变量对应哪种产品)。然后在一个db块内建立db_any的数组,在每个db_any变量的起始值处填写需要指向的db块号。可以通过循环的方式访问每个db_any,将其转化为udt,处理后再送回该db_any。
例子1:db37-db40均为基于udt1建立的db,如图15所示。db36建立数据类型为array[0..3] of db_any的变量,如图16所示,起始值分别是db37,db38,db39,db40。fc22的参数inout为udt_1类型变量,用于数据处理,如图17所示。fc21多次调用fc22,如图18所示。
图15 待使用的db_any引用的数据块
图16 db_any数组及起始值
图17 用于处理udt_1类型变量的fc22(程序略)
图18 程序详情
图19 fc21在ob1的调用
例子2:使用在modbus上的一个例子。
modbus轮询时,通常多次调用modbus_master(或者mb_master),每个modbus_maste使用不同的参数。也可以写成一个modbus_master,这需要在参数中采取变量的形式,但data_ptr这个变量只能采取一种结构、udt的数组,或者二维数组。这种方法可以,但不够灵活,因为每个站点变量大小结构可能各不相同。现在的话可以通过db_any的方式来做到一个完全通用的modbus轮询程序。
前提:tia 博途 v15,s7-1200 v4.2 版本modbus(rtu) v4.0版本,如果不是这些版本,某些功能需要被简化。
1. tia 博途 v14,s7-1200 v4.2 ,则modbus_master的data_ptr只能是非优化块,程序中的static_2只能作为inout。
2. s7-1200 v4.0/v4.1,则array [*] of struct也将不支持,程序中的inout_1需要改为variant,处理程序需要使用move_blk_variant。
例如:
每个modbus_master的站点,需要将其要读/写的数据结构做成udt,并生成对应db块。这里db42是基于modbus_instu 这个udt建立,如图20所示。
图20 modbus从站数据
db43建立struct的数组(最好是udt的数组),其元素包含实际的data_ptr所在db块(参考图20),以及相关的modbus_master参数。这个数组作为fb2的inout,如图21所示。该数组可以根据站点个数决定数组元素个数。
图21 所有从站的参数
fb2为modbus具体程序,inout_1为变长数组,指向图21的数组,如图22-24所示。
图22 fb2参数
图23 程序详情1
图24 程序详情2
图25 程序在ob1中的调用
需要注意的是,例子中使用cb1241,因为是rs485模式,所以下面mode起始值是4,如图26所示。
图26 修改mode
3. tia 博途 v15开始,s7-1200 v4.2开始,增加以下指令,用于db_any变量与数据类型的比较,见表1。
表1 typeofdb指令
lad scl 位置
eq_typeofdb typeofdb 基本指令 -- 比较操作 -- 变量
ne_typeofdb
db_any指向的数据块不限于plc数据类型(udt)或者系统数据类型建立的db块,还可以是to轴的db块,以及fb的背景数据块,见表2。
表2 指令参数
lad指令 操作数1 操作数2 说明
操作数1
┫eq_typeofdb┣
操作数2 db_any 数据类型 比较操作数1对应的db是不是基于操作数2的数据类型建立的,是则该指令返回逻辑运算结果 (rlo)“1”。如果不是则该指令返回 rlo“0”。操作数2的数据类型包括plc数据类型(udt)、系统数据类型、to轴、fb。
操作数1
┫ne_typeofdb┣
操作数2 db_any 数据类型 较操作数1对应的db是不是基于操作数2的数据类型建立的,不是则该指令返回逻辑运算结果 (rlo)“1”。如果是则该指令返回 rlo“0”。操作数2的数据类型包括plc数据类型(udt)、系统数据类型、to轴、fb。
scl指令:typeofdb(操作数),操作数是db_any类型的参数,该语句输出是数据类型,在程序中只能用在if与case进行比较。
用法1:if指令,操作数对应的类型与一个变量类型的比较,例如:
if (typeofdb(操作数1) = 变量类型(例如udt_1))
...
end_if;
用法2:if指令,两个操作数对应的类型比较,例如:
if (typeofdb(操作数1) = typeofdb(操作数2))
...
end_if;
用法3:case of指令,操作数对应的实参的类型与多个变量类型的比较,例如:
case (typeofdb(操作数)) of
udt_1:
...
udt_2:
...
else
...
end_case;
使用举例:
编写fc,检查输入db_any变量类型,udt_1则输出true,其它则输出false,如图27-28所示。
图27 程序详情
scl版本程序,如图28所示。
图28 scl版本程序
4. s7-1200 v4.2开始,db_any可以开始在运动控制中使用
可以使用在形参为to_positioningaxis和to_commandtable类型的实参处,包括以下几种:
(1) 当fc/fb的输入形参数据类型为to_positioningaxis时,外部实参可以使用db_any数据类型的变量。
(2) 在mc_moveabsolute/mc_moverelative指令的参数axis处,实参可以直接使用db_any数据类型的变量。
(3) 当fc/fb的输入形参数据类型为to_commandtable时,外部实参可以使用db_any数据类型的变量。
(4) 在mc_commandtable指令的参数commandtable处,实参可以直接使用db_any数据类型的变量。
与第2条对应的是其他运动控制指令的参数axis,直接使用db_any数据类型的变量,这种用法会报错误,如图29-30所示。
原因是mc_power/mc_reset/mc_home指令的参数axis,类型为to_axis。而mc_halt/mc_movevelocity/mc_movejog/mc_changedynamic指令的参数axis,类型为to_speedaxis。
图29 程序详情
图30 程序在ob1中的调用
诊断缓冲区的报错如图31所示:
图31 报错信息
例子,以(1)和(3)为例,实现功能:fb6判断轴使用的命令表,fb7包含多个轴的fb6功能,如图32-34所示。
图32 fb6的参数设置
图33 程序详情
图34 fb7中循环调用fb6
最后在ob1调用fb7即可
优势:
1. 以往和轴有关的块都需要逐个调用,现在利用db_any和fb的数组,可以用一个循环完成。
2.命令表的类型 to_commandtable只能在input,output以及inout这种外部引脚上,对于需要切换命令表很麻烦,现在用db_any直接在程序内部解决。
5. 隐藏指令
在scl中有两个用于转化的指令,没有放在指令列表中:
db_any_to_uint以及uint_to_db_any,这是db_any和uint类型之间的转化。使用:=同样可以完成它们之间的转化。
在lad中,如果iec检查没有激活,用move指令也可实现db_any和uint类型之间的转化。
这2个指令对db_any指向的db块没有特殊要求。
通过轻型线程提高多核设备中的Linux实时性能
西门子如何看待经济复苏和EDA未来?
基于zynq的IIC驱动的内容和机制
LED灯条调光应用的驱动电源应该如何选择
如何使用Power Design Manager(PDM)进行功耗评估?
S7-1200:DB_ANY类型
DDoS攻击风暴来袭 Memcached成攻击新宠
分享|基于迪文T5L智能屏的净水机智能控制系统方案
添加FPGA终端的步骤方法
基于STM32设计的计算器(实现基本运算)
因为这个,国产首艘航母下水没多久居然大冒黑烟!这个解释你满意吗?
华为海思原来这么厉害,跪了
荣耀V40官方信息配置曝光
蔚来计划自主研发自动驾驶计算芯片 激进还是保守?
康普携手Resonai推进AR技术在智能楼宇领域的应用
三星C7 Pro全面体验评测:细节上做到了大而全
地平线与一汽智能网联开发院签署战略合作协议
IC封装工艺解析
矽品:日月光收购提升国家竞争力的说法禁不起检验
RK3399开发板屏幕切换控制的方式介绍