子程序相互干扰的问题
两个子程序的局部变量和程序完全相同(见下面右图),I0.0为1时Q0.0和Q1.0同时变为1,为什么?
主程序转换为STL后:
LD SM0.0
= L60.0
LD I0.0
= L63.7
LD L60.0
CALL SBR_0:SBR0, L63.7, Q0.0
子程序相互干扰的问题
两个子程序的局部变量和程序完全相同(见下面右图),I0.0为1时Q0.0和Q1.0同时变为1,为什么?
主程序转换为STL后:
LD SM0.0
= L60.0
LD I0.0
= L63.7
LD L60.0
CALL SBR_0:SBR0, L63.7, Q0.0
不同的子程序使用的临时变量区是同一个区域,所以其中一个子程序使用某个地址置位为1后,后一个子程序在调用时该地址仍然为1,所以就直接输出了。
因为你以为set指令不执行的时候线圈会off。然而。set指令不执行的时候是保持线圈原有的状态。
那原有的是什么状态呢?
你设定成了out参数。也就是说进入子程序的时候不对他进行初始化,也就是说仍然保持原值。
那原有的是什么状态呢?
这个值就是L本身的值。这个值是谁给的呢?可以追索到上次调用子程序的是谁。
是子程序自己。(连自己做过的事情都忘记了吗?不会忘的,真的不会忘的。)是 “1”。所以出现了你看见的1。
仔细斟酌上面的过程。你会发现当set指令rst指令在不执行的时候对象的值是不确定的。所以两个指令不可以在多次调用的子程序上用。除非设定成in/out。但是通常这样做都失去set指令的作用。倒不如用out指令代替set和rst。
这其实是个很隐蔽的错误。A侠显然很清楚SET指令的行为。芳侠把问题出在“OUT”类型输出上给点了出来。
1L说得不错,这是因为,当其中一个子程序置1后,L0.1会保留给下一个子程序(同级子程序使用同一片L区),而下一个子程序内的语句无法更新L0.1,所以会输出错误的值。
因此,凡是在子程序中涉及到输出的值,一定要赋值后才能从子程序返回到上一级程序,这是很多人在编程时往往忽略的,我经常也是。
这个问题我编程的时候也遇到过,现在看了芳季老师的讲解,明白了,在300、400中,看到过调用同样的子程序,想在200中也这样编写,但是不行。
假如把SM0.0改成计时器值的比较,可以消除子程序之间的干扰么?
还有就是300的问题,我现在有7路PID控制(采用的是FB41),也是使用的是计时器值的比较,使7路PID循环执行,因为300 的有数据块跟尾,那现在我可以取消计时器了,对么?谢谢
不是很明白楼上问题的意思。干扰是来自重复执行重复赋值的原因,跟使用什么元件无关。
300的不懂。
追问一下,问题我是明白了,但是怎么解决这个问题,我没看懂?
“凡是在子程序中涉及到输出的值,一定要赋值后才能从子程序返回到上一级程序,这是很多人在编程时往往忽略的,我经常也是。”
如何赋值后返回啊?就这个程序说一说,谢谢。
淡定努力
从语句表看,从上到下(严格说是扫描),临时变量一定要先出现写值的语句才出现读值的语句。in量自动由系统在进入子程序时写了值,out量和temp量则只能由用户程序写值。所以,你可以随便使用in量。
借着问题追问一下,不同子程序里面自动分配的地址应该是不会重复的而是独立的,在SBR0和SBR1中都有L0.0和L0.1,系统既然是临时变量自动分配的那么这两个L0.0和L0.1句应该不相同,一个是A房间里面的L0.0和L0.1,一个是B房间的L0.0和L0.1,我觉得这样才对吧!
问题是你接手上一手的工程师走了之后,你坐的是他的办公室呢。你认为老板会额外分配一间新的办公室给你吗?
除非那个工程师未走,你就可以入驻新办公室。对吗?
Plc的安排也是一样。
这个,有必要讨论一下。我的习惯是声明一个临时变量初始化一个一个临时变量,以防止重复调用该块时的数值保留问题。对于临时变量不管FC/FB都有这个问题,因为公用了临时堆栈,所以初始化是很重要很重要的事情。
对于输出,我的习惯是不管FC还是FB不能用(S)(R)。如果要保持输出就用自锁回路。
淡定努力
从语句表看,从上到下(严格说是扫描),临时变量一定要先出现写值的语句才出现读值的语句。in量自动由系统在进入子程序时写了值,out量和temp量则只能由用户程序写值。所以,你可以随便使用in量。
这个当然。
只是“初始化”不同。
A子程序的L区会干扰到B程序的L区吗?只遇到子程序的输出,在子程序退出依然存在的问题,复位就好了嘛!