一、SCL 基础认知

SCL 是 **西门子** **PLC** 的结构化文本 编程语言 ,语法类似 Pascal / 高级语言,支持变量声明逻辑判断循环函数调用数据块操作等,适合处理复杂的 **数学计算** 、流程控制、数据处理场景。核心特点:

  • 可读性强,适合复杂逻辑编写;
  • 支持结构化编程(FB/FC/DB/OB);
  • 兼容西门子全系列 PLC(S7-1200/1500/300/400)

二、SCL 核心语法详解(附示例)

1. 变量声明(最基础也是最核心)

SCL 的变量声明必须遵循 “先声明,后使用” 原则,按作用域分为:输入变量、输出变量、输入输出变量、内部变量、临时变量。

通用声明格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
VAR  // 普通内部变量(FB/FC/DB中,数据持久保存)
变量名: 数据类型 := 初始值;
END_VAR

VAR_INPUT // 输入变量(外部传入)
变量名: 数据类型;
END_VAR

VAR_OUTPUT // 输出变量(向外传递)
变量名: 数据类型;
END_VAR

VAR_IN_OUT // 输入输出变量(双向传递)
变量名: 数据类型;
END_VAR

VAR_TEMP // 临时变量(仅当前周期有效,执行完清空)
变量名: 数据类型;
END_VAR

常用数据类型

类型 说明 示例
BOOL 布尔型(0/1) MotorRun: BOOL;
INT 整数(-32768~32767) Count: INT := 0;
REAL 浮点数(小数) Speed: REAL := 50.5;
STRING 字符串 Msg: STRING[20] := “Hello SCL”;
ARRAY 数组 Data: ARRAY[1…10] OF INT;

示例(FB 中变量声明):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// FB1: 电机控制功能块
VAR_INPUT
Start: BOOL; // 启动信号(I0.0)
Stop: BOOL; // 停止信号(I0.1)
SetSpeed: REAL; // 设定速度(如50.0 r/min)
END_VAR

VAR_OUTPUT
MotorRun: BOOL; // 电机运行输出(Q0.0)
ActualSpeed: REAL; // 实际速度反馈
END_VAR

VAR
RunFlag: BOOL := FALSE; // 内部运行标志(初始值FALSE)
SpeedArray: ARRAY[1..5] OF REAL; // 速度缓存数组
END_VAR

VAR_TEMP
TempValue: INT; // 临时变量,仅当前周期有效
END_VAR
2. 基本运算与逻辑判断
  1. 算术运算
运算符 说明 示例
+ 加法 A := 10 + 5; // A=15
- 减法 B := 20 - 8; // B=12
* 乘法 C := 3* 4; // C=12
/ 除法 D := 10 / 2; // D=5
MOD 取余 E := 7 MOD 3; // E=1
  1. 逻辑运算
运算符 说明 示例
AND 逻辑与 IF Start AND RunFlag THEN …
OR 逻辑或 IF Alarm1 OR Alarm2 THEN …
NOT 逻辑非 RunFlag := NOT Stop;
XOR 逻辑异或 Flag := A XOR B;
  1. 条件判断(IF-THEN-ELSE)
    最常用的流程控制语句,适合分支逻辑。示例(电机启停控制):
1
2
3
4
5
6
7
8
9
// 核心逻辑:停止优先
IF Stop THEN
RunFlag := FALSE; // 停止按钮按下,运行标志置FALSE
ELSIF Start THEN
RunFlag := TRUE; // 启动按钮按下,运行标志置TRUE
END_IF;

// 输出赋值
MotorRun := RunFlag; // 运行标志同步到输出点

多分支示例(温度区间判断)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
VAR
Temp: REAL := 25.5; // 检测温度
TempLevel: INT; // 温度等级
END_VAR

IF Temp < 0 THEN
TempLevel := 1; // 低温
ELSIF Temp >= 0 AND Temp < 30 THEN
TempLevel := 2; // 常温
ELSIF Temp >= 30 AND Temp < 50 THEN
TempLevel := 3; // 中温
ELSE
TempLevel := 4; // 高温
END_IF;
  1. CASE 语句(多值分支)

适合固定值的分支判断,比多层 IF 更简洁。示例(模式选择)

1
2
3
4
5
6
7
8
9
10
11
VAR
Mode: INT := 2; // 运行模式(1-手动,2-自动,3-调试)
ModeMsg: STRING[20];
END_VAR

CASE Mode OF
1: ModeMsg := "手动模式";
2: ModeMsg := "自动模式";
3: ModeMsg := "调试模式";
ELSE: ModeMsg := "无效模式"; // 默认分支
END_CASE;
3. 循环语句

适合重复执行一段逻辑,常用 FORWHILE循环。

  1. FOR 循环(固定次数循环)

语法FOR 循环变量 := 起始值 TO 结束值 BY 步长 DO ... END_FOR;示例(数组赋值)

1
2
3
4
5
6
7
8
9
VAR
DataArray: ARRAY[1..10] OF INT; // 10个整数的数组
i: INT; // 循环变量
END_VAR

// 给数组赋值:DataArray[1]=1, DataArray[2]=2...DataArray[10]=10
FOR i := 1 TO 10 BY 1 DO
DataArray[i] := i;
END_FOR;
  1. WHILE 循环(条件循环)

语法WHILE 条件 DO ... END_WHILE;示例(计数到 100 停止)

1
2
3
4
5
6
7
8
9
VAR
Count: INT := 0;
END_VAR

// 计数到100停止
WHILE Count < 100 DO
Count := Count + 1;
// 可添加其他逻辑,如数据采集、累加等
END_WHILE;
4. 数据块(DB)操作

SCL 中访问 DB 块数据的语法清晰,支持直接访问和符号访问。

  1. 访问全局 DB

假设创建了全局 DB:DB1(名称:GlobalDB),包含变量:

1
2
3
4
VAR_GLOBAL
LineSpeed: REAL := 50.0; // 生产线速度
ProductionCount: INT := 0; // 产量计数
END_VAR

访问方式 1(符号访问,推荐)

1
2
3
4
// 产量计数+1
"GlobalDB".ProductionCount := "GlobalDB".ProductionCount + 1;
// 修改生产线速度
"GlobalDB".LineSpeed := 60.5;

访问方式 2(绝对地址访问)

1
2
3
4
// DB1.DBD0 对应LineSpeed(REAL占4字节)
DB1.DBD0 := 60.5;
// DB1.DBW4 对应ProductionCount(INT占2字节)
DB1.DBW4 := DB1.DBW4 + 1;
  1. 访问 FB 背景 DB

调用 FB 时关联背景 DB 后,可直接访问背景 DB 中的变量:

1
2
3
4
5
6
7
8
9
// 调用FB1,关联背景DB:Motor1_DB
CALL "MotorControlFB", "Motor1_DB" (
Start := I0.0,
Stop := I0.1,
MotorRun => Q0.0
);

// 访问背景DB中的内部变量RunFlag
"Motor1_DB".RunFlag := TRUE;
5. 函数 / 功能块调用
  1. 调用 FC(功能)

假设创建 FC1:求和函数,声明如下:

1
2
3
4
5
6
7
8
9
10
// FC1: SumFC
VAR_INPUT
A: INT;
B: INT;
END_VAR
VAR_OUTPUT
Sum: INT;
END_VAR

Sum := A + B;

SCL 调用方式

1
2
3
4
5
6
VAR
Result: INT;
END_VAR

// 调用FC1,传入参数10和20,结果存入Result
Result := "SumFC"(A := 10, B := 20); // Result最终=30
  1. 调用 FB(功能块)

以之前的电机控制 FB1 为例,SCL 调用语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 方式1:直接调用
CALL "MotorControlFB", "Motor1_DB" (
Start := I0.0,
Stop := I0.1,
SetSpeed := 50.0,
MotorRun => Q0.0,
ActualSpeed => MD20
);

// 方式2:先声明实例,再调用(适合多次访问)
VAR
Motor1: "MotorControlFB" := "Motor1_DB"; // 声明FB实例
END_VAR

Motor1.Start := I0.0;
Motor1.Stop := I0.1;
Motor1(); // 执行FB逻辑
Q0.0 := Motor1.MotorRun; // 赋值输出

三、完整实战示例(生产线计数 + 速度控制)

以下是一个完整的 SCL 程序示例,包含 OB1(主循环)、FC(计算)、FB(控制)、DB(数据存储),覆盖核心语法:

  1. 全局 DB(GlobalDB,DB1)
1
2
3
4
5
VAR_GLOBAL
ProductionCount: INT := 0; // 总产量
LineSpeed: REAL := 50.0; // 设定速度
LineRun: BOOL := FALSE; // 生产线运行状态
END_VAR
  1. FC(SpeedCalcFC,FC1):速度换算(r/min → m/s)
1
2
3
4
5
6
7
8
9
10
VAR_INPUT
RpmSpeed: REAL; // 转速(r/min)
Radius: REAL; // 滚轮半径(m)
END_VAR
VAR_OUTPUT
MpsSpeed: REAL; // 线速度(m/s)
END_VAR

// 公式:线速度 = 2 * π * 半径 * 转速 / 60
MpsSpeed := 2 * 3.14159 * Radius * RpmSpeed / 60;
  1. FB(LineControlFB,FB1):生产线控制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
VAR_INPUT
StartLine: BOOL; // 启动生产线(I0.0)
StopLine: BOOL; // 停止生产线(I0.1)
Pulse: BOOL; // 计数脉冲(I0.2,每触发一次产量+1)
END_VAR
VAR_OUTPUT
LineRun: BOOL; // 生产线运行输出(Q0.0)
ActualMps: REAL; // 实际线速度(MD30)
END_VAR
VAR
RunFlag: BOOL := FALSE;
PulseLast: BOOL := FALSE; // 脉冲上一周期状态(防重复计数)
END_VAR

// 1. 生产线启停逻辑
IF StopLine THEN
RunFlag := FALSE;
ELSIF StartLine THEN
RunFlag := TRUE;
END_IF;
LineRun := RunFlag;

// 2. 产量计数(脉冲上升沿触发)
IF RunFlag THEN
IF Pulse AND NOT PulseLast THEN
"GlobalDB".ProductionCount := "GlobalDB".ProductionCount + 1;
END_IF;
PulseLast := Pulse;
END_IF;

// 3. 调用FC计算线速度
ActualMps := "SpeedCalcFC"(RpmSpeed := "GlobalDB".LineSpeed, Radius := 0.1);
  1. OB1(主循环块)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 调用生产线控制FB
CALL "LineControlFB", "LineControlDB" (
StartLine := I0.0,
StopLine := I0.1,
Pulse := I0.2,
LineRun => Q0.0,
ActualMps => MD30
);

// 调试输出:产量超过1000时报警
IF "GlobalDB".ProductionCount > 1000 THEN
Q0.1 := TRUE; // Q0.1为报警输出
ELSE
Q0.1 := FALSE;
END_IF;

四、SCL 编程注意事项

  1. 变量作用域:临时变量(VAR_TEMP)仅在当前扫描周期有效,不可用于保存状态;
  2. 数据类型匹配:运算时注意数据类型一致(如 REAL 和 INT 运算需先转换,用INT_TO_REAL等转换函数);
  3. 循环终止:WHILE 循环必须确保条件能终止,避免死循环导致 PLC 停机;
  4. 符号访问:优先使用符号名(如 “GlobalDB”.LineSpeed)而非绝对地址,提高可读性和可维护性。

总结

  1. SCL 核心语法:变量声明(按作用域分类)、条件判断(IF/CASE)、循环(FOR/WHILE)、DB 访问、FB/FC 调用是基础,覆盖 80% 的编程场景;
  2. 数据块操作:全局 DB 用于共享数据,FB 背景 DB 用于保存状态,符号访问是推荐方式;
  3. 实战原则:复杂逻辑用 SCL(如计算、循环),简单逻辑可结合梯形图,FB/FC 封装复用逻辑,提升程序结构化程度