资讯动态

IEC 61131标准详解:PLC编程语言与跨品牌移植实战指南

发布时间:2026/10/23 1:06:02 来源:尧图企业网站定制
入行第五年我第一次认真把IEC 61131标准从头到尾读了一遍。那时刚换到一家做产线集成的公司接手的第一件事就是把三个品牌的PLC程序全部摸一遍每天对着不同软件界面看同一套工艺逻辑在梯形图、功能块图和文本语言之间换来换去才真正意识到PLC编程的基础根本不在某个品牌的操作手册里而在IEC 61131这个标准里。今天这篇我想把IEC 61131标准的核心骨架和PLC编程基础知识放在一起讲清楚重点包括标准到底统一了什么、五种编程语言怎么选、同一段逻辑在四种语言里长什么样、POU和变量体系是怎么回事以及跨品牌移植时哪些坑躲不掉。这篇内容适合刚毕业的电气新人也适合从软件行业转做工业自动化的工程师少走弯路这件事越早开始越划算。1. 为什么IEC 61131能成为PLC领域的“通用语言”1.1 1993年之前的“方言时代”现在入行的人可能很难想象上世纪80、90年代的PLC编程是什么局面。每个主流品牌都有自己的编程语言和指令集甚至同一个品牌不同代产品之间程序也很难互转。梯形图作为最通用的外观大家看着都像但定时器的编号规则、触点取反的写法、字和位的寻址方式千差万别。那时候换PLC品牌几乎等于换脑方案商要重新评估工期电气工程师要重新学一套软件老程序的复用率低得可怜。国际电工委员会在1993年发布了IEC 61131系列标准的第一版思路简单却很坚决把PLC的术语、硬件要求、编程语言、通信甚至安全要求全部标准化用一份跨品牌的“普通话”取代各家的“方言”。2013年发布了第三版今天市面上绝大多数主流PLC编程工具都在向这个标准靠拢区别只在靠拢到什么程度。理解这个背景很重要因为很多新人在学的时候容易把“某品牌软件操作”错当成“PLC编程本身”实际上软件只是标准的一种实现载体。1.2 标准家族七个部分各管什么IEC 61131不是一个文件而是一个系列标准。工程上经常提到的部分如下部分内容一句话说明IEC 61131-1通用信息定义PLC的术语、功能模型、基本结构IEC 61131-2设备要求与测试电气、机械、EMC、环境及老化测试要求IEC 61131-3编程语言五种语言加公共元素全标准的核心IEC 61131-5通信PLC与PLC、PLC与上位机之间的通信模型IEC 61131-6功能安全面向安全相关系统的编程要求IEC 61131-7模糊控制模糊推理功能块定义IEC 61131-8应用与实现指南解释易混点提供落地指导早期标准里还有第4部分“用户指南”后来被撤销并入了其他部分所以现在说的IEC 61131主要指上面七个。工程上打交道最多的是第3部分编程语言其次是第1部分功能模型和第5部分通信。第6部分功能安全、第7部分模糊控制相对垂直普通项目用到得少但做安全PLC或者智能控制类产品时会碰到。如果你只打算读一个部分那一定是IEC 61131-3它定义了整个编程模型的地基。1.3 Part 3到底“统一”了什么IEC 61131-3最厉害的地方不是发明了一套新语言而是把各品牌程序中共通、但表述各异的概念抽象出来统一规定它们的语法和语义。这套骨架包括四块程序组织单元POU所有程序都由Program、Function Block、Function三种单元构成变量体系规定变量的类型、作用域、声明区VAR_INPUT、VAR_OUTPUT、VAR_GLOBAL在标准里是同一个意思数据类型从BOOL、INT、REAL这些基础类型到ARRAY、STRUCT等派生类型都有一套标准定义任务模型POU在什么条件下、以什么周期运行由Task机制统一调度。有了这四块骨架你在某品牌IDE里写的FB实例化、定时器调用、上升沿捕捉到了另一个基本符合标准的品牌环境里虽然做不到复制粘贴但概念一一对应学习成本大幅下降。这就是IEC 61131的最大价值它让“PLC工程师”的能力从依附某一品牌变成依附一套通用的工程语言。换个平台你只需要重新适应壳不需要重新学核。2. LD、FBD、ST、IL、SFC五种编程语言的选择逻辑2.1 先看思维契合度再看性能很多新人问我的第一个问题是“学哪种语言最好”。我的回答通常是不是最好而是匹配。你的思维习惯、面对的场景、同事能维护什么语言共同决定最优选择。电气背景的人脑子里装的是继电器电路图硬让他用ST写一切逻辑憋屈还容易出错软件背景的人看梯形图一行行触点会觉得信息密度太低。反过来算法密集的控制用LD写表达式展开到让人崩溃。选语言不是在选“哪个更高级”是在选“哪个跟你的问题类型对得上”。具体到每个语言不同背景的人栽跟头的地方也不一样。电气工程师学ST最容易卡在变量声明和数据类型上总想着“这行到底对应哪个触点”软件工程师学LD最容易卡在“线圈置位复位”和“扫描顺序”上总觉得这不像函数调用。我知道这些坑是因为两边我都见过人踩。解决办法只有一个每个语言至少用一个完整项目去实践别停留在“看懂”的程度。2.2 一张表说清五种语言的主场语言编程范式视觉化程度算法表达最适合的场景维护门槛LD 梯形图继电器逻辑高弱开关量逻辑、互锁、启保停、电气设备回路低电工可读FBD 功能块图信号流高中模拟量处理、PID、比例换算、通信数据处理中等ST 结构化文本高级语言低强复杂计算、数组/循环、自定义算法、协议解析中偏高IL 指令表汇编风格低中历史项目维护、老设备移植偏高SFC 顺序功能图状态机/流程图高弱多步骤顺序工艺、机械手动作、产线节拍中等LD的强项是“看得见”在线监视时触点通断、线圈得电一清二楚现场电工拿着图纸就能查。FBD适合连续调节类逻辑信号从传感器进来经过滤波、量程转换、PID再输出到执行器画出来就是一张信号流程图排查链路一目了然。ST的表达能力最强数组排序、浮点运算、字符串处理这些在LD里让人头大的事情ST里几行搞定。SFC则把“先做什么、条件满足后做什么、出错跳到哪里”用状态步骤画出来顺序控制逻辑用它来写漏步骤、状态卡死的概率会小很多。2.3 没人规定只能用一种语言标准允许在一个程序里混用语言这也是实际项目里最常用的策略。典型架构是外层用SFC组织整个设备的运行状态每个状态步骤内部用ST或FBD写动作逻辑底层启停互锁用LD。这样既有SFC的结构清晰又有ST的算法能力还有LD的直观性。我见过不少老师傅把整个程序全用LD写两百多个网络排下来能跑但每次改版都心惊胆战。新工程完全可以在规划阶段就定好语言分工启保停、急停、互锁这类跟电气图纸强相关的逻辑放LDPID、量程转换、数据校验放FBD任何带数组、循环、复杂判断的逻辑放ST整机动作顺序放SFC。这样每个POU的职责边界清楚后期维护的人不用在一堆语言里反复横跳。语言混用不是炫技是让每种语言做它最擅长的事。3. 同一个电机延时启动程序四种语言的逐行对比3.1 需求定义一个带延时、故障保护和复位的电机回路纸上谈兵不如直接看程序。下面这个需求很常见足够体现语言差异按下启动按钮StartBtn电机延时3秒启动假设启动按钮为点动型不自锁保持运行中按下停止按钮StopBtn电机立即停止热继电器动作Fault时电机立即停止同时报警灯Alarm点亮排除故障后按复位按钮ResetBtn清除报警。输入有StartBtn、StopBtn、Fault、ResetBtn四个BOOL输出是Motor和Alarm两个BOOL。我把同一逻辑分别用ST、LD、FBD、IL各写一遍并加注释。3.2 ST版最接近高级语言逻辑密度最高FUNCTION_BLOCK MotorCtrl VAR_INPUT StartBtn : BOOL; (* 启动按钮 *) StopBtn : BOOL; (* 停止按钮 *) Fault : BOOL; (* 热继电器故障 *) ResetBtn : BOOL; (* 故障复位 *) END_VAR VAR_OUTPUT Motor : BOOL; (* 电机接触器 *) Alarm : BOOL; (* 报警灯 *) END_VAR VAR StartTon : TON; (* 3秒启动延时定时器 *) END_VAR (* 网络1启动条件全部满足且电机未运行、无报警时开始3秒延时 *) StartTon(IN : StartBtn AND NOT StopBtn AND NOT Fault AND NOT Motor AND NOT Alarm, PT : T#3S); (* 网络2延时结束电机启动停止或故障立即打断 *) IF StartTon.Q THEN Motor : TRUE; END_IF; IF StopBtn OR Fault THEN Motor : FALSE; END_IF; (* 网络3故障置位报警复位按钮清除 *) IF Fault THEN Alarm : TRUE; END_IF; IF ResetBtn THEN Alarm : FALSE; END_IF;ST的写法很适合从C、Java转过来的人变量声明、IF判断、函数块调用都似曾相识。几个细节说明一下。TON是标准功能块必须在VAR区声明一个实例StartTonIN条件是累加逻辑所有条件AND在一起其中StopBtn、Fault、Motor、Alarm都要取反PT : T#3S是IEC标准的时间常量写法。这类代码最大优点是修改逻辑快——想改延时5秒改一个常量想增加“两次启动间隔限制”加一个条件即可。3.3 LD版电气工程师的母语LD在编辑器里是图形化的这里用文本形式简化示意。四个网络从上到下每个扫描周期按顺序扫一遍(* 网络13秒启动延时 *) StartBtn StopBtn Fault Motor Alarm TON_1 ---| |------|/|------|/|------|/|------|/|-------[TON]--- IN Q PT T#3S (* 网络2电机自锁输出 *) TON_1.Q Motor ---| |-------( )------- Motor | ---| |------ (* 网络3停止/故障优先断开 *) StopBtn Motor ---| |-------(R)------- Fault Motor ---| |-------(R)------- (* 网络4故障报警与复位 *) Fault Alarm ---| |-------(S)------- ResetBtn Alarm ---| |-------(R)-------读LD的关键是看“串联是AND、并联是OR、常闭触点就是取反”。网络1里StartBtn与四个常闭触点串联等于ST里那一长串AND NOT网络2用TON_1.Q并联Motor自身触点实现自锁输出网络3用R复位优先指令保证停止和故障优先级最高网络4则是一对S/R触发器。对电气专业的同事来说LD是唯一不需要编程概念就能读懂的逻辑表达。但也正因为它直观网络一多、互相引用一复杂排查跳转关系反而费力。3.4 FBD版把电路换成数据流FBD在编辑器里是连线图同一逻辑用FBD可以这样描述五个输入StartBtn、StopBtn取反、Fault取反、Motor取反、Alarm取反接到同一个AND逻辑块AND块的输出作为TON的IN输入TON的PT端设为T#3STON的Q输出与Motor自身反馈接到一个OR逻辑块OR块的输出就是Motor线圈StopBtn和Fault分别接入Motor复位的OR逻辑在不少实现里就是对Motor功能块的R端Fault接到报警RS触发器的S端ResetBtn接到同一触发器的R端Q端输出Alarm。FBD比LD的启保停电路更接近“数据处理”的思维方式信号从左边进来经过逻辑块到右边输出。碰到PID、模拟量滤波这些连续控制FBD的可读性是五种语言里最好的因为你看到的连线就是数据流。它的问题是不适合写循环和分支复杂判断写在FBD里连线会像蜘蛛网减一个条件要重拉三根线。3.5 IL版熟悉即可不必死磕IL是汇编风格一条指令一行操作符在前。对应逻辑如下LD StartBtn ANDN StopBtn ANDN Fault ANDN Motor ANDN Alarm TON TON_1, T#3S LD TON_1.Q OR Motor ST Motor LD StopBtn OR Fault R Motor, 1 LD Fault S Alarm, 1 LD ResetBtn R Alarm, 1第三版标准里IL已经不再被当作优先推荐的完整编程语言很多新推出的编程软件甚至不再提供。现在学IL主要目的就是维护2000年前后的老设备程序。如果你面对的存量设备不多这一节能看懂就好不必花时间深钻。花同样的时间多练ST回报高得多。3.6 四种写法对比后得出的选型结论维度STLDFBDIL逻辑密度高低中中电气工程师可读性差好中差软件工程师可读性好中中差在线监视体验一般最好好一般复杂算法支持强弱中弱新项目推荐度强烈推荐开关量推荐过程量推荐不推荐我的结论是开关量主回路逻辑用LD算法和数据处理用ST连续控制用FBD整机顺序用SFC包外层。这套组合在绝大多数项目里能同时照顾开发效率、现场调试和维护成本。你不需要在四种语言里做到同样熟练但你至少要能读懂它们因为存量设备不会按你的喜好选语言。4. POU、变量作用域与数据类型PLC程序的底层骨架4.1 POU三兄弟Program、Function Block、FunctionIEC 61131-3把可执行代码的最小组织单元统称为POUProgram Organization Unit分三种。Function功能没有内部状态同样的输入永远得到同样的输出比如加法、绝对值、求最大值它不保存记忆。Function Block功能块有内部状态同样的输入在不同时刻可能得到不同输出典型例子就是TON定时器——它必须记住从什么时候开始计时。用FB必须先声明实例一个FB定义可以被实例化成多个副本。Program程序是顶层入口被分配给具体的Task由PLC在扫描周期里调度执行程序内部可以调用FB和Function。这三者的区分不是理论洁癖而是工程复用基础。比如你写好MotorCtrl功能块项目里有十台风机就声明十个实例每个实例各自记忆自己的状态互不干扰。改逻辑只改FB定义所有实例全部继承改动。这不就是面向对象里“类与对象”的思路吗没错第三版标准已经正式引入了方法、接口和访问修饰符FB越来越像类。学PLC编程到后期你会赫然发现自己在用一套简化版的面向对象语言。4.2 变量的作用域在哪声明谁看得见变量声明区的规则是初学者最该先背下来的东西声明区含义典型场景VAR内部变量FB内部状态实例私有VAR_INPUT输入参数由调用者传入函数块内部只读VAR_OUTPUT输出参数向外部输出结果VAR_IN_OUT双向引用参数直接引用调用方的变量类似指针VAR_GLOBAL全局变量跨POU共享的数据如IO映射VAR_TEMP临时变量函数块本次运行中的临时存储不保持VAR_EXTERNAL外部变量在封闭POU中访问已声明的全局变量一个非常常见的坑把FB内部的中间状态变量声明成VAR而不是VAR_TEMP导致多次调用之间状态残留逻辑出现“玄学”现象。反过来需要保持历史数据的变量如果误声明成VAR_TEMP定时器和计数器就全乱了。声明区的选择本质上是回答一个问题这个值在调用结束后还要不要活着。4.3 数据类型与直接寻址从BOOL到STRUCTPLC的数据类型体系分基础类型和派生类型。基础类型包括BOOL布尔、BYTE/WORD/INT/DINT/REAL/LREAL等数值类型、TIME时间类型、STRING字符串类型。派生类型由用户通过结构体STRUCT、数组ARRAY、枚举ENUM组合生成。例如一台设备的轴参数可以定义成STRUCT把速度上下限、加速度、当前位置打包在一起可读性立刻上台阶TYPE AxisPara : STRUCT VelLimit : REAL; Accel : REAL; CurPos : REAL; END_STRUCT END_TYPE另一个基础概念是寻址。老PLC程序里经常看到%QX2.3、%IW10这种直接地址X代表位I是输入W是字。IEC 61131-3并不排斥直接地址但标准提倡符号化编程给变量起名字由编译器负责映射到具体地址。我自己的经验是物理IO映射可以集中在一个专门的POU里用符号变量对接业务逻辑里尽量别出现裸地址。这样做程序移植和排查都轻松得多也方便在仿真环境里替换IO。4.4 任务与扫描周期PLC程序的“心跳”任务模型决定你怎么理解“PLC程序怎么跑”。一个PLC软件里可以有多个Task每个Task可以配置成周期执行比如每10毫秒跑一次也可以由事件触发。Program被分配到某个Task中Task每次触发时从程序开头到结尾顺序执行一遍。所以PLC程序本质上是周期轮询式的不是事件驱动式的它没有“休眠等待”的概念一个调用链扫描结束后立刻开始下一轮。理解这个模型对诊断问题特别重要。你会明白为什么在程序末尾访问刚在开头变化过的IO会有一拍延迟为什么定时器精度受扫描周期影响为什么两个不同Task同时操作同一个全局变量会竞争。很多“偶发故障”查到最后都是对扫描周期和任务调度的理解偏差。记住PLC不是操作系统里的进程它没有中断和回调那套机制一切靠周期轮转。5. 标准之外的现实跨品牌移植的三个真相5.1 真相一标准统一的是概念不是编译器行为IEC 61131-3是一份语义标准不是一个可直接运行的软件。各家编译器在“符合标准”的框架内留下了大量解释空间。举个简单例子INT和REAL混合运算严格符合标准的实现应该报错但有的品牌会自动隐式转换同一个TON在PT0时的输出行为不同品牌可能有区别字符串函数、位访问、边沿检测的底层存储方式也千差万别。你写的是“符合标准的代码”但执行细节依然是某个厂商的执行细节。所以别指望复制粘贴就能跨平台。这也解释了为什么市面上的IEC 61131-3集成开发环境五花八门有的界面长得完全不一样。标准规定了语义骨架却没有规定IDE的交互方式、库函数的丰富程度、在线监控的呈现细节。真正会评估工具的人会先翻它支持的数据类型和功能块清单再去看它对标准的偏离程度而不是只看界面是否好看。5.2 真相二厂商扩展是双刃剑每个主流品牌都会在标准之外扩展大量专用指令运动控制、总线诊断、专有通信、工艺库等等。这些扩展确实是生产力但也恰恰是移植性的最大杀手。在一个品牌里用的轴控制功能块换个品牌完全不存在对应逻辑就必须重写。我的做法是把程序分成两层底层是依赖厂商扩展的设备层只负责跟硬件打交道上层是尽量纯ST写的业务逻辑层不调用厂商指令。这样即使更换平台重写的只有设备层业务逻辑基本能保住。厂商扩展还有个隐形代价招聘和传承。一个项目如果大量使用某品牌的私有库后面接手的工程师就必须先学那套私有库知识很难通用。相反坚持用标准功能块和标准函数写的程序任何懂IEC 61131的工程师都能快速上手。从团队管理的角度尽量缩小私有扩展的使用面是性价比很高的事。5.3 真相三ST是移植性最好的“通用语”五种语言对比下来ST跨品牌移植的摩擦最小。LD里每个品牌的线圈、置位复位、边沿指令差异太多FBD的块封装风格各异IL已经边缘化唯独ST只要坚持用标准函数和标准功能块在多数主流环境里几乎原样搬过去就能编译。所以我的建议是凡是跟硬件绑定不强的逻辑全部用ST写并且保持“保守风格”——显式类型转换、不依赖隐式转换、不用厂商专用扩展函数。这样写出来的代码虽然看着啰嗦一点但可移植性和可读性都最好。提示所谓“保守风格”的ST其实很像以前写C语言时坚持用ANSI C而不是编译器扩展图的就是一份代码多处编译。工业现场十年后替换PLC品牌是常态今天多写的几行显式转换可能帮未来的自己省下整个月。5.4 跨品牌代码迁移的可操作清单如果你真的要把一套程序从A品牌迁到B品牌照着下面清单做能少踩一半坑先迁移IO映射层把所有物理输入输出的地址关系整理成一张表把业务逻辑统一改写为ST删除厂商专用指令和专用功能块所有数据转换写成显式调用严禁依赖自动转换定时器和边沿检测全部基于标准TON、R_TRIG等FB实现全局变量集中管理禁止在FB内部直接访问裸地址用同一组输入序列做回归测试逐项比对输出行为重点关注PT0、首次扫描、通信断线等边界情况。做完这一步你会发现“换品牌重做项目”的大头工作量其实被压缩到了设备层和工程验证上而不是业务逻辑重写。这体验我亲身经历过同一套设备逻辑从日系平台迁到德系平台上层ST几乎没改设备层花了两周重新对接整体工期比预想短了一半。6. 给初学者的上手路线从搭建扫描周期心智模型开始6.1 第一步先建立扫描周期和任务的心智模型我见过太多新人一上来就埋头写梯形图写了两个月还是靠运气调试。我建议反过来第一天先别碰任何语言找设备或仿真环境做几组小实验彻底搞明白“输入刷新—程序执行—输出刷新”的扫描循环再把Task、扫描周期、IO映射这几个概念落实到具体操作里。比如做一个最简单的按钮亮灯程序观察按下按钮后输出到底晚了几拍、为什么晚几拍。这个心智模型一旦建立后面学任何语言都会快很多。这一步最大的障碍是“觉得这有什么好学的”。实际上扫描周期的心智模型决定了你能不能独立排查疑难故障。现场设备偶发抖动、报警自复位、数据错乱十有八九都能溯源到某个POU的执行时机问题。基础概念越早吃透后面越不会靠猜。6.2 第二步用ST写算法逼自己读LD掌握变量声明、POU、数据类型之后我的推荐路线是用ST练习所有算法逻辑同时用LD读老程序。ST写多了你会自然养成变量命名、拆分功能块的好习惯读LD则是补齐现场查问题能力的关键因为存量设备里LD依然是主力。每天抽半小时把一段看不懂的LD手写翻译成ST坚持一个月两种语言都会内化。翻译练习看起来很笨其实很有用。每翻译一段你要被迫弄清楚每个网络的执行顺序、每个置位复位线圈的保持特性、每个定时器的触发条件。这些细节在图形界面里很容易被眼睛滑过去写成ST就躲不掉。等你能把一个两百行的LD程序干净地翻译成ST你对这个设备的理解已经比很多写了三年程序的人强了。6.3 第三步SFC是顺序控制的必修课如果你要做机械设备、装配线、机器人工作站SFC必须单独练。SFC的核心不是语言本身而是状态机思维每个步骤有进入动作和退出动作步骤之间靠转移条件衔接支持分支和汇合。用SFC写顺序工艺逻辑的完整性直观可见调试时能一眼看出设备卡在哪个状态、为什么转移条件没满足。这个优势是LD和ST不具备的。练习SFC时我建议从一个非常简单但有真实分支的状态机开始设备空闲、自动启动、运行中、故障、复位等待。把每个状态的进入动作、退出动作、转移条件写清楚再考虑超时不满足的异常路径。做完这个再去写真的机械手流程就会发现思路完全不一样。6.4 三个适合练手的小项目新手阶段最怕“什么都学了什么都没做成”。我建议直接拿小项目练手小型喷淋系统传感器检测液位定时控制电磁阀带手动自动切换三色灯状态机用SFC实现设备启动、运行、故障、复位的完整状态流转简易排序推送两个传感器和两个气缸的配合用ST写位置判断和顺序逻辑。这三个项目分别覆盖定时与逻辑、状态机、传感器与执行器配合的经典场景。做完之后你对IEC 61131标准里提到的扫描周期、POU、变量、任务这些概念会有非常具体的理解。项目不在多每个都写完整最好带仿真验证比看十遍教程都管用。最后再分享一个我自己的习惯每当要接一台从没碰过的品牌设备我不会先翻手册而是先找一段该品牌自带的示例程序用ST“翻译”一遍。这个方法看起来绕远实际上逼着我用标准概念去覆盖厂商细节很快就能摸清这个平台的脾气。对新人来说想清楚IEC 61131到底规定了什么、厂商到底扩展了什么才是真正把PLC编程基础知识吃透的标志。

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

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

免费获取报价 →
↑