『7x24小时有问必答』
干了12年PLC,整理了项目中最常用、重复率最高的SCL代码片段,每个都有注释!
为什么要标准化SCL代码?
深耕 PLC 调试 12 年,踩过无数现场大坑!见过太多项目同一条产线、同款设备,两位工程师写的程序两套逻辑,一人写的 FB 晦涩难懂,接手的人连动都不敢动,改一行全线停机

很多人误以为标准化会束缚编程思路,恰恰相反:标准化不是捆住创造力,而是用极低的沟通成本,换来设备长期稳定、随手可维护。

整理了近 3 年 20 + 西门子落地项目实战沉淀的  6 套通用标准化模板,全部经过量产产线实测有基本的异常处理和注释。你直接复制到TIA Portal里改改I/O地址和设备参数就能用。

模板编号适用场景核心指令难度
1  状态机FB
顺序控制、工步跳转
CASE...OF
☆☆
2  配方管理FC
多产品换型参数加载
ARRAY[ ]
3  故障重试FB
通信断线、气缸不到位自动重试
WHILE + TIMER
4  数据记日志FC
产量统计、报警记录
WRIT_DBL / ARRAY
5  模块化阀组FB
多路电磁阀统一控制
UDT + FB封装
☆☆
6  看门狗定时器FC
设备空闲超时、通信监视
TON + TONR
☆☆

<b>模版1:状态FB---

所有顺序控制的核心骨架
别再拿 M 点置位复位写顺序控制了!改用 CASE 状态机编程,代码可读性直接翻倍,现场调试至少省一半时间。给大家一套冲压设备完整工作循环标准框架:FB100_StateMachine 状态机 FB 源码,直接复制就能改 IO 投产。
// --- 隐式状态定义 --- //  
IDLE=0         //待机WAIT_PART=1 //等待上料CLAMP=2       //工件夹紧PRESS=3       //冲压加工UNCLAMP=4    //松夹EJECT=5       //下料顶出DONE=6         //单循环完成ERROR=99      //故障报错CASE  State  OF0: // IDLE 待机状态IF  Start  AND NOT  Busy  THEN      Timer(IN:=FALSE);      State  := 1;END_IF;1: // WAIT_PART 工件检测PartDetect  :=  PartSen;IF  PartSen  THEN      State  := 2;ELSIF  Timer.Q THEN      Alarm  := '工件超时未到位';      State  := 99;ELSE      Timer(IN:=TRUE, PT:=T5S);END_IF;2: // CLAMP 夹紧工件ClampOut  := TRUE;IF  ClampFB  THEN      Timer(IN:=FALSE);      State  := 3;ELSIF  Timer.Q THEN      Alarm  := '夹紧超时';      State  := 99;ELSE      Timer(IN:=TRUE, PT:=T2S);END_IF;3: // PRESS 冲压工序PressOut  := TRUE;Timer(IN:=TRUE, PT:=PressTime);IF  Timer.Q THEN      PressOut  := FALSE;      State  := 4;END_IF;4: // UNCLAMP 松开夹具ClampOut  := FALSE;IF NOT  ClampFB  THEN      State  := 5;END_IF;5: // EJECT 下料顶出EjectOut  := TRUE;IF  EjectFB  OR  Timer.Q THEN      EjectOut  := FALSE;      IF  CycleCnt  <  TargetCnt  THEN            CycleCnt  += 1;            State  := 0;      ELSE            State  := 6;      END_IF;ELSE      Timer(IN:=TRUE, PT:=T2S);END_IF;6: // DONE 整循环结束Busy  := FALSE;Done  := TRUE;IF NOT  Start  THEN      State  := 0;END_IF;99: // ERROR 故障统一处理Error  := TRUE;Busy  := FALSE;IF  Reset  THEN      State  := 0;      Alarm  := '';      Error  := FALSE;END_IF;END_CASE;

这套标准状态机三大核心规范:所有运行状态统一在 FB 头部注释定义,一目了然;每一个工步自带定时器超时保护,杜绝设备卡死;全部故障归集到 99 号 ERROR 状态,复位逻辑统一写一处。这套骨架我用了6年,从单工位到18站生产线全是一个结构。

<b>模板2:配方管理FC---
多品种换型不再重新下载程序
产线换产品型号就改配方号,不用动一行PLC代码。核心思路是用ARRAY OF UDT存配方数据,用配方号索引加载。
FC200_RecipeLoader 关键逻辑
// 自定义配方UDT,统一所有产品工艺参数TYPE RecipeDataSTRUCT      Speed : INT;            // 运行速度百分比 0-100      PressTime : TIME;    // 冲压保压时间      TempSet : INT;         // 加热设定温度 ℃      TorqueLimit : REAL; // 扭矩保护上限 Nm      EnableCheck : BOOL; // 视觉检测使能开关END_STRUCT;END_TYPE// 全局DB配方存储区,批量存放多型号参数RecipeDB: ARRAY[1..50] OF RecipeData// FC核心加载逻辑// 1. 先校验配方号合法性,防止越界报错IF  RecipeNo  < 1 OR  RecipeNo  > 50 THEN      Error  := TRUE;      Diag  := '配方号超出存储范围';      RETURN;END_IF;// 2. 读取对应编号整套配方数据TempRecipe  := "RecipeDB"[RecipeNo];// 3. 参数安全校验,拦截非法数值避免撞机IF  TempRecipe.Speed < 0 OR  TempRecipe.Speed > 100 THEN      Error  := TRUE;      Diag  := '速度参数超出0~100合理区间';      RETURN;END_IF;// 4. 正常输出全部工艺参数SpeedOut  :=  TempRecipe.Speed;PressTimeOut  :=  TempRecipe.PressTime;TempSetOut  :=  TempRecipe.TempSet;TorqueLimitOut  :=  TempRecipe.TorqueLimit;VisionEnable  :=  TempRecipe.EnableCheck;Error  := FALSE;Loaded  := TRUE;

这套标准化配方模板 3 大硬核优势:
1、换型零改程序:HMI 仅下发配方编号,整套速度、温度、扭矩参数自动一次性加载,调试工时大幅压缩;
2、内置双层安全校验:配方号边界校验 + 工艺参数区间校验,杜绝操作工误输入非法数值,规避设备撞机风险;
3、无限扩容无负担:现有 50 套配方不够用,只需修改数组上限为 ARRAY[1..200],整套加载逻辑完全不用改动。

<b>模板3:故障自动重试FB---

减少不必要的停机

通信瞬断、气缸偶发不到位是产线最常见的误停机原因。与其让操作工按复位,不如让PLC自动重试一次。但重试必须有次数上限,不能无限循环。
  FB300_Retry 核心逻辑
     // 接口参数 //  DoAction  : BOOL 触发动作 //  FeedbackOK  : BOOL 反馈信号 //  Timeout  : TIME 超时时间 //  MaxRetries  : INT 最大重试次数 //  ActionCmd  : BOOL 输出到执行器 //  RetryCount  : INT 当前重试次数(STAT) //  Failed  : BOOL 最终失败标志 //  InProgress  : BOOL 正在执行  InProgress  :=  DoAction  AND NOT  Failed; IF  DoAction  AND (RetryCount  = 0) THEN // 首次触发  ActionCmd  := TRUE;  RetryTimer(IN:=TRUE, PT:=Timeout);  RetryCount  := 1; END_IF; IF  InProgress  THEN IF  FeedbackOK  THEN // 成功  ActionCmd  := FALSE;  RetryTimer(IN:=FALSE);  RetryCount  := 0;  InProgress  := FALSE; ELSIF  RetryTimer.Q THEN // 超时,准备重试  ActionCmd  := FALSE;  RetryTimer(IN:=FALSE); WAIT(100); // 等待100ms再重试  ActionCmd  := TRUE;  RetryTimer(IN:=TRUE, PT:=Timeout);  RetryCount  += 1; END_IF; // 超过最大重试次数 IF  RetryCount  >  MaxRetries  THEN  ActionCmd  := FALSE;  InProgress  := FALSE;  Failed  := TRUE; END_IF; END_IF; // 复位 IF NOT  DoAction  THEN  RetryCount  := 0;  Failed  := FALSE;  ActionCmd  := FALSE;  RetryTimer(IN:=FALSE); END_IF;
     这个FB我主要用于气缸夹紧检测、RFID读取、视觉拍照触发三个场景。设置2-3次重试,每次超时后等待100ms再试。实践下来,约70%的偶发失败一次重试就成功了,产线综合效率OEE提升了3-5%。

<b>模块4:数据日志FC---

产线数据直接记到DB
不用搭配上位机做数据存储!单靠 PLC 就能自主保存产量、报警、换型日志,一套环形缓冲区数组搞定,存满自动覆盖最早数据,零额外硬件成本。

FC400_LogWriter 环形缓冲区
// 日志单条记录结构体,统一所有事件格式TYPE LogEntrySTRUCT      Timestamp : DT;         // 事件精确时间戳      EventType : INT;       // 事件类型:0=产量 1=报警 2=产品换型      Value : REAL;            // 对应数值(产量数值/故障代码/配方号等)      Desc : STRING[20];    // 事件简短文字描述END_STRUCT;END_TYPE// 日志存储DB全局变量定义LogDB.Data      : ARRAY[0..999] OF LogEntry;   // 1000条环形缓存池LogDB.HeadPtr : INT;                                    // 写入指针LogDB.Count    : INT;                                    // 当前有效记录总数// FC400_LogWriter 日志写入核心逻辑Idx  := "LogDB".HeadPtr;// 写入当前事件全部信息"LogDB".Data[Idx].Timestamp := LDT();"LogDB".Data[Idx].EventType :=  EventType;"LogDB".Data[Idx].Value :=  Value;"LogDB".Data[Idx].Desc :=  Desc;// 环形指针循环前进,触底归零实现循环覆盖"LogDB".HeadPtr += 1;IF "LogDB".HeadPtr >= 1000 THEN      "LogDB".HeadPtr := 0;END_IF;// 记录总数上限锁死1000,不超缓冲区容量IF "LogDB".Count < 1000 THEN      "LogDB".Count += 1;END_IF;

方案四大实用亮点
1、无需上位机:数据全部存在 PLC 自带 DB 块,S7-1200 就能独立存储,省去工控机、数据库成本;
2、自动循环覆盖:1000 条缓存存满后,新数据自动顶掉最早日志,不会出现存储溢出报错;
3、时间戳精准省心:直接调用 LDT () 获取毫秒级系统时间,不用手动拼接日期、时分秒;
4、接 HMI 超简单:HMI 直接读取 LogDB 数组,可分页展示近百条日志,支持一键导出 CSV 归档。
硬件占用说明
1000 条完整日志缓冲区仅占用约 80KB 的 DB 存储空间,西门子 1200 系列 PLC 内存完全够用,完全不影响程序运行。

<b>模块5:模块化阀组FB---

一个FB管所有气缸
一条产线几十个气缸,每个都要写伸出缩回、到位检测、超时报警。用UDT+FB封装,一个FB实列化N次就行。
  FB500_Cylinder UDT+FB封装
// 气缸配置UDT —— 所有气缸参数统一标准化TYPE CylinderConfigSTRUCT      ExtendTime   : TIME;         // 伸出超时时间      RetractTime : TIME;         // 缩回超时时间      Name            : STRING[16];// 气缸设备名称(报警文本直接带出)END_STRUCT;END_TYPE// FB500_Cylinder 标准气缸控制核心逻辑// 输入:Cfg(UDT参数)、Cmd控制指令// 反馈:SolA/SolB电磁阀输出、PosFB/PosBK到位检测、报警、故障CASE  Cmd  OF0: // 指令0:停止复位      SolA  := FALSE;      SolB  := FALSE;      Timer(IN:=FALSE);1: // 指令1:气缸伸出      SolA  := TRUE;      SolB  := FALSE;      Timer(IN:=TRUE, PT:=Cfg.ExtendTime);            IF  PosFB  THEN            Done  := TRUE;            Cmd  := 0;      ELSIF  Timer.Q THEN            Alarm  := '伸出超时:' +  Cfg.Name;            Error  := TRUE;      END_IF;2: // 指令2:气缸缩回      SolA  := FALSE;      SolB  := TRUE;      Timer(IN:=TRUE, PT:=Cfg.RetractTime);            IF  PosBK  THEN            Done  := TRUE;            Cmd  := 0;      ELSIF  Timer.Q THEN            Alarm  := '缩回超时:' +  Cfg.Name;            Error  := TRUE;      END_IF;END_CASE;

现场调用极其简单,所有气缸只需要一行代码实例化调用,无需重复写逻辑:
"Cyl_Clamp1"(Cfg:=Cfg_Clamp1, Cmd:=2);   // 夹紧缸缩回"Cyl_Clamp2"(Cfg:=Cfg_Clamp2, Cmd:=1);   // 夹紧缸伸出
每个实例独立运行,互不干扰。维护时只看实例名就知道控制哪个气缸。

<b>模块6:看门狗定时器FC---

没人做但你早晚需要
设备空闲超3分钟自动回原点、通信断线5秒报警、操作员离开10分钟自动停机——这些需求每个项目都有,但每次写的都不一样。统一用一个FC搞定。
     FC600_Watchdog 统一接口
     // 接口: //  Trigger  : BOOL 触发计时(设备运动信号) //  IdleTime  : TIME 空闲警戒时间 //  AlarmOut  : BOOL 超时报警 //  TimeLeft  : TIME 剩余时间(给HMI显示倒计时) //  Reset  : BOOL 手动复位 //  WarnFlag  : BOOL 提前预警(剩余5秒时置位) IF  Trigger  THEN // 设备在动,重置计时器  Timer(IN:=FALSE);  Timer(IN:=TRUE, PT:=IdleTime);  AlarmOut  := FALSE;  WarnFlag  := FALSE; END_IF; IF NOT  Trigger  AND NOT  Reset  THEN  Timer(IN:=TRUE, PT:=IdleTime);  TimeLeft  :=  IdleTime  -  Timer.ET; IF  Timer.ET >=  IdleTime  - T5S  AND NOT  Timer.Q THEN  WarnFlag  := TRUE; // 提前5秒预警 END_IF; IF  Timer.Q THEN  AlarmOut  := TRUE; END_IF; END_IF; IF  Reset  THEN  Timer(IN:=FALSE);  AlarmOut  := FALSE;  WarnFlag  := FALSE; END_IF;
     HMI上绑定TimeLeft显示倒计时,操作员看到还剩5秒预警就知道要动一下了。和流水线急停联锁——空闲超时自动停输送带,既省电又安全。

<b>写在最后:

先抄后改,逐步内化

分享的这 6 套 PLC 标准化模板,不是一成不变的标准答案,而是经过数百次现场量产验证的通用开发起点。
非常建议 PLC 新手和工程师同仁,先直接套用整套框架结构,快速跑通设备全流程。在程序稳定落地后,再根据自己的设备工艺、产线需求,针对性微调改造,适配专属项目场景。真正的代码标准化,从来不局限于固定逻辑,核心价值只有一个:极致的可维护性与可交接性。哪怕时隔半年、一年,换任意一位工程师接手项目,不用翻阅资料、不用反复询问,打开程序就能看懂架构、快速定位修改点位,极大降低沟通成本和运维风险。

你的项目里,有哪些自用多年、堪称封神的通用代码模板?欢迎评论区分享交流,互相学习、共同精进!

你的分享、点赞、在看、我都喜欢
转发是最大的鼓励!谢谢您的支持!
想加入电气工控自动化技术交流群
请添加班长为好友
(文章来源:吉茄豪豪)
</b></b></b></b></b></b></b>

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

关于我们·投诉举报· 用户帮助· 联系我们 · 本站服务 · 版权声明· 隐私政策 · 投搞指南

法律保护:PLC技术网,plcjs.com,plcjs.net等字样
Copyright 2010-2030. All rights reserved. 


微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码