3. PLC与结构化编程基础

在进入 GX Works3 的结构化编程之前,必须先理解 PLC 的底层工作方式与 IEC 61131-3 标准之间的关系。很多初学者把结构化编程简单理解为“把程序拆成多个子程序”,但真正决定程序可维护性、可复用性和调试效率的,是 PLC 的扫描机制与标准语言规范共同作用的结果。本节从 PLC 工作原理出发,逐步过渡到 IEC 61131-3 标准,再落到结构化编程的优势与适用场景。

一、PLC 工作原理:循环扫描是理解一切的起点

PLC 采用循环扫描(Cyclic Scan)方式运行,一个扫描周期通常包含四个阶段:输入采样、程序执行、输出刷新和系统通信/自诊断。关键在于:输入采样阶段读取的是输入端子当前状态并写入输入映像区,程序执行阶段只访问映像区,输出刷新阶段才把输出映像区写到实际输出端子。这意味着程序执行过程中输入信号变化不会立即被感知,输出也不会立即变化。

扫描周期的时间由程序规模、指令类型和通信负载决定。对于结构化编程而言,这一点非常重要:把程序拆分为多个功能块后,每个功能块都在同一个扫描周期内按调用顺序执行,因此功能块的执行顺序会直接影响结果。例如,若功能块 A 依赖功能块 B 的输出,则 B 必须在 A 之前被调用。

PLC 循环扫描与结构化程序调用关系 输入采样 程序执行 输出刷新 通信/自诊断 同一扫描周期内的功能块调用 FB_MotorCtrl(电机控制) FB_Alarm(报警处理) FB_Comm(通信交互) FB_HMI(人机界面刷新) 调用

二、IEC 61131-3 标准:结构化编程的语言基础

IEC 61131-3 是 PLC 编程语言的国际标准,它定义了五种编程语言:梯形图(LD)、功能块图(FBD)、顺序功能图(SFC)、指令表(IL)和结构化文本(ST)。其中,ST 语言与高级语言接近,适合编写复杂算法和数据处理;FBD 适合表达信号流和逻辑关系;SFC 适合描述顺序控制流程。GX Works3 对上述语言均提供支持,并允许在同一项目中混合使用。

标准还规定了程序组织单元(POU)的三种类型:程序(Program)、功能块(Function Block, FB)和函数(Function, FC)。程序是主任务入口,功能块带有内部状态和背景数据,函数则无内部状态、每次调用返回一个结果。理解这三者的区别,是结构化编程能否落地的关键。

POU 类型 是否有内部状态 典型用途 GX Works3 中的表现
Program(程序) 有,作为任务入口 主循环、任务调度 可被任务直接调用
Function Block(功能块) 有,带背景数据 电机控制、PID、报警处理 需实例化后调用
Function(函数) 无,纯计算 数学运算、单位换算 直接调用,返回单值

三、结构化编程的优势:从“能跑”到“好维护”

结构化编程的核心思想是分而治之:把复杂的控制任务拆分为若干功能独立、接口清晰的功能块,再通过主程序按逻辑调用。它的优势体现在以下几个方面:

  • 可复用性:一个编写良好的电机控制功能块,可以在多条产线、多个项目中重复使用,只需修改输入参数。
  • 可读性:程序结构清晰,维护人员能快速定位到某个功能对应的代码段,而不必在数千行梯形图中逐行查找。
  • 可测试性:功能块可以单独仿真和测试,降低现场调试风险。
  • 团队协作:不同工程师可以并行开发不同功能块,通过接口约定进行集成。
  • 可移植性:符合 IEC 61131-3 标准的程序更容易在不同品牌 PLC 之间迁移。

关键结论:结构化编程不是“把程序拆小”这么简单,而是通过标准化的 POU 和清晰的接口,把控制逻辑变成可组合、可验证、可复用的工程资产。

四、适用场景与常见误区

结构化编程并非适用于所有项目。对于只有几十个 I/O 点、逻辑简单的小型设备,使用梯形图直接编写可能更高效。但当项目满足以下条件时,结构化编程的优势会非常明显:

  1. 设备包含多个相似工位或重复动作,适合抽象为功能块。
  2. 控制逻辑涉及模拟量处理、PID、运动控制或复杂联锁。
  3. 项目需要多人协作,或后期需要频繁修改和扩展。
  4. 需要与上位机、MES 或其它 PLC 进行通信和数据交互。

常见误区:有些工程师把结构化编程等同于“多写几个子程序”,但功能块之间没有清晰接口、共享全局变量、调用顺序混乱,结果反而比单段梯形图更难调试。结构化编程的前提是接口定义清晰、数据流明确、调用顺序可控。

下面是一个简单的 ST 语言功能块接口示例,用于说明结构化编程中“接口先行”的思路:

FUNCTION_BLOCK FB_MotorCtrl
VAR_INPUT
    Start : BOOL;        // 启动命令
    Stop  : BOOL;        // 停止命令
    Overload : BOOL;     // 过载信号
END_VAR
VAR_OUTPUT
    Run   : BOOL;        // 运行输出
    Fault : BOOL;        // 故障输出
END_VAR
VAR
    RunMem : BOOL;       // 内部运行状态
END_VAR

// 启动优先,停止和过载复位
IF Start AND NOT Stop AND NOT Overload THEN
    RunMem := TRUE;
ELSIF Stop OR Overload THEN
    RunMem := FALSE;
END_IF;

Run := RunMem;
Fault := Overload;
END_FUNCTION_BLOCK

在实际项目中,建议先画出功能块之间的调用关系和数据流,再开始编写代码。这样能避免“写到一半发现接口不够用”的返工。同时,功能块的命名应体现其职责,例如 FB_MotorCtrl、FB_Alarm、FB_Comm,而不是 FB1、FB2。命名清晰本身就是结构化编程的一部分。

总结来看,PLC 的循环扫描机制决定了程序执行的时间边界,IEC 61131-3 标准提供了语言和 POU 的规范,而结构化编程则是在这两者之上建立的一套工程方法。掌握这三者的关系,才能在 GX Works3 中写出真正可维护、可复用的程序。