文章目录

博途函数块的形参实参传递方式

发布于 2026-03-23 11:12:15 · 浏览 5 次 · 评论 0 条

博途(TIA Portal)中函数块(FB)的形参实参传递是PLC编程的核心机制。理解其原理与操作细节,能显著提升代码复用性与维护效率。


基本概念区分

形参(Formal Parameter)

形参是函数块内部定义的接口占位符,相当于"信箱上的名字标签"。它只在FB内部可见,不占用实际内存,等待外部调用时接收具体数据。

实参(Actual Parameter)

实参是调用FB时实际传递的具体数据,相当于"投入信箱的具体信件"。可以是变量、常量、表达式,必须有确定的内存地址或数值。


三种传递方式详解

博途FB支持三种形参实参绑定模式,适用场景截然不同。

方式一:符号绑定(推荐用于标准化项目)

核心机制:调用FB时,形参自动关联调用者的静态变量,无需手动填写实参。

配置步骤

  1. 创建 带多重实例功能的FB(默认即支持)。
  2. 声明 形参时选择 InOutInOutStatic 区域。
  3. 拖拽 FB至程序段,博途自动生成背景数据块(IDB)
  4. 展开 FB调用块,观察到形参右侧显示灰色静态变量名(如 Motor1.Speed)。

代码示例

// FB1: 电机控制块
FUNCTION_BLOCK "FB_MotorControl"
VAR_INPUT
    Start : Bool;      // 形参:启动命令
    Stop  : Bool;      // 形参:停止命令
    SetSpeed : Real;   // 形参:设定转速
END_VAR
VAR_OUTPUT
    Running : Bool;    // 形参:运行状态
    ActualSpeed : Real;// 形参:实际转速
END_VAR
VAR
    RampGen : Real;    // 内部斜坡发生器
END_VAR

// 主程序调用(OB1)
"FB_MotorControl_DB1"(          // 自动生成背景DB
    Start := "DI_Start_1",
    Stop := "DI_Stop_1",
    SetSpeed := "HMI_SpeedSet",
    Running => "DO_Run_1",
    ActualSpeed => "HMI_SpeedAct"
);

关键特性

特性 说明
存储位置 形参值存于背景DB,断电保持需勾选 Retain
访问方式 外部可通过 FB_MotorControl_DB1.SetSpeed 直接读写
适用场景 设备标准化、大量同类实例(如100台电机)

方式二:绝对地址绑定(快速调试/临时方案)

核心机制:形参直接关联PLC的绝对地址(如 %I0.0%QW100)。

操作步骤

  1. 打开 FB调用块的参数列表。
  2. 删除 形参右侧的默认静态变量(选中后按 Delete)。
  3. 输入 绝对地址或全局变量名,例如:
    • 形参 Start%I0.0"I_StartButton"
    • 形参 SetSpeed%IW64"AI_SpeedPoti"

典型应用

// 紧急情况下直接绑定硬件地址
"Safety_FB_1"(
    EStop_Ch1 := %I10.0,    // 急停通道1硬接线
    EStop_Ch2 := %I10.1,    // 急停通道2硬接线
    LightCurtain := %I10.2, // 安全光幕
    SafeOut => %Q5.0        // 安全输出
);

风险提示

问题 后果 规避方法
地址冲突 多处写入同一输出导致逻辑混乱 建立地址分配表,交叉引用检查
移植困难 更换CPU型号时地址失效 优先使用符号名而非裸地址
调试困难 在线监控无法显示直观变量名 配合注释详细记录地址功能

方式三:表达式传递(计算型实参)

核心机制:实参可以是运算表达式,调用时即时计算后传入。

支持表达式类型

类型 示例 适用形参方向
算术运算 Pressure * 0.98 + Offset In
比较运算 Temp > AlarmLimit In
位运算 Status AND 16#0F In
类型转换 Real_To_Int(Speed) In
条件选择 Sel(G:=(x>0), IN0:=0, IN1:=x) In

实例:流量补偿计算

// FB: 流量累计(需温度压力补偿)
FUNCTION_BLOCK "FB_FlowTotal"
VAR_INPUT
    FlowRaw : Real;        // 原始流量信号
    CompFactor : Real;     // 补偿系数(0.8-1.2)
    SampleTime : Real;     // 采样周期(秒)
END_VAR

// 调用时实时计算补偿系数
"FB_FlowTotal_1"(
    FlowRaw := %IW80,
    CompFactor := (273.15 + "AI_Temp") / 293.15 * 101325 / "AI_Pressure",
    SampleTime := 0.1
);

重要限制

  • OutInOut 形参不可接收表达式,只能接收可写入的变量
  • 复杂表达式建议拆分,避免单次调用行过长

特殊传递机制:InOut 参数

InOut 参数兼具输入输出特性,是实现"按引用传递"的关键。

与普通变量的本质区别

// 假设有全局变量 Global_Var := 10

// 方式A:In参数(值传递)
"FB_Test"(InputVar := Global_Var);  
// FB内部修改InputVar不影响Global_Var

// 方式B:InOut参数(引用传递)
"FB_Test"(InOutVar := Global_Var);  
// FB内部修改InOutVar直接改变Global_Var

数组与结构体的高效传递

InOut 是传递大体积数据(数组、UDT)的唯一推荐方式,避免数据拷贝开销:

// 定义:100个伺服轴的位置数据
TYPE "UDT_AxisData"
STRUCT
    Position : Array[1..100] of Real;
    Velocity : Array[1..100] of Real;
    Torque   : Array[1..100] of Real;
END_STRUCT;

// FB:多轴插补计算
FUNCTION_BLOCK "FB_Interpolation"
VAR_IN_OUT
    AxisData : "UDT_AxisData";  // 直接引用外部数据,不复制
END_VAR

// 调用:整个结构体作为单一参数传递
"FB_Interpolation_1"(AxisData := "G_AxisGroup_1");

多重实例与数据存储深度

理解形参数据的最终存储位置,是排查"值丢失"问题的关键。

graph TD A["调用层级"] --> B["OB1: 主循环"] B --> C["FB10: 设备管理层"] C --> D["FB20: 电机控制
(形参: Speed)"] D --> E["FB30: 斜坡函数
(形参: RampTime)"] F["数据存储"] --> G["全局DB
(可选共享)"] F --> H["FB10_IDB
(静态变量区)"] F --> I["FB20_IDB
(嵌套在FB10_IDB内)"] F --> J["FB30_IDB
(嵌套在FB20_IDB内)"] D -.->|"Speed值存储于"| I E -.->|"RampTime值存储于"| J

关键结论

  • 多层嵌套调用时,每层FB的形参值存储于各自的背景DB
  • 使用 Multi-instance 功能时,子FB的IDB嵌入父FB的IDB,形成层级结构
  • 查看路径:项目树程序块系统块 → 展开层级查看嵌套关系

常见错误与排查

现象 根本原因 解决方法
形参值始终为0 未分配实参或实参变量未初始化 检查调用块的参数连接状态,确认变量被赋值
修改形参后外部变量不变 误用In而非InOut 将方向改为InOut,或改用Out参数返回
背景DB过大 大量使用Static数组存储历史数据 将大数据移至全局DB,IDB中只存指针
编译报错"实参类型不匹配" 形参RealInt,或数组维度不符 添加类型转换函数,或统一数据类型定义
在线监控值与预期不符 实参被多处赋值,存在冲突 使用交叉引用Ctrl + Alt + C)查找所有写入点

最佳实践总结

设计阶段

  • 优先使用符号绑定,建立清晰的变量命名规范(如 设备_功能_类型
  • 将设备参数(电机额定电流、减速比等)封装为UDT,作为InOut传递

编码阶段

  • 复杂计算在调用前完成,避免FB接口处堆砌表达式
  • InOut参数添加///文档注释,说明数据流向

维护阶段

  • 定期使用 重新链接 功能(右键程序块 → 重新链接),清理失效的实参引用
  • 导出接口描述(工具导出PLC变量),供HMI/SCADA团队同步

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文