S7-200CN: 不带参数子程序-跟我学 - 127/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=376 |
S7-200CN: 不带参数子程序-跟我做 - 128/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=377 |
S7-200CN: 局部变量的使用-跟我学 - 129/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=378 |
S7-200CN: 局部变量的使用-跟我做 - 130/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=379 |
S7-200CN: 带参数子程序1-跟我学 - 131/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=380 |
S7-200CN: 带参数子程序1-跟我做 - 132/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=381 |
S7-200CN: 带参数子程序2-跟我学 - 133/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=382 |
S7-200CN: 带参数子程序2-跟我做 - 134/185 | https://www.ad.siemens.com.cn/service/elearning/cn/CourseV2.aspx?CourseID=383 |
子程序和中断服务程序都是程序的组织结构,它们和主程序一起被称为POU(程序组织单元)。
在S7-200中,每个POU可以单独加密,保护作者的知识产权。
子程序可以把整个用户程序按照功能进行结构化的组织。一个“好”的程序总是把全部的控制功能分为几个符合工艺控制规律的子功能块,每个子功能块可以由一个或多个子程序组成。这样的结构也非常有利于分步调试,以免许多功能综合在一起无法判断问题的所在;而且,几个类似的项目也只需要对同一个程序作不多的修改就能适用。
有关子程序的详情,请看《S7-200系统手册》相关部分。
中断功能是S7-200的重要功能,用及时处理与用户程序的执行时序无关的操作,或者不能事先预测何时发生的“事件”。
S7-200中使用中断服务程序来响应这些内部、外部的中断事件。中断服务程序需要通过用户编程与特定的中断事件联系起来,才能工作。中断程序与子程序最大的不同是,中断服务程序不能由用户程序调用,而只能由特定的事件触发执行。
无法准确预测何时执行中断服务程序。
在《S7-200系统手册》中有关中断指令的叙述十分详细,建议初学者仔细阅读。
使用子程序时,为何动作只能执行一次,或者某些状态不能结束?
如果发生动作不能重复执行,或者状态不能结束(像锁死了一样),而这些功能都与子程序有关时,请检查是否有条件调用子程序。调用子程序的条件在上述动作执行后,或者进入某个状态后不再有效,无法再次“激活”,而脱离上述状态或复位的指令正好在子程序内,必然造成上述的现象。
另可参见:定时器在条件调用的子程序中
带形式参数的子程序,定义为OUT类型的变量为何会在多次调用子程序时互相干扰?
那是因为定义为 OUT 类型的形式参数并非每次调用子程序时在其内部都有确定的赋值操作。可以将此类参数定义为 IN_OUT 类型,或者确保在每次调用子程序时都有赋值操作。
与中断服务程序有关的计算任务,为何会偶尔得出不正确的结果?
出现这种现象的原因多是在主(子)程序和中断程序之间传递数据的机制不当。
中断程序可能在任何时刻执行,如果此时主程序(或子程序)正在对中断程序使用的数据进行操作,其中间结果可能带入中断程序,造成计算结果的变化;同样地,在中断程序中产生数据也对主(子)程序中的计算有类似影响。
解决办法是保证可能产生中间结果的数据不直接参与计算:
详情请看《S7-200系统手册》的中断指令相关章节。
可以在中断程序中加一个测试程序段,如使用SM0.0(常为“1”)将一个输出点置位(使用Set指令),观察是否进入中断服务程序。
中断程序不执行,多数原因是初始化(连接中断事件和中断程序)的问题,或者没有“开中断”。
应该使用SM0.1(或沿触发)执行一次初始化,然后开中断。
当子程序或者指令的使能管脚前面没有编写任何条件时,编译后会出现一个语法错误,如图.无条件调用指令或子程序 所示:
图.无条件调用指令或子程序
?
上面的编程方式是不被允许的。如果用户希望无条件调用子程序或者指令,可以使用SM0.0作为使能条件,如图.SM0.0作为使能条件 所示:
图. SM0.0作为使能条件
以下面一个简单子程序SBR_0为例,SBR_0将一个IN类型的布尔变量IN1直接连接到一个OUT布尔变量OUT1。在主程序中使用M0.0条件调用SBR_0,如图.子程序输出 所示:
????
?????????????????????????????????????????????? 图.子程序输出
当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。如图.子程序和主程序内容 所示:
???
图.子程序和主程序内容
如果将M0.0复位,M0.2置位,单纯按上升沿捕捉的逻辑,由于没有上升沿跳变,子程序的输出都应该是‘0’。但是在线监控可以看到M0.1持续为‘0’, M0.3保持为‘1’。如图.在线监控 所示:
图.在线监控
上升沿捕捉指令的工作原理是将本次左侧能流过来的‘1’、‘0’信号与上次指令执行时的状态比较,如果检测到从0到1的变化,则导通。每条上升沿下降沿指令都隐含一个布尔数据资源来存储上一次输入信号的‘1’、‘0’状态。在程序段1中,M0.0将上升沿捕捉清零,M0.2不输出。程序段2中M0.2为1,上升沿捕捉指令刚好捕捉到一个由0到1的变化,所以M0.3导通。详细请参考表.上升沿变化:
表.上升沿变化
? |
第一个扫描周期 |
第二个扫描周期 |
||
程序段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 |
?
如果有下面情况产生:
则定时器或者计数器资源会因重叠使用而相互影响,造成程序逻辑等方面的错误。
?
这里首先举例一个子程序SBR_0,该子程序的接口声明一个INT类型的IN变量‘Pressure’和一个BOOL类型的OUT变量‘OPEN’,子程序中只有一个程序段,在程序段1中编写当输入Pressure数值大于500时将输出OPEN置位,如图4.46 子程序输出不正常 所示。
图 子程序输出不正常
??? 这样的子程序被调用后,当输入Pressure达到过500时,输出OPEN被置位;但当输入Pressure从未达到过500时,输出OPEN一直保持为一个未知的状态,可能是1,也可能是0。由于子程序的局部变量仅在本次调用时有效,且每次获取到的局部变量资源有一定的随机性,有可能已经具有一个随机的数据存储在该局部变量地址中,因此对于OUT类型的接口变量,必须保证每次调用程序都对其进行写操作,否则就是编程逻辑的不严密。当然,用户也可以考虑使用IN_OUT变量类型代替OUT变量类型。