最近节日
正在加载日历...----
SCL是西门子PLC的结构化文本编程语言

SCL 是 西门子PLC 的结构化文本 编程语言 ,语法类似 Pascal / 高级语言,支持变量声明、逻辑判断、循环、函数调用、数据块操作等,适合处理复杂的 数学计算 、流程控制、数据处理场景。核心特点:
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| 运算符 | 说明 | 示例 |
|---|---|---|
| + | 加法 | 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 Stop THENRunFlag := FALSE; // 停止按钮按下,运行标志置FALSEELSIF Start THENRunFlag := TRUE; // 启动按钮按下,运行标志置TRUEEND_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;适合固定值的分支判断,比多层 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;适合重复执行一段逻辑,常用 FOR和 WHILE循环。
语法: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]=10FOR i := 1 TO 10 BY 1 DO DataArray[i] := i;END_FOR;语法:WHILE 条件 DO ... END_WHILE;示例(计数到 100 停止):
VAR Count: INT := 0;END_VAR
// 计数到100停止WHILE Count < 100 DO Count := Count + 1; // 可添加其他逻辑,如数据采集、累加等END_WHILE;SCL 中访问 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;调用 FB 时关联背景 DB 后,可直接访问背景 DB 中的变量:
// 调用FB1,关联背景DB:Motor1_DBCALL "MotorControlFB", "Motor1_DB" ( Start := I0.0, Stop := I0.1, MotorRun => Q0.0);
// 访问背景DB中的内部变量RunFlag"Motor1_DB".RunFlag := TRUE;假设创建 FC1:求和函数,声明如下:
// FC1: SumFCVAR_INPUT A: INT; B: INT;END_VARVAR_OUTPUT Sum: INT;END_VAR
Sum := A + B;SCL 调用方式:
VAR Result: INT;END_VAR
// 调用FC1,传入参数10和20,结果存入ResultResult := "SumFC"(A := 10, B := 20); // Result最终=30以之前的电机控制 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(数据存储),覆盖核心语法:
VAR_GLOBAL ProductionCount: INT := 0; // 总产量 LineSpeed: REAL := 50.0; // 设定速度 LineRun: BOOL := FALSE; // 生产线运行状态END_VARVAR_INPUT RpmSpeed: REAL; // 转速(r/min) Radius: REAL; // 滚轮半径(m)END_VARVAR_OUTPUT MpsSpeed: REAL; // 线速度(m/s)END_VAR
// 公式:线速度 = 2 * π * 半径 * 转速 / 60MpsSpeed := 2 * 3.14159 * Radius * RpmSpeed / 60;VAR_INPUT StartLine: BOOL; // 启动生产线(I0.0) StopLine: BOOL; // 停止生产线(I0.1) Pulse: BOOL; // 计数脉冲(I0.2,每触发一次产量+1)END_VARVAR_OUTPUT LineRun: BOOL; // 生产线运行输出(Q0.0) ActualMps: REAL; // 实际线速度(MD30)END_VARVAR 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);// 调用生产线控制FBCALL "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;总结