西门子SCL编程完全指南:语法详解+详细例子代码
一、SCL 基础认知
SCL 是西门子 PLC 的结构化文本编程语言,语法类似 Pascal / 高级语言,支持变量声明、逻辑判断、循环、函数调用、数据块操作等,适合处理复杂的数学计算、流程控制、数据处理场景。核心特点:
- 可读性强,适合复杂逻辑编写;
- 支持结构化编程(FB/FC/DB/OB);
- 兼容西门子全系列 PLC(S7-1200/1500/300/400)。
二、SCL 核心语法详解(附示例)
1. 变量声明(最基础也是最核心)
SCL 的变量声明必须遵循 “先声明,后使用” 原则,按作用域分为:输入变量、输出变量、输入输出变量、内部变量、临时变量。
通用声明格式:
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 中变量声明):
// 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 |
(2)逻辑运算
| 运算符 | 说明 | 示例 |
|---|---|---|
| AND | 逻辑与 | IF Start AND RunFlag THEN ... |
| OR | 逻辑或 | IF Alarm1 OR Alarm2 THEN ... |
| NOT | 逻辑非 | RunFlag := NOT Stop; |
| XOR | 逻辑异或 | Flag := A XOR B; |
(3)条件判断(IF-THEN-ELSE)
最常用的流程控制语句,适合分支逻辑。示例(电机启停控制):
// 核心逻辑:停止优先
IF Stop THEN
RunFlag := FALSE; // 停止按钮按下,运行标志置FALSE
ELSIF Start THEN
RunFlag := TRUE; // 启动按钮按下,运行标志置TRUE
END_IF;
// 输出赋值
MotorRun := RunFlag; // 运行标志同步到输出点
多分支示例(温度区间判断):
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;
(4)CASE 语句(多值分支)
适合固定值的分支判断,比多层 IF 更简洁。示例(模式选择):
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循环。
(1)FOR 循环(固定次数循环)
语法:FOR 循环变量 := 起始值 TO 结束值 BY 步长 DO ... END_FOR;示例(数组赋值):
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;
(2)WHILE 循环(条件循环)
语法:WHILE 条件 DO ... END_WHILE;示例(计数到 100 停止):
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),包含变量:
VAR_GLOBAL
LineSpeed: REAL := 50.0; // 生产线速度
ProductionCount: INT := 0; // 产量计数
END_VAR
访问方式 1(符号访问,推荐):
// 产量计数+1
"GlobalDB".ProductionCount := "GlobalDB".ProductionCount + 1;
// 修改生产线速度
"GlobalDB".LineSpeed := 60.5;
访问方式 2(绝对地址访问):
// DB1.DBD0 对应LineSpeed(REAL占4字节)
DB1.DBD0 := 60.5;
// DB1.DBW4 对应ProductionCount(INT占2字节)
DB1.DBW4 := DB1.DBW4 + 1;
(2)访问 FB 背景 DB
调用 FB 时关联背景 DB 后,可直接访问背景 DB 中的变量:
// 调用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:求和函数,声明如下:
// FC1: SumFC
VAR_INPUT
A: INT;
B: INT;
END_VAR
VAR_OUTPUT
Sum: INT;
END_VAR
Sum := A + B;
SCL 调用方式:
VAR
Result: INT;
END_VAR
// 调用FC1,传入参数10和20,结果存入Result
Result := "SumFC"(A := 10, B := 20); // Result最终=30
(2)调用 FB(功能块)
以之前的电机控制 FB1 为例,SCL 调用语法:
// 方式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)
VAR_GLOBAL
ProductionCount: INT := 0; // 总产量
LineSpeed: REAL := 50.0; // 设定速度
LineRun: BOOL := FALSE; // 生产线运行状态
END_VAR
2. FC(SpeedCalcFC,FC1):速度换算(r/min → m/s)
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;
3. FB(LineControlFB,FB1):生产线控制
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);
4. OB1(主循环块)
// 调用生产线控制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 封装复用逻辑,提升程序结构化程度。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)