3. 程序块类型与职责划分
在西门子TIA Portal的S7-1200/1500编程体系中,程序块不是“代码文件的分类”,而是承载不同运行语义、数据生命周期和调用契约的工程对象。OB、FB、FC、DB四类块共同构成一个可执行、可复用、可维护的程序架构。理解它们的语义差异,比记住“OB是主程序、FB带背景数据”这类口诀更重要——因为选型错误往往不会立刻报错,而是在版本迭代、多实例调用或在线修改时集中暴露。
一、四类块的语义定位
OB(Organization Block,组织块)是CPU操作系统与用户程序之间的接口。它不由用户直接调用,而由系统在特定事件发生时触发,例如启动、循环扫描、时间中断、硬件中断、诊断中断等。OB1是默认的循环扫描组织块,其优先级最低,每个扫描周期执行一次。OB的职责是“调度入口”:把不同事件源映射到对应的处理逻辑,而不是承载大量业务算法。一个常见误区是把所有逻辑都塞进OB1,导致扫描周期波动、中断响应被拖慢。
FC(Function,函数)是无记忆的纯逻辑块。它没有背景数据块,输入参数在调用时传入,输出参数在返回时传出,内部临时变量(Temp)在每个扫描周期重新初始化。FC适合表达“给定输入必然得到确定输出”的运算、转换、判断和组合逻辑,例如量程换算、报警字解析、设备互锁条件计算。FC不保存状态,因此不能用于需要记住“上一次值”的场合。
FB(Function Block,功能块)是有记忆的逻辑块。它必须配合背景数据块(Instance DB)使用,静态变量(Static)存放在背景DB中,跨扫描周期保持。FB适合表达“有状态的对象”,例如电机、阀门、PID回路、配方步序。同一个FB可以被多次调用,每次调用分配不同的背景DB,从而形成多个独立实例——这就是“一个FB类型、多个设备实例”的复用模型。
DB(Data Block,数据块)是纯数据容器,分为全局DB和背景DB。全局DB由用户创建,存放共享数据,如配方参数、HMI交互区、报警阈值表;背景DB由FB调用时自动生成,存放该实例的静态变量和背景数据。DB本身不执行逻辑,但它的数据结构决定了FB的接口契约和版本兼容性。
二、调用关系与数据归属
四类块的调用关系可以概括为:OB触发 → FB/FC执行 → DB承载数据。OB是唯一被系统调用的块;FB和FC由OB或上层FB调用;DB不参与调用,只被读写。需要特别注意的是,FC虽然不绑定背景DB,但它可以读写全局DB,因此“无记忆”指的是FC自身不保存状态,而不是它不能访问持久数据。
FB的调用必须指定背景DB。在TIA Portal中,当你在OB1中拖入一个FB时,系统会提示生成一个背景DB,命名通常为“FB名称_DB”。如果同一个FB被调用两次,必须使用两个不同的背景DB,否则两个实例会共享同一份静态数据,导致状态互相覆盖。这是初学者最常见的错误之一。例如,一个“电机控制FB”用于1号电机和2号电机,若共用同一个背景DB,则1号电机的运行标志会覆盖2号电机。
FB内部还可以调用其它FB,形成嵌套调用。此时被调用FB的背景DB可以作为调用者FB的静态变量存在,称为“多重背景”。多重背景的好处是减少独立DB数量,使实例关系更清晰;代价是背景DB的层级变深,在线监视时需要逐层展开。对于设备数量多、结构一致的产线,多重背景是更优的组织方式。
三、选型准则:什么逻辑放什么块
选型的第一判断是“是否需要记住上一次的值”。需要记忆的,用FB;不需要记忆的,用FC。第二判断是“是否被多个对象复用”。如果同一段逻辑要用于多台设备,用FB加不同背景DB,或FC加不同输入参数。第三判断是“是否由系统事件触发”。只有需要独立响应启动、中断、诊断等事件的逻辑,才单独建立OB;普通循环逻辑放在OB1调用的FB/FC中即可。
一个实用的选型顺序是:先识别设备对象,为每个有状态的设备建立FB;再识别公共运算,建立FC;然后识别共享数据,建立全局DB;最后在OB1中按工艺顺序调用FB和FC,并处理启动OB和中断OB。这样得到的程序结构,块职责清晰,后续增加设备时只需增加背景DB和调用,不需要修改已有逻辑。
四、示例:电机控制块的选型与调用
假设一条产线有3台电机,每台需要启停控制、运行反馈、故障报警和累计运行时间。累计运行时间需要跨周期保持,因此必须用FB。定义FB“MotorCtrl”,接口如下:Input:Start、Stop、Fault;Output:Run、Alarm;InOut:RunHours;Static:RunFlag、FaultLatch。在OB1中调用三次,分别绑定背景DB“Motor1_DB”“Motor2_DB”“Motor3_DB”。
// OB1 中的调用示意(梯形图或SCL)
"Motor1_DB"(Start := "I0.0", Stop := "I0.1", Fault := "I0.2",
Run => "Q0.0", Alarm => "Q0.1",
RunHours := "DB_Global".Motor1Hours);
"Motor2_DB"(Start := "I0.3", Stop := "I0.4", Fault := "I0.5",
Run => "Q0.2", Alarm => "Q0.3",
RunHours := "DB_Global".Motor2Hours);
这里“Motor1_DB”和“Motor2_DB”是同一个FB类型的不同实例,各自保存RunFlag和FaultLatch,互不影响。RunHours放在全局DB中,是因为它需要被HMI读取和归档,属于共享数据。如果后续增加第4台电机,只需复制调用并新建背景DB,FB内部逻辑无需改动。
五、常见误区与版本治理关联
第一个误区是“FB背景DB可以随便换”。背景DB的结构由FB接口决定,如果修改FB的Static变量,背景DB需要同步更新,否则在线下载时可能触发一致性错误。第二个误区是“FC可以替代FB”。FC的Temp变量在每个周期重新初始化,用它做状态保持会导致逻辑时好时坏。第三个误区是“全局DB越多越好”。全局DB过多会导致数据归属模糊,版本升级时难以判断哪些数据被哪些块使用。
从版本治理角度看,FB的接口变更影响最大,因为它牵连所有背景DB和调用点;FC的接口变更影响调用点,但不涉及背景DB;OB的变更通常只影响触发逻辑;全局DB的变更影响所有读写它的块。因此,在程序架构设计阶段,应尽量稳定FB接口,把易变参数放入全局DB或FB的Input,而不是频繁修改Static结构。这样在后续版本迭代中,程序块的兼容性和可维护性都会显著提升。