一份可编程控制系统资料写着“调用同一个功能块”,还不能说明它使用了同一份数据。ABB的CODESYS帮助页《Object 'Function Block'》明确区分功能块与实例:功能块通过实例被调用,实例是功能块的一个副本。这个区分让“同一种功能”与“这一次处理的是哪份状态”成为两个问题。

文档首先将功能块定义为执行后产生一个或多个值的程序组织单元。这个定义说明功能块可以给出结果,却没有说所有调用只由当次输入唯一决定。紧接着,原文说明输出变量和内部变量在执行结束后保持不变,直到下一次执行。因此,以相同输入变量多次调用,并不必然返回相同输出。这里的“不必然”需要保留:它既没有保证每次都相同,也没有断言每个功能块每次都会产生不同结果。

实例让这种状态有了具体归属。在“Calling a function block”一节,ABB再次写明,调用始终经由一个实例进行,而且调用时只有相应实例的值发生变化。由此阅读一张资料表,功能块名称可以告诉读者采用哪一种定义,实例身份则指出这次调用对应哪一份数据。把两个实例都简称为功能块名,会省掉原文已经作出的区分,之后也难以说明某项输出究竟属于哪一个对象。

可以设想一个仅用于理解资料的情形:一张说明表列出甲、乙两个实例,二者采用同一功能块类型。仅凭类型相同,不能把两栏已有值自动合为一栏;仅凭一次输入相同,也不能替两个实例补写相同的历史状态。这个例子不是运行记录,没有提供变量声明或调用程序,它只解释为什么类型、实例与当前输入需要各自保留名称。

原页的提示还区分了对外可见范围:从实例外部可以访问输入和输出变量,而非其内部变量。因此,一份只展示输入与输出的摘录,并不因为没有列出内部变量,就证明该实例没有内部状态。外部资料展示了什么,与文档定义中还包含什么,需要分别阅读。本文依据的是ABB这份CODESYS帮助页的定义与调用说明,首次发布日期未另核,不将它扩展为所有软件语言的统一规则。读清两次执行之间所保留的值,能够让调用记录保持对象和状态的归属,而不是只用一个功能块名称解释全部结果。

信息来源

本文基于上述公开资料整理,未使用来源页面的图片、视频或嵌入媒体。