SCL 训练:存储功能块
OB 先做数据运算,再调用 SCL 功能块 Storage_System 管理 100 个货位(放入/取出/清空);演示 LAD + SCL + 全局/实例 DB。
进阶
多块
S7-1200
SCL
FB
DB
多块
导入到我的 TIA 项目
通过 TiaLink 把本示例的 6 个对象导入你当前打开的 TIA Portal 项目。导入前会先预检,默认不覆盖同名对象,导入后不会自动保存。
概述
这个示例由两种语言、三个块组成:Main(OB)先在 SCL 网络里做数据运算,再用 LAD 调用 SCL 功能块 Storage_System;功能块管理 100 个货位的放入、取出和清空。
它是多块工程的典型结构:主程序负责调度,功能块负责具体业务,数据放在全局 DB / 实例 DB 里。讲解按块分开,先看主程序,再看功能块。
信号表
| 对象 |
类型 |
含义 |
作用 |
Data.Number_01_int |
Int |
运算结果 |
主程序 SCL 的写入目标 |
Data.Number_02_int / _03_int |
Int |
整数输入 |
参与加法/乘法 |
Data.Number_04_real / _05_real / _06_real |
Real |
浮点数据 |
参与减法和除法 |
Storage.Selected_Shelf |
Int |
选中货位号 |
0~99 |
Storage.Put_In |
Bool |
放入命令 |
置位对应货位 |
Storage.Take_Out |
Bool |
取出命令 |
复位对应货位 |
Storage.Empty_Storage |
Bool |
清空命令 |
复位全部货位 |
Storage.Shelfs |
Bool 数组 |
100 个货位状态 |
FB 内部按索引读写 |
Storage_System_DB |
实例 DB |
Storage_System 的实例数据 |
保存 FB 的静态变量 |
点表 Default tag table 是空的;这个示例的数据都在 DB 里,不在 I/O 点表。
工作流程
- 每个扫描周期先执行
Main 的 Network 1(SCL 数据运算);
- 再执行 Network 2,用 LAD 调用
Storage_System,把 Storage 的命令和货位数组传进去;
Storage_System 根据 Put_In/Take_Out/Empty_Storage 修改 Shelfs;
Put_In 与 Take_Out 同时为 1 时置位 #Error;Empty_Storage=1 时用 FOR 循环清空 0~99 号货位。
MainOB · 主程序
Network 1 — 数据运算(SCL)
SCL
1"Data".Number_01_int := ("Data".Number_02_int + "Data".Number_03_int) * 3;2"Data".Number_06_real := INT_TO_REAL("Data".Number_03_intRet_Val) / 7;3"Data".Number_04_real -= "Data".Number_05_real;
目的:在 OB 里直接写 SCL,做整数和浮点运算。
条件 → 动作:Number_01_int = (Number_02_int + Number_03_int) * 3;Number_06_real = INT_TO_REAL(...) / 7;Number_04_real -= Number_05_real。
为什么:OB 里可以混用 LAD 和 SCL 网络;简单的算术用 SCL 表达比梯形图更直观。
注意:代码里的 "Data".Number_03_intRet_Val 看起来像原工程的笔误(多了 Ret_Val 后缀),实际字段应以 DB 定义为准;Number_04_real -= 是 SCL 的复合赋值写法。
Network 2 — 调用货位管理 FB(LAD)
目的:把 DB 里的命令和货位数组传给 Storage_System。
条件 → 动作:调用 Storage_System,参数映射为 Selected_Shelf、Put_In、Empty_Storage、Take_Out、Shelfs;实例使用 Storage_System_DB。
为什么:LAD 的调用框把输入/输出参数列得很清楚,比在 SCL 里手写调用更适合展示接口。
注意:调用是每个扫描周期都执行的(OB1 的常态),所以 FB 内部逻辑必须能处理"命令保持为 1"的情况。
Storage_SystemFB · 功能块(SCL)
| 名称 | 数据类型 | 注释 |
| Input |
| Selected_Shelf | Int | |
| Put_In | Bool | |
| Empty_Storage | Bool | |
| Take_Out | Bool | |
| Output |
| Error | Bool | |
| InOut |
| Shelfs | Array[0..99] of Bool | |
| Static |
| Temp |
| X | SInt | |
| Constant |
|---|
Network 1 — 放入 / 取出 / 清空(SCL)
SCL
1 2IF #Put_In AND #Take_Out = FALSE THEN3 4 #Shelfs[#Selected_Shelf] := TRUE;5 6ELSIF #Take_Out AND #Put_In = FALSE THEN7 8 #Shelfs[#Selected_Shelf] := FALSE;9 10ELSIF #Put_In AND #Take_Out THEN11 12 #Error := TRUE;13 14END_IF;15161718IF #Empty_Storage = TRUE THEN19 FOR #X := 0 TO 99 DO20 21 #Shelfs[#X] := FALSE;22 END_FOR;23END_IF;24
目的:管理 100 个货位的状态。
条件 → 动作:
Put_In=1 且 Take_Out=0 → Shelfs[Selected_Shelf] := TRUE;
Take_Out=1 且 Put_In=0 → Shelfs[Selected_Shelf] := FALSE;
- 两者同时为 1 →
Error := TRUE;
Empty_Storage=1 → FOR 循环把 Shelfs[0..99] 全部置 FALSE。
为什么:用 IF/ELSIF 处理互斥命令,用 FOR 循环批量清空;数组下标直接来自 Selected_Shelf。
注意:代码里 #Error 只置位、没有复位;Selected_Shelf 超出 0~99 会造成数组越界(SCL 可能报错或写错位置)。
常见问题
- 功能块不动作:确认
Storage_System_DB 已作为实例 DB 存在,调用参数映射正确。
- 货位号越界:
Selected_Shelf 必须限制在 0~99;可在 FB 里加范围检查。
- Error 一直为 1:当前逻辑没有复位
#Error,需要增加复位条件。
- SCL 代码编译不过:注意原工程里的
Number_03_intRet_Val 和数组类型定义,按实际 DB 字段修正。
变体与扩展
- 加范围保护:在 IF 前检查
Selected_Shelf 是否在 0~99 内。
- 加错误复位:用
Reset 参数清除 #Error。
- 多货架:把
Shelfs 扩展成二维数组,按区域 + 货位管理。
变量与数据块
Data 全局 DB
| 名称 | 数据类型 | 起始值 | 注释 |
| Static |
| Number_01_int | Int | | |
| Number_02_int | Int | | |
| Number_03_int | Int | | |
| Number_04_real | Real | | |
| Number_05_real | Real | | |
| Number_06_real | Real | | |
Storage 全局 DB
| 名称 | 数据类型 | 起始值 | 注释 |
| Static |
| Put_In | Bool | | |
| Take_Out | Bool | | |
| Selected_Shelf | Int | | |
| Empty_Storage | Bool | | |
| Shelf | Array[0..99] of Bool | | |
Storage_System_DB 实例 DB(Storage_System)
| 名称 | 数据类型 | 起始值 | 注释 |
| Input |
| Selected_Shelf | Int | | |
| Put_In | Bool | | |
| Empty_Storage | Bool | | |
| Take_Out | Bool | | |
| Output |
| Error | Bool | | |
| InOut |
| Shelfs | Array[0..99] of Bool | | |
| Static |
|---|