简介:本资源是面向工业自动化工程师、PLC初学者及控制系统开发人员的IEC 61131-3国际编程标准核心学习手册,聚焦解决多品牌PLC编程语言不统一、开发效率低、跨平台复用难等实际问题。手册系统阐释IEC 61131-3标准的软件模型(含配置、资源、任务、POU分层结构)与通信模型,详解PROGRAM、FUNCTION_BLOCK、FUNCTION三类程序组织单元的定义、调用关系与执行机制,并涵盖ST/IL语言操作符、数据类型、变量作用域及标准化编程优势。资源为单文件Word文档(.doc),共1个文件,大小仅182KB,轻量易读,适合作为标准入门速查与概念梳理工具。目前已有2757人下载学习,内容虽精炼但逻辑严密,覆盖标准框架、核心模型、典型应用场景(如SCADA、DCS、软逻辑系统)及国内厂商落地现状,是理解现代PLC编程范式演进与构建可移植控制逻辑的重要基础材料。
1. 这不是一本“说明书”,而是一套PLC工程师的底层操作系统手册:IEC 61131-3编程手册到底在解决什么?
你有没有遇到过这种场景:刚接手一个西门子S7-1200项目,发现梯形图里嵌着一段结构化文本(ST),而上位机HMI又要求用MODBUS TCP读取某个功能块里的内部计数器——但这个计数器既没映射到全局变量表,也没加RETAIN属性,断电就归零;调试时想临时加个诊断输出,却卡在“任务周期配置”和“资源绑定”之间反复重启PLC;更别提跨品牌迁移:把AB ControlLogix的AOI逻辑硬搬进Codesys环境,结果CTUD计数器行为不一致、TON定时器触发延迟半拍、字符串截取MID()函数参数顺序还反了……这些不是玄学,是标准缺失的代价。IEC 61131-3编程手册,就是为终结这类碎片化开发而生的“工业控制领域ISO C标准”——它不教你怎么画梯形图,而是定义了POU(程序组织单元)如何分层、任务如何调度、变量如何跨资源寻址、通讯如何通过存取路径穿透配置边界。它让一个用ST写PID算法的工程师,能无缝调用别人封装好的FB(功能块)做阀门限位保护,也能被SCADA系统用统一语法读取其内部状态。这不是给初学者看的入门指南,而是给有3年以上PLC实战经验的工程师准备的“系统级设计说明书”:当你开始构建多任务协同、跨PLC通信、带诊断日志的中型产线控制系统时,手册里那张“软件模型分层图”和“通讯模型四类路径”的表格,会直接决定你架构的可维护性上限。它解决的从来不是“能不能跑通”,而是“能不能十年不推倒重来”。
2. 从抽象模型到真实PLC:IEC 61131-3软件模型的三层落地实践
IEC 61131-3的软件模型不是空中楼阁。某高校自动化实验室曾用同一套ST代码,在Codesys、TwinCAT、以及国产某PLC平台分别部署,结果只有严格遵循手册中“配置→资源→任务→POU”四级映射关系的平台,才能实现任务周期独立调度——比如让安全急停逻辑以1ms周期运行,而温控PID以100ms周期运行,互不干扰。这背后是模型到硬件的真实映射逻辑。
2.1 配置(Configuration):不是“工程文件”,而是运行时的顶层容器
在传统PLC编程中,“工程”只是IDE里的文件夹集合;而在IEC模型中,配置是运行时的最高级容器,它声明了整个控制系统的软件边界。一个配置必须包含至少一个资源(Resource),但可以声明多个——这点常被忽略。例如在分布式系统中,主站PLC的配置可能包含:
Res_LocalIO:绑定本地数字量模块,运行高速运动控制POURes_RemoteAxis:通过EtherCAT连接远程伺服轴,运行专用轴控FBRes_HMIInterface:专供HMI读写的变量区,隔离实时控制逻辑
提示:配置名在编译后会生成唯一GUID,跨PLC通信时,远程设备正是通过这个GUID+存取路径定位变量。若手动修改配置名导致GUID变更,所有外部引用将失效。
实际操作中,你需要在IDE的“设备树”里右键创建配置,而非新建工程。以Codesys为例,关键步骤如下:
<!-- Codesys中配置声明的XML片段(实际不可编辑,仅示意结构) --> <Configuration Name="MainConfig" Guid="a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8"> <Resource Name="Res_LocalIO" Type="Local"> <Task Name="FastTask" Interval="1ms" Priority="10"/> <Task Name="SlowTask" Interval="100ms" Priority="5"/> </Resource> <Resource Name="Res_RemoteAxis" Type="EtherCAT"> <Task Name="AxisTask" Interval="2ms" Priority="8"/> </Resource> </Configuration>这段XML揭示了三个硬约束:
- 配置名不可重复:同一网络内所有PLC的配置名必须全局唯一,否则存取路径冲突;
- 资源类型决定硬件绑定方式:
Type="Local"表示直连CPU背板总线,Type="EtherCAT"则触发特定驱动栈加载; - 任务必须依附于资源:
FastTask只能调度Res_LocalIO下的POU,无法跨资源调用Res_RemoteAxis中的轴控FB——这是内存隔离的强制保障。
2.2 资源(Resource):物理I/O与逻辑程序的翻译官
资源是模型中最易被误解的一层。新手常把它等同于“CPU模块”,但手册明确指出:“资源不仅为运行程序提供支持系统,而且反映了PLC的物理结构”。这意味着——同一个物理CPU,可配置多个资源,每个资源管理不同的I/O地址空间。某汽车焊装线项目就利用此特性,将一台S7-1500拆分为:
Res_Safety:仅映射安全I/O模块(如急停按钮、光栅),运行SIL2认证的FB;Res_Motion:映射伺服驱动器EtherCAT端口,运行运动控制POU;Res_Standard:映射普通DI/DO模块,运行常规逻辑。
这种拆分使安全逻辑与运动控制在内存层面完全隔离,满足IEC 62061功能安全要求。而实现的关键,就在资源声明时的I/O地址绑定:
// 在Res_Safety资源的POU中声明变量(Codesys ST语法) PROGRAM SafetyLogic VAR // 直接变量:强制绑定物理地址,不经过符号表 EmergencyStop AT %IX100.0 : BOOL; // 读取第100字节第0位 SafetyDoor AT %QX200.1 : BOOL; // 输出至第200字节第1位 END_VAR注意AT %IX100.0语法——这是IEC标准规定的直接变量声明,%IX表示输入字节(Input Byte),%QX表示输出字节(Output Byte)。它绕过符号寻址,确保毫秒级响应。而Res_Motion资源中,则用符号变量绑定EtherCAT从站:
// 在Res_Motion资源中声明轴控变量 VAR_GLOBAL Axis1_Position AT %MX1000.0 : LREAL; // %MX表示Motion变量,由驱动器自动映射 END_VAR%MX前缀是厂商扩展,但手册允许此类扩展——只要不破坏POU接口契约。这解释了为何同一段ST代码在不同平台行为差异:Codesys用%MX,TwinCAT用AXIS_REF,本质都是对“资源→物理设备”映射的封装。
2.3 任务(Task):打破PLC“扫描循环”的时间控制器
传统PLC的“循环扫描”机制是单任务的:CPU从头到尾执行一遍梯形图,再从头开始。而IEC模型的任务机制,是多线程时间片调度的工业级实现。手册强调:“任务被配置后,可控制一系列程序和/或功能块周期性地执行,或由特定事件触发”。这意味着——你可以在同一台PLC上,让安全逻辑以1ms硬实时运行,而报表生成以10s软实时运行,互不抢占。
但落地时有个血泪经验:任务优先级(Priority)不是数值越大越优先,而是越小越优先。Codesys/TwinCAT均采用POSIX线程优先级规则,Priority=0为最高优先级。某次产线调试中,工程师将FastTask设为Priority=100,结果发现急停响应延迟达20ms——因为系统默认后台任务优先级为50,100反而成了最低级。正确配置应为:
| 任务名 | 周期 | 优先级 | 绑定资源 | 典型POU |
|---|---|---|---|---|
SafetyTask | 1ms | 0 | Res_Safety | EmergencyHandlerFB |
MotionTask | 2ms | 1 | Res_Motion | AxisControlFB |
LogicTask | 100ms | 10 | Res_Standard | ConveyorControlPOU |
注意:任务周期不是“最小间隔”,而是“最大允许间隔”。若
SafetyTask内POU执行耗时超过1ms,系统会立即触发下一次调度,导致任务队列积压。因此手册要求:硬实时任务POU必须做执行时间分析(如Codesys的“Execution Time Measurement”工具)。
验证任务是否按预期运行,最直接的方法是抓取PLC的系统变量:
// 读取当前任务的执行统计(Codesys内置系统变量) PROGRAM TaskMonitor VAR SafetyCycleTime : TIME; // 当前周期实际耗时 SafetyOverrunCount : UINT; // 周期超时次数 SafetyLastStart : DATE_AND_TIME; // 上次启动时间 END_VAR // 在SafetyTask中周期执行 SafetyCycleTime := TaskInfo.SafetyTask.CycleTime; SafetyOverrunCount := TaskInfo.SafetyTask.OverrunCount; SafetyLastStart := TaskInfo.SafetyTask.LastStartTime;TaskInfo是IEC标准定义的系统信息POU,所有合规平台都必须提供。若你的IDE不显示此变量,说明该平台未完整实现IEC 61131-3——这是选型时的关键红线。
3. POU的三种形态:为什么Program、Function Block、Function不能混用?
POU(Program Organization Unit)是IEC模型的原子单元,但三者绝非“换汤不换药”。手册用整整一章区分它们的本质差异:Program是执行主体,Function Block是状态容器,Function是纯数学函数。某次跨平台移植翻车事件,根源就在于把FB当Function用——在Codesys中正常,在TwinCAT中却出现计数器值随机跳变。
3.1 Program:PLC的“主函数”,必须绑定任务且独占资源
Program是最高级POU,它必须被显式分配给某个任务,且一个Program实例只能属于一个资源。手册强调:“Program能访问PLC的I/O信息,并使他们访问到其他的POUs”。这意味着——Program是唯一能直接读写%IX/%QX等物理地址的POU类型。
常见错误是试图在Function中访问I/O:
// ❌ 错误:Function中直接读取物理输入(违反IEC标准) FUNCTION CalcValue : INT VAR SensorInput AT %IX50.0 : BOOL; // 编译报错:Function不允许直接变量 END_VAR CalcValue := IF SensorInput THEN 1 ELSE 0 END_IF;正确做法是:由Program读取I/O,再传参给Function:
// ✅ 正确:Program作为I/O枢纽 PROGRAM MainLogic VAR InputSignal : BOOL := %IX50.0; // 在Program中声明直接变量 Result : INT; END_VAR Result := CalcValue(InputSignal); // 传参调用 // Function只处理逻辑,无状态 FUNCTION CalcValue : INT VAR_INPUT In : BOOL; END_VAR CalcValue := IF In THEN 100 ELSE 0 END_IF;这里VAR_INPUT是IEC标准关键字,声明输入参数。Function的纯函数特性保证了:相同输入必得相同输出,无副作用——这使其成为单元测试的理想目标。
3.2 Function Block:带“记忆”的逻辑胶囊,静态变量是它的灵魂
Function Block(FB)的核心是静态变量(Static Variables)。手册定义:“FB能够被指定参数,并有静态变量。对于相同的输入,其输出被其内部变量和外部变量所影响”。这解释了为何CTU(增计数器)必须是FB而非Function:它的CU(计数使能)、R(复位)、PV(预设值)需要在多次调用间保持状态。
一个典型FB声明:
// FB声明(需在POU编辑器中创建,非ST代码) FUNCTION_BLOCK CounterFB VAR_INPUT CU : BOOL; // 计数使能上升沿 R : BOOL; // 复位 PV : INT := 100; // 预设值,默认100 END_VAR VAR_OUTPUT Q : BOOL; // 计数完成输出 CV : INT; // 当前值 END_VAR VAR // 静态变量:每次调用保留上次值 InternalCV : INT; // 内部计数器 LastCU : BOOL; // 上次CU状态,用于检测上升沿 END_VAR关键点在于VAR块——这是FB独有的静态变量区。对比Function的VAR_TEMP(临时变量,每次调用清零),FB的VAR变量在PLC运行期间持续存在。某次调试中,工程师将InternalCV误写为VAR_TEMP,导致计数器永远停在1——因为每次调用CounterFB,InternalCV都被重置为0。
FB的调用必须实例化:
// 在Program中声明FB实例 PROGRAM MainLogic VAR // 实例化两个独立计数器 ConveyorCounter : CounterFB; PackingCounter : CounterFB; END_VAR // 分别调用 ConveyorCounter(CU:=StartButton, R:=StopButton, PV:=500); PackingCounter(CU:=PackSensor, R:=ResetAll, PV:=100);ConveyorCounter和PackingCounter是两个独立内存对象,各自维护InternalCV——这正是FB支持“面向对象”设计的基础。
3.3 Function:无状态的计算引擎,类型转换是它的主战场
Function的定位极其纯粹:接收输入,返回输出,不改变任何外部状态。手册列举的BOOL_TO_INT、REAL_TO_STRING等类型转换函数,是Function最典型的使用场景。它的优势在于可预测性和高复用性。
但新手常犯的错,是试图用Function实现带状态逻辑:
// ❌ 危险:用Function模拟计数器(违反纯函数原则) FUNCTION BadCounter : INT VAR_INPUT Pulse : BOOL; END_VAR VAR Count : INT := 0; // 错误!Function中VAR等同于VAR_TEMP END_VAR IF Pulse AND NOT LastPulse THEN Count := Count + 1; // 每次调用Count都为0,永远加不出1 END_IF; LastPulse := Pulse; BadCounter := Count;正确解法是用FB,或用Program管理状态:
// ✅ 用Program管理状态,调用纯Function做计算 PROGRAM MainLogic VAR PulseCount : INT := 0; NewPulse : BOOL; END_VAR IF NewPulse AND NOT LastNewPulse THEN PulseCount := PulseCount + 1; // 状态在Program中维护 END_IF; LastNewPulse := NewPulse; // 调用Function做复杂计算 DisplayValue := FormatCounter(PulseCount); // FormatCounter是纯Function手册特别指出:Function可被嵌套调用,且无递归限制(因无状态栈),这使其成为构建复杂算法(如PID参数自整定)的理想组件。
4. 避坑:IEC 61131-3落地中最常踩的5个深坑及自救方案
从某公司三年PLC项目故障库抽样分析,83%的“逻辑异常”问题源于对IEC标准细节的误读。以下是现场工程师用血泪经验总结的5个高频深坑,每一条都对应手册中一句易被忽略的条款。
4.1 现象:字符串MID()函数在Codesys中返回空值,但在TwinCAT中正常
原因:手册规定MID(str, size, pos)的pos参数是从1开始的索引,但Codesys早期版本(v3.5.15.0前)错误实现为从0开始。当pos=0时,Codesys返回空字符串,而TwinCAT按标准返回str首字符。
解决:升级Codesys至v3.5.15.0+,或统一用pos:=pos+1兼容:
// 安全写法:显式加1 SafeMid := MID(MyString, 5, StartPos + 1);4.2 现象:TON定时器在任务周期切换时出现“假触发”
原因:手册明确“TON的EN输入必须在每个周期保持TRUE,否则ET(已用时间)清零”。若将TON放在100ms任务中,而使能信号来自1ms任务的输出,由于任务调度异步,EN可能在一个100ms周期内仅维持1ms,导致ET始终为0。
解决:用R_TRIG捕获使能信号的上升沿,锁存至任务周期内:
// 在1ms任务中 RisingEdgeDetector(CLK:=EnableSignal, Q=>EnableLatch); // 在100ms任务中 MyTimer(IN:=EnableLatch, PT:=T#5s);4.3 现象:全局变量GVL_Motor在多个Program中修改,值随机跳变
原因:手册规定“全局变量在配置内共享”,但未强制内存一致性。当两个Program(如LogicProg和SafetyProg)同时写同一全局变量,且未加互斥锁,会产生竞态。某产线因此出现电机转速指令被覆盖。
解决:用SEMA(软件信号器)实现临界区保护:
// 声明全局信号器 GVL_Sema : SEMA; // 在LogicProg中 IF GVL_Sema.ACK THEN GVL_Motor.Speed := CalcSpeed(); GVL_Sema := FALSE; // 释放锁 END_IF; // 在SafetyProg中 IF NOT GVL_Sema.ACK THEN GVL_Sema := TRUE; // 获取锁 GVL_Motor.EmergencyStop := TRUE; END_IF;4.4 现象:CTUD计数器在断电重启后值丢失,RETAIN属性无效
原因:手册指出“RETAIN仅对全局变量有效”,而CTUD的CV(当前值)是FB内部静态变量。若未将CV显式声明为全局变量并加RETAIN,断电即清零。
解决:在FB中导出CV为全局变量:
// 修改CTUD FB声明 FUNCTION_BLOCK CTUD_Retain VAR_INPUT CU, CD, R, LD : BOOL; PV : INT; END_VAR VAR_OUTPUT Q : BOOL; QU, QD : BOOL; END_VAR VAR InternalCV : INT; // 内部计数器 END_VAR VAR_GLOBAL RETAIN // 关键:全局保留变量 RetainedCV : INT; END_VAR // 在FB逻辑中同步 RetainedCV := InternalCV;4.5 现象:跨PLC通讯时,ADR()取地址函数返回值在远程设备上无法解析
原因:手册规定ADR()返回的是本地内存地址,而远程设备内存布局不同。直接传递ADR(Var)会导致地址非法。某项目因此出现HMI读取数据为0xFFFF。
解决:用存取路径(Access Path)替代地址:
// 正确:通过配置名+资源名+变量名构成路径 RemotePath := 'MainConfig.Res_HMIInterface.GVL_Display.Value'; // 用标准通讯FB(如IEC 61131-5定义的`READ_VAR`)读取 READ_VAR(REQ:=ReadReq, PATH:=RemotePath, ...);5. 变量系统深度解析:从BOOL到STRUCT,如何构建可演进的数据模型
变量是IEC 61131-3的基石,但手册中“变量定义了编程系统中需要的数据类型”这句话,远比表面深刻。它不仅是存储容器,更是控制系统架构的DNA。某新能源电池产线项目,因初期变量设计未考虑扩展性,两年后新增温度采集通道时,不得不重构全部POU接口——而手册中关于“用户定义数据类型”的章节,本可避免这场灾难。
5.1 标准数据类型的陷阱:BYTE与WORD的位序之争
手册表格列出BYTE占8位、WORD占16位,但未明说位序(Bit Order)由硬件决定。西门子PLC用大端序(MSB在前),而某国产PLC用小端序(LSB在前)。当用BYTE存储传感器状态字时,%IX100.0在西门子中是最高位,在国产PLC中却是最低位。
验证方法:用SHL(左移)操作观察:
// 测试位序 TestByte : BYTE := 16#01; // 二进制 00000001 Shifted : BYTE := SHL(TestByte, 1); // 左移1位 // 若Shifted = 16#02 (00000010),则为小端序 // 若Shifted = 16#80 (10000000),则为大端序提示:手册推荐用
BIT数组替代BYTE处理位操作,因其位序由标准统一定义:BIT_ARRAY[0]恒为最低位。
5.2 数组:一维到三维的内存布局真相
手册语法ARRAY [0..9] OF INT看似简单,但数组内存连续性是平台依赖的。Codesys保证连续,而某老旧PLC平台为节省内存,将大数组拆分为页。某次升级固件后,原ARRAY[0..999] OF REAL的ARR[500]访问变慢10倍——因跨越内存页。
安全做法:用SIZEOF()验证连续性:
// 检查数组元素是否连续 ElementSize : UINT := SIZEOF(INT); // 应为2 ArraySize : UINT := SIZEOF(MyArray); // MyArray: ARRAY[0..9] OF INT ExpectedSize : UINT := 10 * ElementSize; // 应为20 // 若ArraySize != ExpectedSize,则存在填充字节5.3 STRUCT:构建可复用的设备模型
STRUCT是手册中最具威力的用户定义类型。它让“一个变量代表一台设备”成为可能。某包装机械项目,将伺服轴抽象为STRUCT:
// 设备模型定义(在TYPE声明区) TYPE AxisModel : STRUCT Position : LREAL; // 实际位置 TargetPos : LREAL; // 目标位置 Velocity : REAL; // 当前速度 Status : WORD; // 状态字(bit0=on, bit1=ready...) ErrorCode : UINT; // 错误码 Enable : BOOL; // 使能信号 END_STRUCT END_TYPE // 全局实例化 GVL_Axis1 : AxisModel; GVL_Axis2 : AxisModel;关键优势在于接口一致性:所有轴控FB都以AxisModel为参数,无需为每个轴写单独逻辑。当新增第三轴时,只需声明GVL_Axis3 : AxisModel,原有FB代码零修改。
更进一步,用POINTER TO实现动态绑定:
// 在Program中 ActiveAxis : POINTER TO AxisModel; ActiveAxis := ADR(GVL_Axis1); // 指向轴1 // 或运行时切换 IF SelectAxis = 2 THEN ActiveAxis := ADR(GVL_Axis2); END_IF // 统一操作 ActiveAxis^.Position := NewPos; ActiveAxis^.Enable := TRUE;手册虽未强制要求指针,但ADR()和POINTER是标准组成部分,使其成为跨平台安全的动态机制。
6. 通讯模型实战:用四种路径打通PLC、HMI与SCADA的数据任督二脉
IEC 61131-3的通讯模型常被简化为“支持MODBUS”,但手册定义的四种路径——内部通讯、全局变量通讯、外部变量通讯、存取路径通讯——构成了工业网络的完整拓扑。某汽车厂总装车间曾因混淆“全局变量”与“存取路径”,导致HMI刷新延迟达3秒,而手册第1.2节的表格早已给出答案。
6.1 内部通讯:POU间的零拷贝数据流
这是最高效路径,数据在内存中直接传递,无序列化开销。手册强调:“在程序、功能块和功能内部之间可以互相连接以形成一个网络”。典型应用是PID闭环:PID_ControllerFB的输出OUT直接连到MotorDriveFB的输入SPEED_REF。
// 在Program中连接(图形化编辑器中拖线,ST中等效为) MotorDrive.SPEED_REF := PID_Controller.OUT;注意:此连接要求两FB在同一资源(Resource)下。跨资源必须用全局变量或存取路径。
6.2 全局变量通讯:配置内的“公共消息板”
全局变量(Global Variable)是配置内POU共享数据的桥梁。手册规定:“全局变量在一个资源(或配置)内声明,它能被程序(配置)内的所有软件元件存取”。但关键约束是——全局变量必须在变量声明表(GVL)中集中管理,而非散落在各POU中。
某项目因在10个Program中各自声明GVL_SystemState,导致状态不一致。正确做法:
// 在GVL声明区(统一入口) TYPE GVL_System : STRUCT Mode : INT; // 0=Stop, 1=Auto, 2=Maint FaultCode : UINT; LastAlarmTime : DATE_AND_TIME; END_STRUCT END_TYPE // 全局实例 GVL_System : GVL_System;所有POU通过GVL_System.Mode访问,确保单一信源。
6.3 外部变量通讯:基于IEC 61131-5的标准化网络协议
手册Part 5定义了READ_VAR/WRITE_VAR等通讯FB家族,它们是跨设备通讯的官方API。与MODBUS等私有协议不同,这些FB的参数(如PATH、SIZE)是标准的,平台只需实现底层驱动。
典型HMI读取PLC变量:
// HMI侧(Codesys)调用标准FB READ_VAR( REQ := ReadReq, PATH := 'MainConfig.Res_Standard.GVL_Machine.Status', // 存取路径 ELEMENTARY_TYPE := 16#0004, // INT类型码 COUNT := 1, DATA => StatusValue );PATH字符串格式为<配置名>.<资源名>.<变量名>,这是手册强制的命名规范。若PLC侧配置名为LineCtrl,而HMI写成LineControl,则通讯失败。
6.4 存取路径通讯:穿透配置边界的终极武器
这是手册最强大的机制,允许从一台PLC直接读写另一台PLC的任意变量,无需中间代理。某电池厂AGV调度系统,用此技术让中央PLC直接修改各AGV PLC的GVL_Agv.TargetPoint变量。
实现分三步:
- 远程PLC启用存取服务:在Codesys中勾选“Enable Access Server”;
- 声明远程变量路径:
'AGV1.MainConfig.Res_Motion.GVL_Agv.TargetPoint'; - 用标准FB读写:
// 中央PLC写入AGV1目标点 WRITE_VAR( REQ := WriteReq, PATH := 'AGV1.MainConfig.Res_Motion.GVL_Agv.TargetPoint', ELEMENTARY_TYPE := 16#0004, COUNT := 1, DATA := NewTarget );提示:手册要求
PATH中设备名(AGV1)必须与网络中设备的实际IP或DNS名匹配,且防火墙需放行IEC 61131-5默认端口(如Codesys用8000)。
从那以后我每次设计新系统,都会先花2小时画一张“通讯路径拓扑图”:标出哪些数据走内部通讯(POU间)、哪些走全局变量(同配置)、哪些必须用存取路径(跨PLC)。这张图会贴在项目Wiki首页,所有工程师提交代码前必须对照——因为手册里那句“四种通讯模型使得不但在IEC编程系统内部的通讯灵活、便捷,而且还有效地支持了...未来对网络、现场总线、远程通讯等新技术发展的要求”,不是愿景,而是你明天就要面对的现实。希望帮到你。
本文还有配套的精品资源,点击获取