广东湘恒智能科技有限公司
主营产品: 西门子变频器,西门子PLC\西门子模块、西门子触摸屏、西门子伺服电机、西门子工控机、西门子集成系统、西门子低压、西门子控制单元、西门子CPU,广东省西门子授权代理商,等
Smart200如何写出可重复调用的子程序
发布时间:2024-11-14

200Smart是日式风格的小型PLC,其函数用子程序来实现,叫做SBR。SBR类似于TIA平台1200的FC,没有自己的私有数据。

SBR的用来实现一些不需要保留私有数据的一次调用函数功能,比如一次性的数学计算,如果需要使用前几次的计算结果,通常可以使用几种方式传入SRB,一种是使用接口的InOut,另一种是不使用接口而是直接使用全局变量。但直接使用全局变量的缺点除了不能模块化,还有不能被重复调用(无法实现多个实例)。

常规意义上来讲SBR多次调用需要注意很多问题。我们与1200比较,1200有DB,1200的FC可以使用DB来区分不同的实例。而200Smart的子程序就只能靠设计者自己来规划不同的V区来区分不同的实例。

多次调用还有很多和语法特点有关的注意事项,比如沿指令,在SBR多次调用中就不能使用。其他更让人头痛的指令是定时器,当然定时器不论是SBR中还是在主程序里都不能多次调用,这个不是SBR的问题,但通常也会伴随子程序多次调用出现更多问题,例如:

1,将使用了实际软元件的FB程序在OUT指令中的多个位置使用时,将变为双重线圈。

2,使用了实际的软元件的FB程序在多个位置被调用时,有可能无法正常动作。

归根到底,200Smart子程序的问题就是V区变量规划问题,它给设计者带来了更多和编程无关的管理工作。通常你需要准备几张纸来手动规划V区。无论是采用电子表格还是纸,随着设计的推进,修改V区修改已经调试好的模块是初学者面临的棘手而繁琐的工作。

在论坛上有篇帖子给我带来了一些解决200Smart如何才能让SBR具有类似FB背景数据块的实现方案思路。

具体来说就是分配出不同尺寸的连续的V区域,每个区域由一个索引来唯一定位,这样只要知道了索引就能定位这个区域。每个区域就是一个背景数据块,可以被SBR分配使用。

以ST20来说,V区共计8190个字节,如果背景DB需要使用3000个字节,那么开始地址大约是从VB5000开始的。这里面包括了之后要设计的管理段,实际分配给SBR使用的背景DB容量小于这个数量。这些关于DB开始位置、容量、以及适配不同型号PLC的V区*后地址的参数可以被修改而无需修改管理程序。

有解决思路,那如何知道子程序要使用哪个DB呢?

工作中我见过德国人的解决思路,需要在每次扫描过程中保证每个子程序按照既定的顺序来执行,不能出现条件调用子程序的情况存在。说白了就是在调用程序之前规划好的V区地址(假设VB800-VB900)存入FC中对应的临时变量中,FC中都使用该临时变量来进行逻辑运算或存储结果数据,*后再将携带着结果数据的临时变量写入到规划好的V区变量中(VB800-VB900)中,接下来的子程序使用的VB800-VB900也就是刚才调用子程序所使用的DB块了,接下来进行详细说明。



图片

FC第一行Load Data




图片

FC*后一行Save Data




图片

FC中使用DB



SBR如何知道要使用哪个DB?需要在SBR接口的InOut处设计一个索引参数(DB_Index),这个索引定位了DB。如果该子程序是第一次被执行,索引接口变量就从索引资源变量(IndexSource)处取得当前可以使用的索引,索引资源自加一,以便下个SBR分配索引。如果不是第一次被调用,则不会再分配索引,而是使用原来的索引值,也就定位了同一个DB。

SBR内已经定位了DB,要怎么使用该DB呢?可以有两种使用方式:

一种是复制DB数据到SBR临时变量区,在Temp区使用的好处是可以用符号变量操作。使用完毕在退出子程序前把同一个Temp内容复制回DB区就实现了犹如在DB区中使用数据一样的效果。

第二种使用方式是直接在DB上操作数据,由于并不知道该SBR使用的DB地址,也就不能开始就设计好符号变量(事实上可以开始就设计好符号变量,后面有叙述。),所以直接使用就是用指针操作数据。由于指针操作存在很多不便性,所以这种方式主要用于使用指针显得很方便的场合,比如数组操作之类。

随着背景DB实现程序的设计推进,使用DB的方式这两种都有采用,针对不同的应用场景有不同的使用方式。比如,如果子程序的Temp区足以容纳需要的数据,就使用Temp操作;如果SBR的Temp容量小需要更多的存储区,就把多余的部分使用直接在DB中操作。如果接口比较多,需要使用更多的接口数量,就使用事先设计好DB中的符号变量,直接操作符号变量的方式,在遵循一定的设计顺序后就可以在该方式下也实现多个实例化。

实现的代价

要想实现上述功能,牺牲V区的一些空间和增加程序代码的数量、增加扫描时间是必然的代价,其中,牺牲V区空间其实是谈不上的,V区通常足够大,一般来说不用白不用,用了不白用。*主要的增加了代码体积和增加了扫描时间。在不增加其他功能,单纯一个做好的具有背景DB功能的空白模板,编译后块大小是2657字节。

200Smart的接口数量是有限的,只有16个IO接口,超出限制将不能正常添加形参。有人说可以把多个bit形参组合成Byte、Word、DWord之类,确实有效,但这个不是讨论的重点,所谓曲线救国毕竟是曲线呀。要怎么做呢?当然是使用指针了,也就是全局V区作为SBR的形参,可这还是需要人工规划不同的V区来适用不同的实例,没有解决根本问题。

既然已经有了可以自动分配和定位的DB,那么规划出几处特殊的DB来作为扩展接口的数据块。同一种类型的实例使用同一个DB,在DB中事先设计适用于同一个类型的接口变量形参,这样SBR内部直接使用DB内的变量形参,不用更改。那如何才能适用于同一类型的多个实例呢?我想到了子程序内部使用的Temp变量运行机制。200Smart子程序的临时变量区其实只有一个,是公共使用的。也有资料表明200Smart的Temp区一共14个,这涉及到200Smart的嵌套层级,这个和我想到的实现无关,只要想到这些就足够了。

我的实现方案是设计14个特殊用途的DB,用来作为Temp区使用,命名和子程序内的Temp冲突,但只要知道这个和子程序Temp是不同的概念就可以了。为了区别,以下暂且称为DBTemp吧。DBTemp的用途一方面是由于SBR内部还是有需要使用全局变量的情况出现无可避免,比如......(想不起来了,大概跟指针反引用有关),如果需要,则把这些数据用某个DBTemp内的预先定义的变量替代,只要使用前后让这个DBTemp进行FIFO操作,这样无论SBR何时执行都能够正确操作。这样就需要设计DBTemp的FIFO算法。设计14个DBTemp也和之前提到的嵌套有关,其实加入背景数据块后会降低嵌套深度,因为背景数据块管理程序需要调用一级子程序,如果需要使用背景DB则留给用户的嵌套深度是7级主循环嵌套调用。

考虑到其实实际项目中很少有需要使用全部14层级的情况,所以我安排用*后4个DBTemp作为SBR扩展IO接口。4个也就是只有4类子程序需要扩展接口。之所以是4个,主要是考虑到可能需要扩展的类型有限,使用原来的16个接口就可解决大多数类型的设计,这也是实验阶段目标所导致的,如果需要可以修改少量代码就可适配。

使用时首先按照FIFO原则先指定需要使用的DBTemp编号入队,以保护前面使用者的数据不丢失,然后给DBTemp内的SBR形参赋实际参数值,然后调用SBR。调用完毕处理DBTemp内的需要输出的参数,*后出队,恢复前面使用者的数据。这里涉及到接口类型,作为扩展接口的参数全部类同于InOut类型,Out和InOut需要调用完毕及时转存,而In需要设计者自己保证不会破坏原有数据。

那么DBTemp每个的容量选择多少合适呢?我设计了50个字节长度,这个可以在DBInit模块使用参数进行调整。

而背景数据块设计了255个DB可以使用,也是可以在DBInit模块使用参数进行调整。

管理模块的设计

管理堆表头设计

在V中分配的背景DB需要有一些空间来容纳管理变量,我把这些变量放置到了开头,称作管理DB的表头。

这些表头信息是:

pHeapHead 指向自身的堆指针,也是Heap首地址。

HeapStatus 堆状态信息。

DBCap 数据块预置容量

DBLen 数据块实际使用长度

pDBTerminal 数据块终点地址

pDBVector 数据块头指针

IndexSource 索引资源

指定数量的全局数据块索引

表头和DB之间的分隔符"#"

这些变量的作用涉及到许多技术实现细节,以后慢慢添加。

之后是数据块,不过头两个DB块是特殊用途DB的管理块,本质上这两个DB和之后的几个特殊用途DB都是数据块,只不过由管理程序使用,分配用户DB也不会用这几个块空间来分配。

1,数据块的结构

每个数据块的第一个字是DB容量,这个由DB分配程序来读写,用户不用操心。
之后是一个字节的DB标志符"FF",这个是方便调试而设计的,并无多大作用,也是设计遗留下来的东西,唯一的作用是可以帮助分辨DB开始。

这个标识符唯一不存在于接下来的一个DB。

然后才是真正的DB数据。

2,Temp块管理DB的设计

Temp块管理DB管理的其实不只Temp块,还硬塞进来了FIFO队列。 FIFO队列后是14个存放DBTemp的指针向量。DBTemp动态分配,这些指针表在DBTemp初始化时自动生成。由于设计也是逐步推进的,这里采用直接存放4字节的指针,而不是像接下来的用户DB指针表存放的是V编号,也就是指针的低字数据。

3,用户DB指针表(用户DB管理表)的设计

用户DB的定位采用的是遍历定位方式,但考虑许久还是专门设计出一个DB来存放用户DB开始的指针数据,这样DBIndex不是直接定位用户DB,而是首先定位这个表的数据,然后提取数据作为指针来直接定位用户DB。好处是代码量少些,也可能执行起来快速些。

用户DB不是一开始就规划好的,而是动态分配的,位置、尺寸都是动态由子程序自己所需DB尺寸自动生成的。

4,DBTemp块的设计

DBTemp共计14个,每个都具有用户指定的大小,比如50个字节。没有内部特殊结构,和普通DB没有区别。

用户可以使用的普通数据块

共计255个容量,每个的大小不同,由用户子程序决定


展开全文
拨打电话 微信咨询 发送询价