资讯动态

PLC编程实用指南:ST与梯形图混编的三种实现方式

发布时间:2026/10/30 1:10:09 来源:尧图企业网站定制
干PLC项目这些年我越来越觉得ST和梯形图之间不存在什么“二选一”。真正效率高的项目都是ST与梯形图混编出来的——用梯形图去管急停、互锁、安全回路这类“看得见”的东西用ST去写统计、数组、迭代、算法这些“算得准”的东西。很多刚接触PLC的朋友看到ST就头大觉得不如梯形图直观也有做软件出身的人觉得梯形图太啰嗦。这篇文章就聊聊ST和梯形图混编的三种常见写法它们各自适合什么场景、怎么落地、坑在哪里希望帮大家少走弯路。我下面用到的方法不绑定某一款PLC三菱GX Works、西门子博途、Codesys这类支持IEC语言的环境中基本都能对应上。文章会用一个“多电机顺序启动运行时长统计”的小案例把三种写法完整跑一遍你可以直接套到自己的项目里改一改。1. 为什么要把ST和梯形图混编而不是从头用到尾1.1 梯形图真正擅长的不是“逻辑”而是“看得见的连锁”很多人说梯形图就是“电气原理图翻版”这话只说对了一半。梯形图的核心优势其实是可观测性——左边触点、右边线圈哪个按钮没到、哪个中间继电器没吸合在线监控时一眼就能看出来。比如一台设备要满足“启动按钮按下并且没急停、前门关好、后门关好、油泵运行正常”才能开机用梯形图写成几段串联触点维护电工拿着万用表都能看懂逻辑。你让电工去查ST程序里的IF里面套了个AND他多半要骂人。但梯形图的短板也很明显一旦计算量上来比如要对一组温度数据做滑动平均、要统计50次故障中出现最多的类型编号、要根据当前速度查表再插值计算输出梯形图每个计算都得拆成一堆比较指令和运算指令程序块会膨胀得极快改起来非常容易把“主逻辑”冲散。1.2 ST真正擅长的不是“表达”而是“计算和数据处理”STStructured Text结构化文本本质上是高级编程语言的PLC版本。它有变量、有IF/CASE/FOR、有函数、有结构体甚至可以写循环。用ST写一套PID、写一个排队逻辑、写一段报表统计会比梯形图简短一个量级。但是ST也有它的问题程序块在线监控时想看某个布尔变量当前是真是假得在监视表里一个一个加变量没有梯形图那种“通电/断电”的图形感。尤其在现场调试时工艺电气工程师和你站在一起看程序满屏的“IF-THEN-ELSIF”远不如一组触点来得直观。1.3 混编的本质把“看得见”和“算得准”拆开所以ST与梯形图混编的核心思想并不是“炫技”而是把程序分成两类职责安全、互锁、手动操作、状态指示这类适合梯形图因为它们要求“能快速被现场人员读懂”并且每个周期都应被扫描到。算法、统计、转换、流程调度这类适合ST因为它们要求“能短小精悍地表达复杂计算”并且方便后续修改。混编就是把这两类职责放到各自合适的“容器”里再通过规范的接口连接。文章接下来讲的三种写法其实就是“接口怎么连”的三种典型答案。2. 三种主流混编写法逐一解析2.1 写法A梯形图壳 ST核这种写法最容易被刚接触混编的人接受也最适合改造老项目。思路梯形图作为主程序负责按钮、互锁、安全回路ST程序块封装成功能块FB/FC专门处理计算、统计、定时等“核心算法”。梯形图里通过一个调用指令把ST块“点起来”ST块通过输入变量接收梯形图的信号处理完再通过输出变量把结果送回梯形图。典型应用场景设备顺序控制为主、计算为辅的项目。比如传送带上三个工位每个工位有传感器梯形图负责判断传送带启动条件ST块负责统计每个工位计数并在数值超限时报警。为什么说它适合改造老项目老程序大多已经是梯形图想增加数据统计功能时不需要推翻原有结构只要新写一个ST功能块再在梯形图里找个合适的位置调用即可。原有逻辑一行不用动。缺点接口变量太多时调用指令的参数表会很长。我曾经见过一个ST块有二十几个输入输出参数梯形图那边的调用指令占了半个屏幕改起来也很痛苦。所以这种写法要求“接口精简、块内做的事要内聚”。示意框架梯形图网络 X0启动 --| |----[SR块调用 FB_Statistics: 启动信号:X0, 计数:CNT_C, 完成:Y5]ST功能块内部用IF判断启动信号上升沿累加计数超过阈值修改输出布尔。2.2 写法BST总调 梯形图联锁这套写法正好和写法A反过来适合流程型、状态机型项目。思路ST作为“总指挥”负责整个工艺的状态流转。比如一段自动循环包含初始化、等待、启动、加工、退回、结束这几个状态ST用CASE语句来管理当前状态、状态切换条件。每个状态具体要做的“硬输出”比如哪些接触器吸合、哪些阀动作会调用不同的梯形图子程序或梯形图功能块来完成。梯形图只负责“看见”这些具体输出的互锁条件ST负责“决策”什么时候切换。典型应用场景自动流水线、单机多步循环、带工艺步骤的多工位设备。这类项目如果全用梯形图写状态多了以后一大堆SET/RST和跳转会把程序变成蜘蛛网全用ST写现场电工又看不懂动作条件。为什么这么好用因为CASE结构天然适合“状态梳理”。每一步有一个编号程序跳到第几步就是第几步调试时在监视表里看步号就明白设备卡在哪。并且新增一个工艺步骤在CASE里插一段再新增一个梯形图动作子程序不会打乱其他逻辑。缺点要求程序员对状态划分有清晰理解否则CASE里面状态跳来跳去比梯形图跳转更难排查。示意框架CASE iStep OF 0: // 待机 IF bStart THEN iStep : 10; END_IF; 10: // 启动准备 CALL FB_PreCheck(); IF FB_PreCheck.bOK THEN iStep : 20; END_IF; 20: // 自动运行 CALL FB_RunAction(); IF bStopReq THEN iStep : 30; END_IF; ... END_CASE这里的FB_PreCheck、FB_RunAction都可以用梯形图写ST主程序只是调用它们。2.3 写法C按任务和数据域分层混编这是三种写法里格局最大的一种适合中型以上项目或多任务PLC。思路不同“任务”Task负责不同的事。PLC一般有主程序任务、周期任务、事件任务等。我们可以让主任务用梯形图专门做I/O映射、硬件互锁、急停让周期任务或事件任务用ST专门做模拟量滤波、计算、通讯数据解析、统计。两者通过“全局变量区”交换数据。典型应用场景设备既有硬逻辑又有大量运算。比如一台伺服设备主循环要处理按钮、安全门、报警连锁同时另一个周期任务要在5ms内完成位置脉冲规划、速度曲线计算。这种计算交给ST而主循环的梯形图只去读ST算好的“目标脉冲数”。为什么这么写把不同实时性要求的功能放到不同任务里可以让算法任务跑得很快而主循环任务不会被拖慢。梯形图主循环把时间用在“应急响应”上ST周期任务把时间用在“持续计算”上互不干扰。缺点对PLC的任务调度机制要有了解否则两个任务同时读写同一个全局变量可能产生数据不同步调试时还得在多个任务里切来切去。示意框架主任务梯形图扫描周期默认 X0急停 --- 总停中间继电器 Y0输出 --- 状态指示灯 周期任务ST执行周期10ms GV_nRunSec : GV_nRunSec 1; // 运行时间累加 IF GV_nRunSec MOD 600 0 THEN GV_nRunMin : GV_nRunMin 1; END_IF;2.4 三种写法怎么选维度写法A 梯形图壳ST核写法B ST总调梯形图联锁写法C 任务级分层控制流主体梯形图ST梯形图ST双主体适合项目逻辑为主、算法为辅流程/状态机为主多任务、多实时性调试直观性较高中等中等代码扩展新增ST块即可新增CASE分支梯形图块新增任务或数据域数据接口功能块参数功能块参数全局状态全局变量区为主上手难度低中高没有哪种是“绝对正确”的。小型设备用写法A最舒服设备动作步骤多、有清晰的工艺阶段用写法B设备同时存在硬互锁和高速计算用写法C。很多时候一个项目也会混用任务层用C主循环用A或B的思维。3. 实例演示顺序启动与运行统计的三种混编实现3.1 控制需求与I/O分配为了把三种写法讲透我用同一个需求来写。设备上有三台电机M1、M2、M3要求按下启动按钮后M1立即启动M1运行5秒后M2启动M2运行5秒后M3启动按下停止按钮三台电机依次停止这里简化成全部停止不做逆序急停按下后所有输出立刻断开自动累计系统总运行时间单位分钟统计启动次数如果启动次数超过设定值输出保养提示。输入输出分配地址类型含义X0输入启动按钮X1输入停止按钮X2输入急停按钮Y0输出M1接触器Y1输出M2接触器Y2输出M3接触器Y10输出保养提示灯中间数据启动次数nStartCnt、运行分钟数nRunMin、定时器变量。下面分别用写法A、写法B、写法C实现这个需求。这里只展示核心部分实际工程里还要加过载、反馈等原理相同。3.2 写法A完整实现梯形图主逻辑 ST功能块梯形图部分简化描述实际每个网络有对应指令网络1 急停切断 X2常闭 --[Y0复位]--[Y1复位]--[Y2复位] 网络2 启动保持 X0常开 --| |-- 保持M0 X1常闭 --|/|--- M0 M0保持线圈 网路3 调用ST块 M0常开 ----[CALL FB_MotorSeq]注意梯形图里尽量不要写定时器算启动顺序因为那个“5秒后启动下一台”更适合放到ST块里用TON来管理。ST功能块类的结构化文本写法FUNCTION_BLOCK FB_MotorSeq VAR_INPUT bStart : BOOL; // 启动信号来自梯形图M0 bStop : BOOL; // 停止信号 bEStop : BOOL; // 急停信号 nMaxCount : UINT; // 启动次数上限 END_VAR VAR_OUTPUT yM1 : BOOL; // M1接触器控制 yM2 : BOOL; // M2接触器控制 yM3 : BOOL; // M3接触器控制 bMaintainFlag : BOOL; // 保养提示 nStartCnt : UINT; // 启动次数 nRunMin : UINT; // 运行总分钟 END_VAR VAR tonDelay1 : TON; tonDelay2 : TON; tonRunMin : TON; rtPreTrigger : BOOL; bSeqActive : BOOL; END_VAR // —— 急停与停止复位 —— IF bEStop THEN yM1 : FALSE; yM2 : FALSE; yM3 : FALSE; bSeqActive : FALSE; tonDelay1(IN : FALSE, PT : T#0S); tonDelay2(IN : FALSE, PT : T#0S); ELSIF NOT bStop THEN // —— 启动链M1立即、M2延时5S、M3再延时5S —— IF bStart AND NOT bSeqActive THEN bSeqActive : TRUE; tonDelay1(IN : TRUE, PT : T#5S); yM1 : TRUE; END_IF; IF bSeqActive THEN // 运行时间累计 tonRunMin(IN : TRUE, PT : T#60S); IF tonRunMin.Q THEN nRunMin : nRunMin 1; tonRunMin(IN : FALSE, PT : T#0S); tonRunMin(IN : TRUE, PT : T#60S); END_IF; END_IF; // M2启动延时到且当前没停 tonDelay1(IN : bSeqActive AND NOT yM2, PT : T#5S); IF tonDelay1.Q THEN yM2 : TRUE; END_IF; // M3启动在M2已经运行后开始计时所以用tonDelay2的IN条件带yM2 tonDelay2(IN : yM2, PT : T#5S); IF tonDelay2.Q THEN yM3 : TRUE; END_IF; // 停止时全部断开 IF bStop THEN yM1 : FALSE; yM2 : FALSE; yM3 : FALSE; bSeqActive : FALSE; END_IF; END_IF; // —— 启动次数统计上升沿触发—— IF bStart AND NOT rtPreTrigger AND NOT bEStop THEN nStartCnt : nStartCnt 1; END_IF; rtPreTrigger : bStart; // 保养提示 IF nStartCnt nMaxCount THEN bMaintainFlag : TRUE; ELSE bMaintainFlag : FALSE; END_IF这段ST块把定时器、计数、分钟换算都包在了里面。调试时你只需要在梯形图看M0、Y0/Y1/Y2ST块的外部参数全部映射成变量可以在监视表里看FB_MotorSeq.nStartCnt。用写法A的体会主逻辑非常干净梯形图网络很少现场排查时先看M0是否通、再看ST块的输出BOOL是真是假定位很快。需要注意ST功能块里的内部定时器不能重复做多个实例如果你在梯形图里调用两次同一个FB实例等于同一个定时器被两个网络共用逻辑会冲突。3.3 写法B完整实现ST总调 梯形图联锁功能块这种写法先要建几个“梯形图功能块”负责具体动作FC_SafetyCheck梯形图网络判断急停、停止、启动按钮输出一个综合安全信号。FC_OutputStage梯形图网络根据当前步号和互锁条件输出Y0/Y1/Y2。然后ST主程序就像一个“总厂长”只安排流程不直接碰硬件点。梯形图功能块1示例简化描述网络急停常闭点 停止常闭点 启动常开 bSafeReady示意图[ X2常闭 ] --- [ X1常闭 ] --- [ X0常开 ] ---- bSafeReady梯形图功能块2示例网络 bStepActive - Y0 bStepActive AND tonDelay1.Q - Y1 bStepActive AND tonDelay1.Q AND tonDelay2.Q - Y2ST主程序PROGRAM PRG_Main VAR stSafety : FC_SafetyCheck; stOut : FC_OutputStage; iStep : INT; tonStep1 : TON; tonStep2 : TON; nRunMin : UINT; nStartCnt: UINT; tonMin : TON; bOldStart: BOOL; END_VAR // 先采集安全条件 stSafety( xStart : X0, xStop : X1, xEStop : X2 ); // 状态机 CASE iStep OF 0: // 待机 IF stSafety.bSafeReady THEN iStep : 10; nStartCnt : nStartCnt 1; tonStep1(IN : FALSE, PT : T#0S); tonStep2(IN : FALSE, PT : T#0S); END_IF; 10: // M1运行 IF NOT stSafety.bSafeReady THEN iStep : 0; ELSIF X1 THEN // 停止按钮直接停 iStep : 0; ELSE tonStep1(IN : TRUE, PT : T#5S); IF tonStep1.Q THEN iStep : 20; END_IF; END_IF; 20: // M1M2运行 IF X1 THEN iStep : 0; ELSE tonStep2(IN : TRUE, PT : T#5S); IF tonStep2.Q THEN iStep : 30; END_IF; END_IF; 30: // 三台全运行 IF X1 THEN iStep : 0; END_IF; END_CASE; // 输出由梯形图块根据步号执行 stOut( bEnable : (iStep 10), bM2Delay : (iStep 20), bM3Delay : (iStep 30), yM1 : Y0, yM2 : Y1, yM3 : Y2 ); // 运行分钟累计 IF iStep 10 THEN tonMin(IN : TRUE, PT : T#60S); IF tonMin.Q THEN nRunMin : nRunMin 1; tonMin(IN : FALSE, PT : T#0S); tonMin(IN : TRUE, PT : T#60S); END_IF; END_IF这个写法里梯形图功能块FC_SafetyCheck和FC_OutputStage都是“纯硬件接口”ST只提供条件。你在线监视时查看iStep当前值是10、20还是30立刻知道设备跑到哪个阶段。如果现场急停触发了你查的是stSafety.bSafeReady以及梯形图网络里X2触点而不是满屏的ST。这就是混编在状态机项目里的价值。3.4 写法C完整实现主任务梯形图 周期任务ST这种写法要把工程配置成两个任务主任务MainTask梯形图。扫描周期默认通常10ms左右负责采集X0/X1/X2映射到全局变量GV_bStart/GV_bStop/GV_bEStop把全局变量GV_bM1/GV_bM2/GV_bM3映射到Y0/Y1/Y2做急停的硬切断X2常闭复位Y0/Y1/Y2周期任务FastTaskST。执行周期可设50ms负责顺序启动、延时计时、计数、运行分钟统计。因为计算不需要1ms级响应周期任务更节省CPU。全局变量区伪代码VAR_GLOBAL GV_bStart : BOOL; GV_bStop : BOOL; GV_bEStop : BOOL; GV_bM1 : BOOL; GV_bM2 : BOOL; GV_bM3 : BOOL; GV_nStartCnt : UINT; GV_nRunMin : UINT; GV_bMaintain : BOOL; END_VAR主任务梯形图示意X0 --[MOVE GV_bStart:TRUE] X1 --[MOVE GV_bStop:TRUE] // 急停回路 X2常闭 --[Y0:FALSE] --[Y1:FALSE] --[Y2:FALSE] // 输出映射 GV_bM1 --[Y0 : TRUE] GV_bM2 --[Y1 : TRUE] GV_bM3 --[Y2 : TRUE]注意这里的输出映射也要考虑急停优先实际工程中急停应该通过安全继电器硬回路去切PLC程序只是辅助。周期任务STPROGRAM PRG_Algorithm VAR ton1 : TON; ton2 : TON; bSeqActive : BOOL; bOldStart : BOOL; END_VAR // 急停或停止关闭顺序 IF GV_bEStop OR GV_bStop THEN GV_bM1 : FALSE; GV_bM2 : FALSE; GV_bM3 : FALSE; bSeqActive : FALSE; ton1(IN:FALSE, PT:T#0S); ton2(IN:FALSE, PT:T#0S); ELSE // 启动 IF GV_bStart AND NOT bOldStart AND NOT bSeqActive THEN bSeqActive : TRUE; GV_bM1 : TRUE; GV_nStartCnt : GV_nStartCnt 1; END_IF; IF bSeqActive THEN ton1(IN : GV_bM1, PT : T#5S); IF ton1.Q THEN GV_bM2 : TRUE; END_IF; ton2(IN : GV_bM2, PT : T#5S); IF ton2.Q THEN GV_bM3 : TRUE; END_IF; END_IF; // 运行时间累计 IF bSeqActive THEN // 每60秒加1分钟这里简化使用TON END_IF; END_IF; bOldStart : GV_bStart; // 保养判断 IF GV_nStartCnt 1000 THEN GV_bMaintain : TRUE; ELSE GV_bMaintain : FALSE; END_IF写法C的好处主任务梯形图不需要知道“先M1后M2再M3”的流程它只管“GV_bM1为真则Y0输出”。急停时可以直接在梯形图里强制复位输出即使ST任务卡死输出仍然能被切断。这正好体现了“任务级混编”的安全隔离优势。3.5 编译下载与在线调试注意事项不管用哪种写法实际调试时有几个通用习惯第一先编译后下载别在运行中直接改接口。ST功能块增删输入输出参数后梯形图调用指令的参数列表也会变下载时PLC一般会停机。建议先在仿真器里编译通过再下载到设备。第二在线监控时梯形图和监视表配合着看。梯形图看触点通断很快但要观察ST里的数值变量变化就打开“监视表/看窗体”把nStartCnt\ nRunMin\ iStep等关键变量拖进去。我习惯把监视表分成两栏一栏是ST内部状态变量一栏是梯形图映射地址左右对照。第三强制输出前先断开执行条件。在ST里强制变量可以但在梯形图里在Y0线圈上强制TRUE若控制的是一台真实电机会有危险。建议先在输出点断开负载或者使用“仿真模式”测试。4. 混编项目中的数据结构、命名与注释规范4.1 定义“语言边界”比写代码更重要混编项目里梯形图和ST之间来回传数据的区域就是“边界”。边界不清晰乱得最快。两个典型反面教材梯形图里直接使用ST块的内部变量相当于把ST内部实现细节暴露给外部。之后ST块一改梯形图这边编译错一片。ST里直接读写PLC的I/O地址比如WHILE TRUE DO Y0 : ...;这样梯形图就完全没法做互锁。以后修改急停逻辑还得钻进ST里头找。所以我的习惯是所有跨语言访问的目的地必须是功能块接口或全局变量区不允许直接访问绝对地址。这条规则让每一个混编项目都保持清爽。4.2 用结构变量统一接口减少散乱BOOL当三个电机的状态、控制字、反馈都要传给ST时不要一个个散开VAR_INPUT mot1_run : BOOL; mot1_fb : BOOL; mot1_flt : BOOL; mot2_run : BOOL; ... END_VAR这样参数表会变得很长而且很容易把一号电机和三号电机的信号填反。更建议用UDT结构体把同一台设备的信号打包TYPE ST_Motor : STRUCT bRun : BOOL; bFeedback : BOOL; bFault : BOOL; nMaintCnt : UINT; END_STRUCT END_TYPE然后功能块接口变成VAR_IN_OUT Motors : ARRAY[1..3] OF ST_Motor; END_VAR梯形图调用时只需要把三个电机的接口数据一次性放入数组ST块里用FOR循环处理代码量立刻降下来参数也不容易填错。4.3 注释不是给PLC看的是给三个月后的自己看的ST和梯形图混编项目最危险的就是“别人接手时不知道这个ST块是谁调用的、为什么这么写”。我在ST功能块的开头固定写这几行注释功能块名称、创建日期、作者调用位置在哪一个梯形图网络/哪一个状态中被调用输入输出变量的物理含义更新记录比如// // FB_MotorSeq - 三电机顺序启动控制与运行统计 // 创建2025-05-10 // 功能输入启动/停止/急停信号输出三路接触器 // 内部管理5s/5s延时、启动计数、运行分钟累计 // 调用位置主程序网络3 // 修改记录 // 2025-05-12 增加nMaxCount上限判断 //梯形图侧的调用网络也一样加个注释块说明“这里调用FB_MotorSeq启动信号来自M0输出Y0/Y1/Y2”。4.4 版本管理要跟上ST代码一定要留文本备份梯形图在大多数PLC软件里是二进制或专有格式对比版本不方便但ST代码本质是文本。所以我每次改动ST功能块都会把代码复制到一个带日期和版本号的文本文件里和PLC项目同步备份。遇到“昨天还能跑今天改了几行就不动”的情况直接文本对比就能找出哪行变了。如果团队用Git可以把ST源文件打包进仓库diff一下非常直观。5. 常见问题与排查技巧5.1 ST块运行正常但梯形图里输出不对实例化顺序现象ST块里明明有输出梯形图线圈却不亮。排查多数是因为同一个ST功能块被调用了两次或者同一个全局变量在两个功能块里互相覆盖。比如你在网络1给SR.M1 : TRUE在网络5又给SR.M1 : FALSE扫描顺序靠后的会“吃掉”前面的结果。处理确定ST块的“唯一调用位”如果不确定在梯形图里搜索功能块实例名看出现几次。混编项目里我要求每个ST功能块只在一个网络调用输出变量不允许在第二个地方赋值。5.2 ST里的TON定时器“不启动”现象ST里写ton1(IN : TRUE, PT : T#5S);但Q始终不变。原因很多环境下TON是功能块你必须在每个扫描周期都执行一次这个调用。如果这个调用被写在IF分支里条件不满足时就不执行定时器就永远不运行。处理把TON调用放到IF外面或确保每个扫描周期都调用它。条件用IN参数控制。我总结的写法是// 定时器一律无条件调用 ton1(IN : bCondition, PT : T#5S); IF ton1.Q THEN // 动作 END_IF;5.3 编译报错类型不匹配到处都是ST和梯形图交互时常见错误是BOOL、BIT、WORD、INT之间互相混用。尤其是从梯形图把WORD给ST块当UINT或者读回来时忘了类型转换。许多平台不允许隐式转换会红色报错。处理接口保持简单能用BOOL就用BOOL能用INT就用INT。确实需要位操作时在ST块内部转换不要暴露给梯形图。例如nTemp : WORD_TO_UINT(wStatusWord); bReady : nTemp.0; // 某些平台支持位访问5.4 安全回路混编后“失效”了现象急停按钮按下ST块里的逻辑已经停止但输出接触器没断开。原因ST只负责逻辑计算不等于物理输出中断。如果你把急停完全交给ST处理一旦CPU死机、通信异常输出仍可能保持。处理急停、安全门、光栅、双手启动这类安全信号必须经过安全继电器或安全PLC硬回路PLC程序只作为辅助逻辑。梯形图里也应该有独立的“急停切断”网络即使ST功能块不执行也能通过梯形图常闭触点把输出复位。这个原则在我做过的项目里没有任何例外。5.5 全局变量被两个任务同时写数据“跳来跳去”写法C里常见。一个任务在算另一个任务在显示全局变量刷新不同步。处理若PLC支持“数据区快照”在主任务映射时一次性读取或把统计结果用中间变量缓冲一次只在指定周期复制到显示变量。宁可数据显示慢几十毫秒也不能出现一会儿大一会儿小。6. 关于混编我个人的一点体会从最早只会梯形图到后来硬着头皮写ST再到现在熟练地在两者之间切来切去我最大的转变是不再纠结“哪个语言更高级”而是问“这段逻辑将来谁会看、谁会改、有没有实时性要求”。如果这段逻辑是全厂电气维修师傅也要面对的我一定用梯形图因为现场最怕的就是“只有你能看懂的程序”。如果这段逻辑涉及大量数据计算比如统计数组、配方表、排队逻辑我就抽到ST功能块里因为梯形图写那些确实遭罪。两种语言在同一个项目里并不打架反而是很自然的分工一个管好“面子”——安全联锁和手动操作一个管好“里子”——算法和调度。最后再分享一个小技巧刚开始尝试混编时不要把一个写得很复杂的梯形图直接改成ST。更好的做法是先新建一个ST功能块把原来梯形图里最头痛的那一段“丑逻辑”原封不动翻译进去然后在梯形图里调用它跑通。跑通之后再去优化ST内部代码。这样你既不会因为改坏了主程序被现场追着骂也能慢慢体会到ST的清爽。等你习惯了这种切换自然就会找到属于你自己的混编风格。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑