一、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. 基本运算与逻辑判断
算术运算
运算符
说明
示例
+
加法
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
逻辑运算
运算符
说明
示例
AND
逻辑与
IF Start AND RunFlag THEN …
OR
逻辑或
IF Alarm1 OR Alarm2 THEN …
NOT
逻辑非
RunFlag := NOT Stop;
XOR
逻辑异或
Flag := A XOR B;
条件判断(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;
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. 循环语句 适合重复执行一段逻辑,常用 FOR和 WHILE循环。
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;
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 块数据的语法清晰,支持直接访问和符号访问。
访问全局 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;
访问 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. 函数 / 功能块调用
调用 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
调用 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(数据存储 ),覆盖核心语法:
全局 DB(GlobalDB,DB1)
1 2 3 4 5 VAR_GLOBAL ProductionCount: INT := 0; // 总产量 LineSpeed: REAL := 50.0; // 设定速度 LineRun: BOOL := FALSE; // 生产线运行状态 END_VAR
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;
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);
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 编程注意事项
变量作用域:临时变量(VAR_TEMP)仅在当前扫描周期有效,不可用于保存状态;
数据类型匹配:运算时注意数据类型一致(如 REAL 和 INT 运算需先转换,用INT_TO_REAL等转换函数);
循环终止:WHILE 循环必须确保条件能终止,避免死循环导致 PLC 停机;
符号访问:优先使用符号名(如 “GlobalDB”.LineSpeed)而非绝对地址,提高可读性和可维护性。
总结
SCL 核心语法:变量声明(按作用域分类)、条件判断(IF/CASE)、循环(FOR/WHILE)、DB 访问、FB/FC 调用是基础,覆盖 80% 的编程场景;
数据块操作:全局 DB 用于共享数据,FB 背景 DB 用于保存状态,符号访问是推荐方式;
实战原则:复杂逻辑用 SCL(如计算、循环),简单逻辑可结合梯形图,FB/FC 封装复用逻辑,提升程序结构化程度