4、FB功能块核心概念:实例、输入输出参数、静态变量、内部变量、调用机制与执行逻辑
在PLC结构化编程体系中,功能块(Function Block,FB)是复用逻辑与封装工艺的核心载体。与函数(FC)不同,FB拥有独立的存储区,能够“记住”上一次调用的状态,这一特性使其在电机控制、阀门调节、温度PID等需要保持历史状态的场景中具有不可替代的价值。理解FB的实例化机制、变量分类与调用执行逻辑,是掌握结构化编程从“会写”走向“会设计”的关键分水岭。本章将围绕FB的六大核心概念展开深度拆解,帮助读者建立从声明到调用的完整认知闭环。
4.1 实例与实例化机制:从模板到数据副本
4.1.1 核心原理:FB定义与实例的本质区别
FB的定义(类型)相当于一份“图纸”或“模板”,它描述了功能块的输入输出接口、算法逻辑和内部数据结构。而实例则是根据这份模板在PLC内存中创建的具体“数据副本”。每个实例都拥有独立的背景数据块(Instance DB),用于存储该实例的静态变量、输入输出参数的当前值。这意味着,同一个FB类型可以被实例化多次,每次实例化都会分配独立的内存区域,互不干扰。
以电机控制为例,若设备上有4台相同型号的电机,只需编写一个“Motor_Control”FB,然后创建4个实例(如Motor1、Motor2、Motor3、Motor4)。每个实例的启动命令、当前转速、故障状态等数据都存储在自己的背景DB中,但执行的控制逻辑代码是共享的。这种“代码共享、数据独立”的机制,是FB实现高效复用的根本原因。
4.1.2 判断方法:如何确定需要多少个实例
在实际工程中,确定实例数量需遵循以下步骤:
- 识别被控对象:统计现场具有相同控制逻辑的设备数量,如阀门、泵、变频器等。
- 分析差异性:若设备之间存在参数差异(如不同电机的额定电流不同),可通过输入参数传递差异值,无需创建不同FB。
- 评估存储资源:每个实例的背景DB会占用PLC的装载存储区和工作存储区。对于中小型PLC(如S7-1200),需注意DB总大小限制。
- 考虑扫描周期:实例数量越多,每个扫描周期内FB被调用的次数越多,CPU执行时间相应增加。需评估CPU的扫描周期是否满足工艺要求。
4.1.3 案例拆解:多轴定位系统的实例化设计
某包装机械需要控制6个伺服轴完成同步定位。工程师设计了一个“Axis_Control”FB,包含使能、目标位置、速度、加速度等输入参数,以及当前位置、到位标志、报警代码等输出参数。通过创建6个实例(Axis1至Axis6),每个实例在背景DB中独立存储各自的设定值和实际值。在OB1中按顺序调用6次该FB,每次传入不同的背景DB和轴参数。这种设计使程序代码量减少约70%,且新增轴时只需复制调用代码并分配新DB即可。
4.1.4 常见误区与总结
- 误区1:将FB当FC使用——不创建实例直接调用,导致静态变量无法保持,逻辑混乱。
- 误区2:实例数量过多——超出PLC存储限制,导致编译失败或下载异常。
- 误区3:忽略背景DB的保持性设置——在断电保持需求下,需在DB属性中勾选“保持”选项,否则PLC重启后实例数据丢失。
总结:实例化是FB复用的基础,合理规划实例数量与命名规则,是结构化编程的第一步。
4.2 输入输出参数:接口设计与数据交互
4.2.1 核心原理:参数的类型与传递方式
FB的输入参数(VAR_INPUT)和输出参数(VAR_OUTPUT)构成了与外部程序交互的接口。输入参数在调用时由调用者提供值,输出参数在FB执行完毕后将结果返回给调用者。此外,还有输入输出参数(VAR_IN_OUT),它允许FB直接读写调用者的变量,适用于需要修改外部数据的场景。
参数传递遵循“值传递”原则:输入参数在调用开始时被复制到FB的局部存储区,FB内部对输入参数的修改不会影响调用者的原始变量。而VAR_IN_OUT参数传递的是变量的地址,FB内部对该参数的修改会直接反映到调用者的变量上。
4.2.2 设计方法:参数接口的规范化设计
| 参数类别 | 命名建议 | 数据类型选择 | 典型应用 |
|---|---|---|---|
| 输入参数 | i_前缀(如 i_StartCmd) | Bool、Int、Real、Time | 启动命令、设定值、使能信号 |
| 输出参数 | o_前缀(如 o_CurrentSpeed) | Bool、Int、Real、Word | 状态反馈、实际值、报警代码 |
| 输入输出参数 | io_前缀(如 io_ErrorCode) | 任意类型 | 累计值、故障字、模式切换 |
设计原则:接口应尽量精简,避免过多参数导致调用复杂。对于超过5个输入参数的FB,建议使用UDT(用户自定义类型)将相关参数打包,提高可维护性。
4.2.3 实战场景:PID温控FB的参数封装
设计一个“PID_TempCtrl”FB,输入参数包括:i_Setpoint(设定温度)、i_ActualTemp(实际温度)、i_Kp、i_Ki、i_Kd(PID系数)、i_SampleTime(采样周期);输出参数包括:o_Output(控制输出)、o_Error(偏差)、o_Status(运行状态)。通过VAR_IN_OUT参数io_IntegralAcc传递积分累计值,使FB在多次调用间保持积分状态。这种设计使FB既可用于不同温区,又可通过调整PID参数适应不同热惯性对象。
4.2.4 常见误区与总结
- 误区1:滥用VAR_IN_OUT——频繁使用VAR_IN_OUT会降低程序可读性,且不利于FB的独立测试。
- 误区2:参数类型不匹配——调用时传入错误数据类型,导致编译错误或运行时数据转换异常。
- 误区3:忽略参数的初始值——未设置输入参数默认值,在HMI未赋值时可能导致FB误动作。
总结:输入输出参数是FB与外部世界的“桥梁”,规范化的接口设计能大幅提升FB的通用性和可维护性。
4.3 静态变量与内部变量:状态保持与临时存储
4.3.1 核心原理:两类变量的本质区别
静态变量(VAR)存储在背景DB中,在FB多次调用之间保持值不变。它们用于记录FB的“记忆”,如当前状态、累计值、上次输出值等。内部变量(VAR_TEMP)存储在PLC的局部数据堆栈(L堆栈)中,仅在FB本次调用期间有效,调用结束后即被释放。内部变量用于存储临时计算结果,如循环计数器、中间运算值等。
理解这一区别至关重要:若将需要保持的数据错误地声明为VAR_TEMP,则每次调用FB时该变量都会被重新初始化,导致逻辑错误。反之,若将临时变量声明为VAR,则会无谓占用背景DB空间,且可能因上次调用的残留值引发意外行为。
4.3.2 判断方法:如何选择变量类型
| 判断条件 | 选择变量类型 | 原因 |
|---|---|---|
| 数据需要在两次调用间保持 | 静态变量(VAR) | 存储在背景DB,断电保持(可选) |
| 数据仅本次调用使用,无需保持 | 内部变量(VAR_TEMP) | 节省DB空间,提高执行效率 |
| 数据需要被多个FB实例共享 | 全局DB变量 | 静态变量仅对单个实例可见 |
| 数据需要掉电保持 | 静态变量+DB保持属性 | 确保PLC重启后数据不丢失 |
4.3.3 案例拆解:电机软启动FB的变量设计
设计“Motor_SoftStart”FB,实现电机斜坡启动功能。需要保持的变量包括:当前输出频率(静态变量)、启动时间累计值(静态变量)、启动完成标志(静态变量)。临时变量包括:频率增量(VAR_TEMP)、循环计数(VAR_TEMP)。若将频率增量误声明为静态变量,则每次调用时增量会累积,导致输出频率异常跳变。正确设计后,FB在每次扫描周期内计算一次增量,并更新静态变量中的当前频率,实现平滑启动。
4.3.4 常见误区与总结
- 误区1:所有变量都用静态变量——导致背景DB臃肿,且临时变量残留值可能引发逻辑错误。
- 误区2:忽视VAR_TEMP的初始化——虽然VAR_TEMP在调用时自动分配,但其初始值不确定,需在FB内部显式赋值。
- 误区3:静态变量命名与内部变量混淆——建议在命名时添加前缀(如s_表示静态,t_表示临时),提高代码可读性。
总结:正确区分静态变量与内部变量,是FB设计的基本功。合理使用两类变量,既能保证状态保持,又能优化存储资源。
4.4 调用机制与执行逻辑:扫描周期内的行为
4.4.1 核心原理:FB在扫描周期中的执行位置
PLC采用循环扫描的工作方式,每个扫描周期依次执行:读取输入映像区、执行用户程序、写入输出映像区、执行系统自诊断。FB的调用发生在“执行用户程序”阶段。当CPU扫描到FB调用指令时,会执行以下步骤:
- 将输入参数的值从调用点复制到FB的输入存储区。
- 从背景DB中加载静态变量的当前值。
- 执行FB内部的算法逻辑,使用输入参数、静态变量和内部变量进行计算。
- 将输出参数的值写入调用点指定的变量。
- 将更新后的静态变量值写回背景DB。
这一过程在单个扫描周期内完成,且FB的调用是“顺序执行”的——即在一个扫描周期内,若同一FB被多次调用,则每次调用都会完整执行上述步骤,且后一次调用可以看到前一次调用对静态变量的更新。
4.4.2 判断方法:调用位置与执行顺序的影响
FB的调用位置会影响其执行时机和数据可见性。例如,在OB1中先调用“Motor_Control”FB,再调用“Status_Report”FB,则后者可以看到前者更新后的输出值。若调用顺序相反,则Status_Report看到的是上一次扫描周期的旧值。因此,在设计中需明确FB之间的数据依赖关系,合理安排调用顺序。
此外,FB可以在不同组织块中调用(如OB1主循环、OB35定时中断、OB100启动),不同OB中的调用时机不同,需注意数据一致性问题。例如,在OB35中调用高速计数FB,在OB1中调用显示FB,两者之间可能存在数据不同步。
4.4.3 实战场景:多FB协同工作的调用链设计
某反应釜控制系统包含三个FB:FB_TempCtrl(温度控制)、FB_StirrerCtrl(搅拌控制)、FB_AlarmMgr(报警管理)。在OB1中按以下顺序调用:
// OB1 主程序片段
CALL FB_TempCtrl, "TempCtrl_DB"
i_Setpoint := 85.0
i_ActualTemp := "Temp_Sensor_AI"
o_HeaterOut := "Heater_AO"
o_Status := "TempCtrl_Status"
CALL FB_StirrerCtrl, "Stirrer_DB"
i_StartCmd := "Stirrer_Start"
i_SpeedSet := 1200
o_SpeedAct := "Stirrer_Speed"
o_Running := "Stirrer_Run"
CALL FB_AlarmMgr, "Alarm_DB"
i_TempStatus := "TempCtrl_Status"
i_StirrerStatus := "Stirrer_Run"
o_AlarmCode := "Process_Alarm"
该调用链确保温度控制先执行,搅拌控制其次,报警管理最后,使报警逻辑能够基于最新的设备状态进行判断。若将报警管理放在最前,则可能因读取到旧状态而漏报或误报。
4.4.4 常见误区与总结
- 误区1:在多个OB中重复调用同一FB实例——可能导致数据竞争,需使用互斥机制或确保调用时机不重叠。
- 误区2:忽略FB执行时间——复杂FB(如浮点运算、字符串处理)会延长扫描周期,需评估CPU性能。
- 误区3:在FB内部调用自身(递归)——PLC不支持递归调用,会导致编译错误或运行时故障。
总结:理解FB的调用机制与执行逻辑,是确保程序时序正确、数据一致的基础。合理规划调用顺序和位置,能有效避免隐性逻辑错误。
4.5 综合复盘:FB设计的关键决策点
本章围绕FB的六大核心概念展开,从实例化机制到调用执行逻辑,构建了完整的知识框架。在实际项目中,FB设计的关键决策点可归纳为:
| 决策点 | 关键问题 | 推荐做法 |
|---|---|---|
| 实例规划 | 需要多少个实例?命名是否清晰? | 按物理对象命名,评估存储与扫描周期 |
| 接口设计 | 参数是否精简?类型是否合理? | 使用前缀规范,必要时用UDT打包 |
| 变量分类 | 哪些数据需要保持?哪些是临时的? | 静态变量用于状态保持,VAR_TEMP用于临时计算 |
| 调用策略 | 调用顺序是否满足数据依赖? | 按数据流方向排列调用,避免时序冲突 |
掌握这些核心概念后,读者应能够独立设计出结构清晰、复用性高、易于维护的FB程序。下一阶段的学习将聚焦于FB的封装技巧与跨项目复用方法,进一步释放结构化编程的生产力。