SCL 函数块的形参与实参传递方式
在 Siemens TIA Portal 中使用 SCL(Structured Control Language)编程时,理解参数传递机制是确保程序稳定运行的基础。形参是功能块接口定义的变量占位符,实参是调用块时传入的具体存储地址或常数。错误的传递方式会导致数据丢失、程序崩溃或不可预测的逻辑错误。
1. 参数类型与传递特性
SCL 块接口包含五种基本参数类型。每种类型决定了数据如何从调用环境进入块内部,以及如何处理返回值。
| 参数类型 | 传递方向 | 传递机制 | 数据保持性 | 适用范围 |
|---|---|---|---|---|
Input |
传入 | 值传递 (By Value) | 不保持 | FB / FC |
Output |
传出 | 值传递 (By Value) | 不保持 | FB / FC |
InOut |
传入/传出 | 引用传递 (By Reference) | 不保持 | FB / FC |
Static |
内部存储 | 地址直接访问 | 保持 | 仅 FB |
Temp |
内部临时 | 地址直接访问 | 不保持 | FB / FC |
注意:表格中“值传递”意味着数据被复制一份到局部内存,“引用传递”意味着直接操作原始数据的地址。
2. 数据流向逻辑
理解数据如何在实际参数与形式参数之间流动,有助于调试程序。以下流程展示了调用过程中的数据路径。
flowchart TD
A["实际参数:全局变量"] -->|1. 复制数值 | B["形参:Input"]
B --> C["块内部逻辑运算"]
C -->|2. 复制数值 | D["形参:Output"]
D -->|3. 回写数值 | E["实际参数:全局变量"]
F["实际参数:数据块地址"] -->|1. 传递地址 | G["形参:InOut"]
G --> C
C -->|2. 直接修改 | F
H["形参:Static"] -->|3. 保持上次值 | C
- Input 路径:调用时,实参的值被复制到形参的局部存储区。块内修改形参不会影响外部实参。
- Output 路径:块执行结束后,形参的值被复制回实参地址。
- InOut 路径:传递的是实参的内存地址。块内直接读写该地址,修改立即生效。
- Static 路径:仅存在于背景数据块 (Instance DB) 中,断电保持,多次调用间保留数据。
3. 创建与配置功能块
按照以下步骤在 TIA Portal 中建立支持参数传递的 SCL 功能块。
- 打开 项目树中的“程序块”文件夹。
- 双击 “添加新块”图标。
- 选择 块类型为“功能块 (FB)"或“函数 (FC)"。
- 输入 块名称,例如
FB_MotorControl。 - 设置 语言为
SCL。 - 点击 “确定”生成块。
- 切换 到右侧“指令”窗口的“接口”选项卡。
- 展开 “输入参数 (Input)"栏。
- 输入 变量名
StartCmd,数据类型选择Bool。 - 展开 “输出参数 (Output)"栏。
- 输入 变量名
RunStatus,数据类型选择Bool。 - 展开 “输入输出参数 (InOut)"栏。
- 输入 变量名
MotorData,数据类型选择Struct或DWord。 - 展开 “静态数据 (Static)"栏(仅 FB 可用)。
- 输入 变量名
ErrorCount,数据类型选择Int。 - 双击 块名称打开编程界面。
- 编写 逻辑代码,使用已定义的形参名。
- 点击 工具栏上的“编译”按钮检查错误。
4. 编写 SCL 逻辑代码
在块内部编写逻辑时,直接使用接口定义的形参名称。以下示例展示了如何读取输入、处理逻辑并赋值输出。
FUNCTION_BLOCK "FB_MotorControl"
TITLE = 电机控制逻辑
VERSION : 0.1
VAR_INPUT
StartCmd : Bool; // 启动命令
ResetCmd : Bool; // 复位命令
END_VAR
VAR_OUTPUT
RunStatus : Bool; // 运行状态
ErrorFlag : Bool; // 错误标志
END_VAR
VAR_IN_OUT
MotorSpeed : Real; // 电机转速 (引用传递)
END_VAR
VAR_STATIC
RunTimer : TIME; // 运行计时 (保持)
END_VAR
BEGIN
// 处理复位逻辑
IF "ResetCmd" THEN
"RunStatus" := FALSE;
"MotorSpeed" := 0.0;
"ErrorFlag" := FALSE;
"RunTimer" := T#0S;
END_IF;
// 处理启动逻辑
IF "StartCmd" AND NOT "ErrorFlag" THEN
"RunStatus" := TRUE;
// 直接修改传入的实参地址
"MotorSpeed" := "MotorSpeed" + 10.0;
"RunTimer" := "RunTimer" + T#100MS;
ELSE
"RunStatus" := FALSE;
END_IF;
// 错误检测
IF "MotorSpeed" > 1000.0 THEN
"ErrorFlag" := TRUE;
END_IF;
END_FUNCTION_BLOCK
关键点:
- 代码中
"VariableName"是 TIA Portal 自动生成的符号访问格式。 MotorSpeed作为InOut参数,其修改会直接改变调用处传入的变量值。RunTimer作为Static参数,下次扫描周期时会保留上一周期的累加值。
5. 调用功能块并传递实参
在主程序块(如 OB1)中调用已创建的功能块,并将实际变量绑定到形参。
- 打开
OB1或其他调用块。 - 拖拽
FB_MotorControl到程序段中。 - 点击 块上方的引脚名称(如
StartCmd)。 - 输入 实际变量名,例如
Global_Start_Button。 - 点击
MotorSpeed引脚。 - 输入 实际数据块地址,例如
"DB_Motor".ActualSpeed。 - 确认
InOut参数必须传入变量地址,禁止传入常数。 - 编译 整个项目以确保引脚连接无误。
调用时的代码示例如下:
CALL #FB_MotorControl
(
StartCmd := "Global_Start_Button",
ResetCmd := "Global_Reset_Button",
RunStatus => "Motor_Is_Running",
ErrorFlag => "Motor_Has_Error",
MotorSpeed := "DB_Motor".ActualSpeed
);
注意::= 用于输入参数赋值,=> 用于输出参数读取(新版 TIA Portal 通常统一使用 := 或自动识别,但逻辑上需区分方向)。
6. 常见陷阱与优化建议
在实际工程中,参数传递方式的选择不直接影响性能,还关乎安全性。
- 避免大结构体值传递:如果
Input参数是一个包含 100 个元素的结构体,每次调用都会复制大量数据。改用InOut传递指针或引用可显著减少扫描时间。 - InOut 参数安全检查:
InOut允许块内部修改外部数据。确保块内部逻辑有边界检查,防止意外改写关键系统变量。 - 常数传递限制:
Input参数可以接受常数(如100),但InOut和Output参数必须连接可写地址变量。尝试传入常数会导致编译报错。 - 静态变量依赖:
Static变量依赖背景数据块 (Instance DB)。禁止在多任务中断中同时调用同一个背景数据块实例,否则会导致数据竞争。 - 未连接引脚处理:在 SCL 属性设置中,可以配置未连接引脚的默认行为。建议显式连接所有关键引脚,避免使用默认值导致逻辑隐蔽错误。
- 数据类型匹配:实参与形参的数据类型必须严格一致,或存在隐式转换关系。禁止将
Bool直接传递给Int形参,除非使用显式转换函数BOOL_TO_INT()。
7. 调试与监控技巧
- 启用 块接口监控。
- 在线 下载到 PLC。
- 打开 调用的块实例。
- 观察 接口栏中形参的当前值。
- 对比 实参变量表中的数值。
- 验证
InOut参数修改后,外部变量是否同步变化。 - 检查
Static变量在停止/启动循环后是否保持预期值。 - 使用 交叉引用工具查找所有调用该块的位置,确认实参传递一致性。

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