发现一个子程序调用的问题 点击:1016 | 回复:18



PLC酷客

    
  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:52:53
楼主

发现一个子程序调用的问题


下面是一个很简单的子程序:



如果两次用SM0.0的常开触点调用,发现出现了冲突,大家不妨试试。
对不起,应该发到S7-200的论坛的,是S7-200的问题。



楼主最近还看过



PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:53:04
1楼

把“电动机”换成IN_OUT类型试试。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:53:14
2楼

个人理解,仅做参考:自锁信号一般取主接触器的常开触点作为PLC的输入,用程序内部的OUT作为自锁,感觉有些弊端。#电动机这个局部变量在子程序内部已定义成OUT变量类型了,其实程序对它进行了读和写操作,在多次调用子程序时,冲突就是这个原因。在子程序内部,通常情况下,IN变量最好只进行读操作,OUT变量最好只进行写操作,IN/OUT变量可以进行读写操作。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:53:30
3楼

电动机变量应该设定为INOUT类型,而不能是OUT类型,OUT变量不能把值从外部传入FC中,在300中也是会出问题的。
问题不是一定会出现,但一旦L0.2用到的L区状态被置位后,再调用此FC,就会出现电动机无启动操作而自己启动的情况。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:53:44
4楼

300仿真没有问题,硬件我没有试过。
200按一个启动按钮,两个Q点都要ON,300则不会。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:53:57
5楼

另外,这段程序即使单次调用也会出现不能自锁的情况吧。


单次调用自锁没有问题,我做了实验。


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:54:08
6楼

S7-200的子程序使用临时变量来传递参数,对于OUT类型子程序不会把实参读入形参,所以这里使用OUT形参的触点就出现了临时变量未赋值先使用的情况,换成IN/OUT类型则避免了该问题,而S7-300的FC的参数传递机制又有区别,对于I.Q.M以及非绝对地址引用的DB块数据(如DBX0.0)形参传递的是实参的地址,即访问形参即访问实参,不会经过临时变量,而使用绝对地址引用的DB块数据(如DB1.DBX0.0)时也会使用临时变量来传递参数。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:54:17
7楼

放在300里一样有问题!
300仿真没有问题,硬件我没有试过。
200按一个启动按钮,两个Q点都要ON,300则不会。


          对于模块化编程,是相对于线性化编程而言的,我常常理解成电子电路中的“集成块”,就是把分立元器件按一定标准功能封装在一块,具有输入、输出和公共接口,比如7805三端稳压集成块,有些集成块带有“ROM“,则类似FB这样有静态数据类型。
          IN_OUT类型,是指又有“读”操作,又有“写”操作的块接口类型。在此例中,#OUT就应该定义为IN_OUT类型。这个例子即便在300中实验没有出现问题,不能说明它在300中可以定义为OUT类型。


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:54:28
8楼

S7-200的子程序使用临时变量来传递参数,对于OUT类型子程序不会把实参读入形参,所以这里使用OUT形参的触点就出现了临时变量未赋值先使用的情况,换成IN/OUT类型则避免了该问题,而S7-300的FC的参数传递机制又有区别,对于I.Q.M以及非绝对地址引用的DB块数据(如DBX0.0)形参传递的是实参的地址,即访问形参即访问实参,不会经过临时变量,而使用绝对地址引用的DB块数据(如DB1.DBX0.0)时也会使用临时变量来传递参数。


         youhm侠对PLC的运行机制很透彻呀


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:54:39
9楼

S7-200的子程序使用临时变量来传递参数,对于OUT类型子程序不会把实参读入形参,所以这里使用OUT形参的触点就出现了临时变量未赋值先使用的情况,换成IN/OUT类型则避免了该问题,而S7-300的FC的参数传递机制又有区别,对于I.Q.M以及非绝对地址引用的DB块数据(如DBX0.0)形参传递的是实参的地址,即访问形参即访问实参,不会经过临时变量,而使用绝对地址引用的DB块数据(如DB1.DBX0.0)时也会使用临时变量来传递参数。


如果I.Q.M形参传递的是实参的地址,对于I\Q\M形实参,则不仅OUT变量可以将值传入,IN变量应该也可以将值传出。
目前用PLCSIM测试结果中OUT变量可以将值传入FC中,而IN变量不能将值传出FC。也就是说将启动按钮、停止按钮和电动机都定义为OUT类型,也可以控制电动机的输出,而将启动按钮、停止按钮和电动机都定义为IN类型则无输出。
目前未在PLC上进行测试。


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:54:50
10楼

S7-200的子程序使用临时变量来传递参数,对于OUT类型子程序不会把实参读入形参,所以这里使用OUT形参的触点就出现了临时变量未赋值先使用的情况,换成IN/OUT类型则避免了该问题,而S7-300的FC的参数传递机制又有区别,对于I.Q.M以及非绝对地址引用的DB块数据(如DBX0.0)形参传递的是实参的地址,即访问形参即访问实参,不会经过临时变量,而使用绝对地址引用的DB块数据(如DB1.DBX0.0)时也会使用临时变量来传递参数。
如果I.Q.M形参传递的是实参的地址,对于I\Q\M形实参,则不仅OUT变量可以将值传入,IN变量应该也可以将值传出。
目前用PLCSIM测试结果中OUT变量可以将值传入FC中,而IN变量不能将值传出FC。也就是说将启动按钮、停止按钮和电动机都定义为OUT类型,也可以控制电动机的输出,而将启动按钮、停止按钮和电动机都定义为IN类型则无输出。
目前未在PLC上进行测试。


          你是用梯形图测试的吧,你转换成STL会有所发现。


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:55:05
11楼

单次没有问题?,多次就有问题了,用??IN_OUT类型,是指又有“读”操作,又有“写”操作的块接口类型,

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:55:14
12楼

应该是: 结果不一定正确,但是有可能是正确的!
从语法上使用,“电动机”这个变量一定要用IN/OUT类型!
曾经做过一台设备,和这个情况非常非常类似! 也是一个本该使用IN/OUT类型的数据,结果“不小心”选择了IN,设备发到现场使用一个多月都正常。一个多月后就偶尔会不正常。 当时找问题头发都多白了几根,呵呵。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:55:21
13楼

“电动机”是个OUT类型的临时变量,不能用于自保持。因为每次子程序执行完毕时都会释放临时变量,释放后临时变量的状态是不确定的,因此自保的就无法自保了。每次调用子程序时,又会重新分配临时变量。
单次调用可能不出问题,多次调用一定不行。300的FC中也一样会出这个问题。这是个常问的老问题了。
在200中,只能用IN/OUT类型让子程序的中间状态自保或置位,外面用v地址赋值。在300中,这个自保的变量应该用静态变量,然后再输出给OUT变量。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:55:33
14楼

S7-200的子程序使用临时变量来传递参数,对于OUT类型子程序不会把实参读入形参,所以这里使用OUT形参的触点就出现了临时变量未赋值先使用的情况,换成IN/OUT类型则避免了该问题,而S7-300的FC的参数传递机制又有区别,对于I.Q.M以及非绝对地址引用的DB块数据(如DBX0.0)形参传递的是实参的地址,即访问形参即访问实参,不会经过临时变量,而使用绝对地址引用的DB块数据(如DB1.DBX0.0)时也会使用临时变量来传递参数。
如果I.Q.M形参传递的是实参的地址,对于I\Q\M形实参,则不仅OUT变量可以将值传入,IN变量应该也可以将值传出。
目前用PLCSIM测试结果中OUT变量可以将值传入FC中,而IN变量不能将值传出FC。也就是说将启动按钮、停止按钮和电动机都定义为OUT类型,也可以控制电动机的输出,而将启动按钮、停止按钮和电动机都定义为IN类型则无输出。
目前未在PLC上进行测试。
          你是用梯形图测试的吧,你转换成STL会有所发现。



是了,实际上300梯形图将IN型变量先赋给L变量,再以L变量作为实参调用FC块,导致IN类型实参在梯形图状态下无法把值传出来。


PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:55:59
15楼

下面是西门子的一个资料里有关FC的基本数据类型的参数传送机理的图:



下面是有关的文字说明:
传递机理  
        随着调用指令CALL,STL/LAD/FBD编辑器首先根据参数列表中给出的实际参数,计算交叉区域指针,并在FC调用指令之后立即存贮这些指针。
 此时,如果在该FC内部访问形式参数(比如:A On_1),CPU就根据存储在B堆栈中的返回地址确定该FC调用指令。然后根据相关的参数列表,FC就可确定与形式参数对应的实际参数的交叉区域指针。于是,通过这个指针就实现了对实际参数的访问。
 这种传递机理与“按引用调用”相一致,如果在某一FC中访问了形式参数,那么,结果也访问了相应的实际参数。 .
 这种通过指针的访问机理要求:
 ? 在FC调用中,所有的块参数都必须赋值。
 ? 在参数声明里,不能对块参数进行初始化。
注意事项
        如果是用DB中的实际参数来对块参数进行赋值,或者传递的是复杂类型参数,那么,参数传递将变得更加复杂。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:56:13
16楼

下面的文字来源于STEP7的FC的在线帮助。

将实际参数分配给形式参数:
FC所使用的输入、输出以及输入/输出参数作为指针保存到调用FC的逻辑块的实际参数中。
通过地址(指针跨过区域边界指向目标)访问FC参数。当数据区(数据块)地址或调用块的局部变量用作实际参数时,实际参数的副本将临时保存到用于传送参数的调用块的本地数据区中。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:56:31
17楼

临时变量就是形参,用c语言的定义来解释更容易理解。
在未出现函数调用时,形参不占内存中的存储单元。只有发生函数调用时函数中的形参才被分配内存单元。在调用结束后,形参所占的内存单元也被释放。
换句话说,当子程序没被调用时,子程序中的临时变量就当它不存在,因此也不可能自保。只有把用作自保的临时变量换成静态变量或背景数据块,才能自保持。

PLC酷客

  • [版主]
  • 精华:9帖
  • 求助:31帖
  • 帖子:1460帖 | 7990回
  • 年度积分:457
  • 历史总积分:59176
  • 注册:2004年7月13日
发表于:2013-12-02 16:56:42
18楼

单次调用自锁没有问题,我做了实验。


          在C、VB等计算机语言中,声明局部变量时,可以加上static,凡是static局部变量,和全局变量一样,占有固定的存贮区域,不随子程序的执行终止而消失。而在 S7200中,没有对应Static类似的局部变量,一般来说是不能够在子程序多次调用时局部变量自身保留值的。但是也有巧合的时候。当整个程序只有一个子程序,或某一局部变量只有一个子程序同级调用时使用,这相当于该局部变量对该子程序具有了“static”属性,多次调用之间“实现”了值的保留。



热门招聘
相关主题

官方公众号

智造工程师