3. PLC程序结构与单元测试切入点

在产线单元测试与虚拟调试中,PLC程序结构决定了“哪些部分可以单独拿出来测、哪些必须联调”。如果程序组织混乱,测试就只能整机跑,问题定位会非常困难。因此,理解OB、FB、FC、DB的组织方式,并据此识别可独立测试的功能块与耦合边界,是单元测试设计的第一步。

一、OB/FB/FC/DB的组织方式与测试含义

西门子PLC(以S7-1200/1500为例)的程序结构由四类基本元素构成,它们各自承担不同职责,也对应不同的测试策略。

OB(组织块)是操作系统与用户程序的接口,决定程序的执行时机和优先级。常见OB包括:OB1(主循环)、OB100(启动)、OB35(循环中断)、OB82(诊断中断)等。OB本身通常不包含复杂逻辑,而是调用FB/FC。测试时,OB的“可测性”较低,因为它依赖扫描周期和硬件事件,一般通过仿真或在线监控验证调用关系是否正确。

FB(功能块)是带背景数据块的功能单元,具有“记忆”能力,适合实现状态机、步序控制、PID等需要保持状态的逻辑。FB的测试价值最高:只要给定输入和背景DB的初始状态,就能在仿真环境中独立运行,观察输出和状态变化。

FC(功能)是无记忆功能的函数,适合实现数学运算、逻辑组合、数据转换等纯逻辑。FC的测试更简单:输入确定则输出确定,不依赖历史状态,适合做单元测试中的“纯函数”验证。

DB(数据块)分为全局DB和背景DB。全局DB用于存储共享数据,背景DB与FB实例绑定。DB本身不执行逻辑,但它是耦合的重要来源:多个FB/FC读写同一个全局DB时,就形成了数据耦合,测试时必须考虑数据初始化和隔离。

测试切入点判断原则:FB和FC是单元测试的主要对象;OB负责调度,通常不单独测试;DB是耦合载体,需要识别其被哪些块读写。

二、状态机与步序控制的测试切入点

产线单元中,设备动作通常由状态机或步序控制实现。例如一个“气缸伸出—到位检测—缩回”的单元,其FB内部可能包含Step0~Step5的步序。测试这类FB时,不能只看最终输出,而要验证每一步的转移条件。

以一个典型步序FB为例,其内部结构如下:

FB "CylinderCtrl"
VAR_INPUT
    Start : Bool;        // 启动命令
    SensorOut : Bool;    // 伸出到位传感器
    SensorIn : Bool;     // 缩回到位传感器
    FaultReset : Bool;   // 故障复位
END_VAR
VAR_OUTPUT
    ValveOut : Bool;     // 电磁阀输出
    StepNo : Int;        // 当前步号
    Error : Bool;        // 故障标志
END_VAR
VAR
    Step : Int := 0;     // 内部步序
    Timer : TON;         // 超时定时器
END_VAR

该FB的步序逻辑可概括为:Step0等待Start;Step1输出ValveOut并启动超时定时器;Step2等待SensorOut;Step3关闭ValveOut;Step4等待SensorIn;Step5完成复位。测试时,可以构造输入序列,逐拍推进,观察StepNo和ValveOut是否符合预期。

这里的关键是:状态机的每个状态和转移条件都是可独立测试的。例如,只测试“Step1超时未收到SensorOut时,Error是否置位”,不需要真实气缸动作,只需在仿真中强制SensorOut保持FALSE并推进定时器即可。

三、识别可独立测试的功能块与耦合边界

并非所有FB都能独立测试。判断标准是:该FB的输入输出是否完整、是否依赖外部全局数据、是否依赖其他FB的运行结果。

可独立测试的FB通常具备以下特征:输入输出接口清晰;状态保存在自身背景DB中;不直接读写其他FB的背景DB;不依赖硬件I/O的实时值(可通过仿真强制)。

耦合边界则出现在以下情况:多个FB共享同一个全局DB;FB之间通过全局DB传递中间结果;FB调用其他FB并依赖其输出。此时,单元测试需要构造“桩”或“替身”,或者将耦合部分一起测试。

下面这张图展示了一个产线单元的程序结构、数据耦合关系以及推荐的测试切入点。图中左侧为OB调度层,中间为FB/FC功能层,右侧为DB数据层;虚线表示耦合边界,绿色标记表示可独立测试的块,橙色标记表示需要联调或构造桩的块。

产线单元PLC程序结构与测试切入点 OB 调度层 OB1 主循环 调用FB/FC OB100 启动 初始化DB OB35 循环中断 高速计数/PID OB82 诊断中断 故障处理 FB / FC 功能层 FB 气缸控制 状态机/步序 ✓ 可独立测试 FB 输送带控制 启停/调速 ✓ 可独立测试 FC 数据转换 标定/换算 ✓ 可独立测试 FC 报警处理 逻辑组合 ✓ 可独立测试 FB 单元协调器 调用气缸/输送带FB,读写全局DB ⚠ 需联调或构造桩 DB 数据层 全局DB 共享状态/参数 背景DB FB实例状态 背景DB FB实例状态 耦合边界 可独立测试 需联调/构造桩 数据读写

四、从结构到测试用例的映射方法

识别出可独立测试的FB后,下一步是将其转化为测试用例。以“FB 气缸控制”为例,可以设计如下测试序列:

测试编号 初始状态 输入激励 预期输出/状态 验证点
TC-01 Step=0, Error=FALSE Start=TRUE Step=1, ValveOut=TRUE 启动转移正确
TC-02 Step=1, Timer运行中 SensorOut=TRUE Step=2, ValveOut保持 到位检测转移
TC-03 Step=1, Timer超时 SensorOut=FALSE Error=TRUE, Step保持 超时故障处理
TC-04 Step=4, SensorIn=FALSE SensorIn=TRUE Step=5, 完成标志 缩回到位完成

这些用例可以在PLCSIM或虚拟调试环境中执行,不需要真实气缸。测试时,通过强制输入变量、监控StepNo和ValveOut,即可判断FB行为是否符合设计。

五、耦合边界的处理策略

当FB之间存在耦合时,单元测试需要采取不同策略。常见做法有三种:

  • 构造桩模块:用简化的FC或FB替代被调用的块,只返回固定值或简单逻辑,使被测FB可以独立运行。
  • 数据隔离:为被测FB分配独立的背景DB,避免与其他实例共享全局DB。测试前初始化DB,测试后检查DB变化。
  • 联合测试:当耦合过于紧密、拆分成本过高时,将相关FB作为一个测试单元,一起验证输入输出关系。
注意:不要为了追求“单元独立”而强行拆分本应协同工作的FB。耦合边界的选择应基于实际测试收益,而非教条。

在实际产线单元中,建议先按“设备动作”划分FB,再按“数据共享”识别耦合。例如,气缸FB和输送带FB如果都读写同一个“单元状态DB”,则它们之间存在数据耦合,测试时需要确保DB初始状态一致,或使用独立的测试DB。

总结来说,OB/FB/FC/DB的组织方式决定了测试的粒度:OB负责调度,不单独测试;FB和FC是单元测试的核心;DB是耦合的载体,需要识别并隔离。状态机和步序控制提供了天然的测试切入点——每个状态和转移条件都可以独立验证。通过构造输入序列、监控状态变量、判断输出结果,可以在虚拟调试环境中高效完成单元测试,为后续联调打下基础。