当子程序或者指令的使能管脚前面没有编写任何条件时,编译后会出现一个语法错误,如图.无条件调用指令或子程序 所示:
图.无条件调用指令或子程序
上面的编程方式是不被允许的。如果用户希望无条件调用子程序或者指令,可以使用SM0.0作为使能条件,如图1.SM0.0作为使能条件 所示:
图1. SM0.0作为使能条件
以下面一个简单子程序SBR_0为例,SBR_0将一个IN类型的布尔变量IN1直接连接到一个OUT布尔变量OUT1。在主程序中使用M0.0条件调用SBR_0,如图2.子程序输出 所示:
图2.子程序输出
当M0.0为‘1’时,子程序执行,CPU_输入0有信号时,CPU_输出0有信号输出。此时将M0.0复位,则子程序不再执行,输出OUT1保持子程序最后一次执行的状态,不会被自动复位。
举一个简单的例子,在子程序SBR_0中声明一个布尔类型输入变量和一个布尔类型的输出变量,输入变量IN1通过一个常开触点连接一个上升沿捕捉指令,之后再连接一个线圈输出到输出变量OUT1。在主程序中的网络1和网络2中,连续使用SM0.0作为使能条件两次调用子程序SBR_0,子程序的输入输出分别连接M0.0、M0.1、M0.2、和M0.3。如图3.子程序和主程序内容 所示:
图3.子程序和主程序内容
如果将M0.0复位,M0.2置位,单纯按上升沿捕捉的逻辑,由于没有上升沿跳变,子程序的输出都应该是‘0’。但是在线监控可以看到M0.1持续为‘0’, M0.3保持为‘1’。如图4.在线监控 所示:
图4.在线监控
上升沿捕捉指令的工作原理是将本次左侧能流过来的‘1’、‘0’信号与上次指令执行时的状态比较,如果检测到从0到1的变化,则导通。每条上升沿下降沿指令都隐含一个布尔数据资源来存储上一次输入信号的‘1’、‘0’状态。在程序段1中,M0.0将上升沿捕捉清零,M0.2不输出。程序段2中M0.2为1,上升沿捕捉指令刚好捕捉到一个由0到1的变化,所以M0.3导通。详细请参考表1.上升沿变化:
表1.上升沿变化
|
第一个扫描周期 |
第二个扫描周期 |
||
程序段1 |
程序段2 |
程序段1 |
程序段2 |
|
M0.0 |
0 |
0 |
0 |
0 |
M0.1 |
0 |
0 |
0 |
0 |
M0.2 |
1 |
1 |
1 |
1 |
M0.3 |
1 |
1 |
1 |
1 |
P(上升沿捕捉) |
0 |
1 |
0 |
1 |
4、为什么子程序中的定时器和计数器不工作或者工作不正常?
如果有下面情况产生:
● 一个在内部使用了定时器或计数器的子程序,在同一时刻被调用了多次
● 相同编号的定时器或计数器被多个子程序使用,且同一时刻这些子程序有两个或者以上被调用
则定时器或者计数器资源会因重叠使用而相互影响,造成程序逻辑等方面的错误。
5、为什么子程序的输出不正常?
这里首先举例一个子程序SBR_0,该子程序的接口声明一个INT类型的IN变量‘Pressure’和一个BOOL类型的OUT变量‘OPEN’,子程序中只有一个程序段,在程序段1中编写当输入Pressure数值大于500时将输出OPEN置位,如图5. 子程序输出不正常 所示。
图5. 子程序输出不正常
这样的子程序被调用后,当输入Pressure达到过500时,输出OPEN被置位;但当输入Pressure从未达到过500时,输出OPEN一直保持为一个未知的状态,可能是1,也可能是0。由于子程序的局部变量仅在本次调用时有效,且每次获取到的局部变量资源有一定的随机性,有可能已经具有一个随机的数据存储在该局部变量地址中,因此对于OUT类型的接口变量,必须保证每次调用程序都对其进行写操作,否则就是编程逻辑的不严密。当然,用户也可以考虑使用IN_OUT变量类型代替OUT变量类型。