1. 为什么还要聊PLC基本指令干了这么多年自动化我越来越觉得PLC基本指令这东西就像学写字时的横竖撇捺——你后面写多漂亮的文章都得靠这些笔画撑着。很多人一上来就想搞PID、搞运动控制、搞总线通讯结果连个自锁电路都写得磕磕绊绊程序跑起来不是抖就是飞。我见过太多现场调试时抓耳挠腮的兄弟最后问题就出在一个常闭触点用错了或者定时器时间基准没搞明白。这篇文章我想把PLC基本指令这件事彻底讲透。不是照本宣科念手册而是把我这些年踩过的坑、总结出来的门道用最直白的话说清楚。不管你是刚入行的电气小白还是干了几年但总觉得基础不扎实的老手看完都能有收获。我会从指令的分类逻辑讲起然后逐个拆解最常用的那些指令配上可以直接抄的代码示例最后再聊聊现场调试时那些手册上不会写的经验。先说一下这篇文章适合谁看。如果你正在学PLC编程或者工作中需要维护、改造一些小型自动化设备那这篇就是写给你的。我会尽量避开那些晦涩的术语堆砌用生活里的例子来解释。比如自锁电路你就想象成家里的灯开关——按一下灯亮松手灯还亮这就是自锁。PLC里的指令说白了就是把继电器电路翻译成程序语言理解了继电器逻辑指令就理解了一大半。还有一点要提前说清楚不同品牌的PLC指令名字可能不太一样比如三菱叫LD、OUT西门子叫A、但底层逻辑是相通的。我会以最通用的IEC标准指令体系为主结合常见品牌的写法来对比说明。你学会了核心逻辑换任何品牌都能快速上手。2. 基本指令的分类逻辑与核心思路2.1 从继电器电路到程序指令的思维转换很多人学PLC卡壳根本原因是没有完成从“硬件接线”到“软件逻辑”的思维转换。以前用继电器控制你得考虑触点怎么接、线怎么走、继电器线圈怎么并。现在用PLC这些物理连接全部变成了程序里的“软触点”和“软线圈”。我打个比方。继电器电路里一个按钮按下去电流从火线经过按钮触点流到继电器线圈线圈得电吸合带动常开触点闭合。这个过程在PLC里就变成了输入端子检测到按钮信号程序里对应的输入继电器比如X0或I0.0状态变为1然后程序扫描到这个状态执行逻辑运算最后把结果写给输出继电器比如Y0或Q0.0输出端子驱动外部负载。关键区别在于继电器电路是“并行”工作的所有电路同时通电而PLC程序是“串行”扫描的CPU一个周期一个周期地从头到尾执行。这个扫描机制决定了PLC程序里会有一些继电器电路里不存在的现象比如“扫描周期导致的响应延迟”、“双线圈问题”等等。理解了这一点你才能明白为什么有些逻辑在继电器电路里没问题搬到PLC里就出毛病。2.2 基本指令的三大类别我把PLC基本指令分成三大类这样你学起来会更有条理。第一类是触点指令包括常开触点LD、常闭触点LDI、上升沿触点LDP、下降沿触点LDF等。这些指令负责从输入信号或者内部变量中“读取”状态相当于继电器电路里的各种触点。触点指令的特点是它们不改变信号状态只是把当前状态取出来参与逻辑运算。第二类是连接指令包括串联AND、并联OR、串联块ANB、并联块ORB等。这些指令负责把一个个触点连接起来形成完整的逻辑关系。串联就是“与”逻辑所有条件都满足才通并联就是“或”逻辑任意一个条件满足就通。复杂逻辑就是这两种关系的嵌套组合。第三类是输出指令包括线圈输出OUT、置位SET、复位RST、上升沿输出PLS、下降沿输出PLF等。这些指令负责把逻辑运算的结果“写”到某个变量或者输出端子上。输出指令决定了程序最终要干什么。这三类指令的关系就像盖房子触点指令是砖块连接指令是水泥输出指令是最后封顶。你先把砖块摆对位置再用水泥砌起来最后封顶房子就盖好了。2.3 为什么梯形图是最直观的编程方式PLC编程有好几种语言梯形图、指令表、功能块图、结构化文本。但我一直推荐新手从梯形图入手原因很简单——梯形图和继电器电路图长得几乎一样你不需要在脑子里做太多翻译。梯形图左边是母线相当于继电器电路的火线右边是输出相当于零线。程序从左到右、从上到下执行。触点画在横线上线圈画在最右边。这种视觉化的表达方式让你一眼就能看出逻辑关系调试的时候也容易定位问题。当然指令表也有它的优势比如输入快、程序紧凑。我个人的习惯是设计阶段用梯形图因为直观优化阶段可能会转成指令表因为效率高。但对于基本指令的学习来说梯形图绝对是最好的切入点。3. 触点指令与连接指令的深度拆解3.1 常开与常闭最基础也最容易出错常开触点LDLoad和常闭触点LDILoad Inverse是所有程序的起点。常开触点的逻辑是信号为1时导通为0时断开。常闭触点反过来信号为0时导通为1时断开。听起来简单但现场出问题最多的就是这两个。我遇到过好几次设备该动的时候不动查了半天发现是常闭触点用成了常开。为什么会犯这种错因为你在写程序的时候脑子里想的是“按钮按下设备启动”但实际接线可能是“按钮常闭按下断开”。这时候程序里就得用常闭触点来对应。注意程序里的常开/常闭和实际接线是两回事。按钮接常开还是常闭取决于安全逻辑。急停按钮必须接常闭这样断线也能触发停机。程序里对应的触点就要用常开因为正常状态下急停信号是1程序里常开触点导通急停按下信号变0常开触点断开设备停止。我总结了一个简单的对应关系实际接常开程序用常开实际接常闭程序用常闭。但安全相关的信号要反过来思考——正常状态信号是1触发状态信号是0程序里用常开触点这样断线也会导致信号变0触发安全动作。3.2 上升沿与下降沿捕捉瞬间变化上升沿触点LDPLoad Pulse和下降沿触点LDFLoad Falling是处理“瞬间动作”的关键。上升沿触点在信号从0变1的那个扫描周期导通一次之后即使信号保持为1触点也不再导通。下降沿反过来信号从1变0时导通一次。为什么需要沿触发举个例子。你想用一个按钮控制设备的启动和停止——按一下启动再按一下停止。如果用普通常开触点按钮按住不放程序每个扫描周期都会执行启动逻辑这显然不对。用上升沿触点按钮按下的瞬间只触发一次就能实现“按一下切换状态”的效果。沿触点的实现原理是PLC内部会存储信号的上一个扫描周期的状态然后和当前状态比较。如果上一个周期是0当前是1就是上升沿如果上一个周期是1当前是0就是下降沿。这个“上一个周期状态”的存储是PLC自动完成的你不需要手动干预。实操心得沿触点后面不能直接跟线圈输出因为沿触点只导通一个扫描周期线圈也只会得电一个周期。如果你需要保持输出必须用SET置位或者用自锁电路。我见过新手写LDP X0然后直接OUT Y0结果Y0只闪了一下还以为是PLC坏了。3.3 串联与并联逻辑关系的搭建串联用AND指令表示“与”逻辑。在梯形图里就是把触点竖着排一个接一个。所有触点都导通逻辑才通。比如“自动模式且启动按钮按下”就是两个条件串联。并联用OR指令表示“或”逻辑。在梯形图里就是把触点横着排上下分支。任意一个触点导通逻辑就通。比如“手动启动或自动启动”就是两个条件并联。复杂逻辑就是串联和并联的嵌套。比如“A或B且C或D”就是先并联再串联。在梯形图里你先画两个并联块然后把这两个块串联起来。指令表里用ORBOR Block和ANBAND Block来处理块操作。这里有个容易混淆的地方OR和ORB的区别。OR是单个触点并联ORB是并联块之间的串联。我刚开始学的时候经常搞混后来总结了一个口诀单个触点并联用OR块与块串联用ANB块与块并联用ORB。你多画几次梯形图就记住了。3.4 置位与复位状态保持的利器SET置位和RST复位是一对好搭档。SET让线圈保持得电状态即使触发条件消失了线圈依然得电直到遇到RST指令才复位。这相当于继电器电路里的自锁但比自锁更简洁。自锁电路需要把输出线圈的常开触点并联在启动按钮上接线多、占空间。用SET/RST就干净多了启动条件触发SET Y0停止条件触发RST Y0中间不需要任何自锁触点。程序看起来清爽调试也方便。但SET/RST也有坑。最大的问题是双线圈——如果你在程序的不同位置对同一个输出用了多次SET或OUTPLC会以最后一个扫描到的结果为准。这会导致一些莫名其妙的故障。我的建议是一个输出变量只在一个地方用SET/RST或者OUT不要分散在多处。注意SET/RST和OUT不能混用。如果你先用OUT Y0后面又用SET Y0程序行为会变得不可预测。要么全用OUT配合自锁要么全用SET/RST别混着来。4. 定时器与计数器指令的实战应用4.1 定时器时间控制的基石定时器是PLC里使用频率最高的功能指令之一。它的逻辑很简单触发条件满足时开始计时计时到达设定值后输出触点动作。但就是这么一个简单的指令现场用错的概率高得惊人。定时器有三个关键参数触发条件、时间设定值、时间基准。触发条件就是什么时候开始计时时间设定值就是计多久时间基准就是每个单位代表多少时间常见的有1ms、10ms、100ms。不同品牌的时间基准设置方式不一样。三菱的定时器T0到T199是100ms基准T200到T245是10ms基准你在用的时候要选对编号。西门子的定时器TON需要指定PT预设时间和PT的数据类型时间基准是自动的。不管哪种核心逻辑都一样实际延时 设定值 × 时间基准。举个例子。你要延时5秒。如果用100ms基准的定时器设定值就是50如果用10ms基准的定时器设定值就是500。设定值写错了延时时间就差十倍。我见过一个哥们儿调一个延时启动设了100结果等了10秒才动查了半天才发现是基准搞错了。定时器还有通电延时和断电延时的区别。通电延时TON是触发条件满足后开始计时计时到了输出动作断电延时TOF是触发条件断开后开始计时计时到了输出复位。大部分场景用通电延时就够了但有些特殊逻辑需要断电延时比如风机停机后继续吹一会儿。4.2 计数器计数的艺术计数器CTU加计数、CTD减计数、CTUD加减计数用来统计脉冲次数。每个计数器需要三个参数计数脉冲输入、复位输入、设定值。计数脉冲每来一个上升沿当前值加1或减1复位输入触发时当前值清零当前值达到设定值时计数器输出触点动作。计数器的典型应用是产量统计、位置控制、循环次数控制。比如一个包装机每包一袋产品光电传感器给一个脉冲计数器加1计到10袋就自动换箱。逻辑很简单但有几个细节要注意。第一计数脉冲必须是沿信号。如果你用普通触点接计数输入PLC每个扫描周期都会检测到信号为1计数器会疯狂累加。必须用上升沿触点LDP或者计数器内部自带的沿检测功能。第二复位信号的优先级。大部分计数器复位信号的优先级高于计数脉冲。也就是说如果复位和计数同时触发计数器会复位而不是计数。这个特性可以用来做清零保护。第三计数器的当前值可以读取。你可以用比较指令判断当前值是否达到某个数值实现更灵活的控制。比如计到5的时候输出一个信号计到10的时候输出另一个信号。4.3 定时器与计数器的组合应用单独用定时器或计数器能解决的问题有限真正强大的地方在于组合使用。我举一个实际案例一个设备需要运行2小时后自动停机停机10分钟后再自动启动循环往复。这个逻辑用两个定时器就能实现。第一个定时器T0计时2小时设定值72000100ms基准计时到了触发停机同时启动第二个定时器T1计时10分钟设定值6000。T1计时到了复位T0同时复位自己设备重新启动。两个定时器互相触发、互相复位形成一个循环。再复杂一点加上计数器统计循环次数。每完成一次“运行-停机”循环计数器加1计到5次就彻底停止不再循环。这就是定时器和计数器的经典组合。实操心得定时器和计数器的编号不要重复使用。有些PLC的定时器和计数器共用编号空间你用了T0做定时器就不能再用T0做计数器。编程前先规划好编号分配避免冲突。5. 数据传送与比较指令的进阶用法5.1 传送指令数据的搬运工传送指令MOVMove把源操作数的值复制到目标操作数。源可以是常数、寄存器、输入输出状态目标通常是数据寄存器或者输出寄存器。MOV指令不改变源操作数的值只是把值复制一份给目标。传送指令看起来简单但它是很多高级功能的基础。比如你要根据不同的配方参数控制设备就可以用MOV把配方数据传送到实际的控制寄存器。再比如你要把计数器的当前值显示在触摸屏上也需要用MOV把计数器的值传送到显示寄存器。传送指令有一个重要的特性数据类型匹配。16位数据传送到16位寄存器32位数据传送到32位寄存器不能混。如果你把32位数据传送到16位寄存器PLC会报错或者只传送低16位结果完全不对。我刚开始用的时候经常犯这个错后来养成了一个习惯写MOV之前先确认两边数据类型的位宽。5.2 比较指令逻辑判断的利器比较指令包括,,,,,用来判断两个数值的大小关系。比较指令的输出是一个触点条件成立时触点导通不成立时断开。你可以把比较触点当作普通触点来用串联、并联都可以。比较指令的典型应用是位置控制。比如一个伺服电机需要走到指定位置停止你可以用比较指令判断当前位置寄存器的值是否大于等于目标位置条件成立就触发停止。再比如温度控制当前温度低于设定值就加热高于设定值就停止加热用比较指令轻松实现。比较指令和传送指令经常配合使用。比如一个多段速控制系统根据不同的速度档位用比较指令判断当前档位然后用传送指令把对应的速度值写入频率寄存器。这种“判断-赋值”的模式在自动化程序里非常常见。5.3 数据运算指令加减乘除的妙用加减乘除指令ADD、SUB、MUL、DIV用来对数据进行算术运算。这些指令在位置控制、张力控制、配方计算等场景里用得很多。举个例子。一个卷绕设备需要根据卷径的变化调整张力。卷径随着卷绕的进行不断增大你可以用编码器计数得到卷绕圈数然后用乘法指令计算当前卷径再用除法指令计算对应的张力设定值。整个过程就是几个运算指令的组合。运算指令要注意溢出问题。16位数据的范围是-32768到32767两个大数相乘很容易溢出。如果预计结果会超过这个范围就要用32位运算指令DMUL、DDIV等。溢出会导致结果完全错误而且PLC不一定报错排查起来很麻烦。注意运算指令的结果要存放到数据寄存器里不要直接输出到物理输出端子。物理输出端子只有0和1两种状态运算结果写进去没有意义。6. 程序流程控制指令的合理运用6.1 跳转指令程序的岔路口跳转指令CJConditional Jump根据条件决定是否跳过一段程序。条件成立时程序跳转到指定标号处继续执行条件不成立时顺序执行。跳转指令可以用来实现模式切换——手动模式下跳过自动程序自动模式下跳过手动程序。跳转指令用好了能提高程序效率用不好就是灾难。最大的坑是跳转导致输出状态保持。如果你跳过了某个输出线圈所在的程序段那个输出会保持跳转前的状态不会自动复位。比如自动程序里有个电机输出你跳到手动模式时跳过了这段程序电机可能还在转。所以跳转前一定要把相关输出复位或者用SET/RST明确控制。我的建议是能用条件判断解决的尽量不用跳转。跳转指令虽然省扫描时间但程序可读性差调试困难。现在的PLC扫描速度都很快省那点时间意义不大程序清晰可靠才是第一位的。6.2 子程序代码的模块化子程序CALL和SRET用来把程序分成多个模块。主程序里用CALL调用子程序子程序执行完用SRET返回主程序。子程序的好处是代码复用——同一个功能写一次多处调用。子程序特别适合处理那些“按需执行”的功能。比如设备有多种工作模式每种模式的逻辑写成一个子程序主程序根据模式选择调用哪个子程序。这样主程序很简洁每个子程序各司其职维护起来方便。子程序里要注意局部变量和全局变量的区别。有些PLC的子程序支持局部变量只在子程序内部有效全局变量在整个程序里都有效。用局部变量可以避免变量名冲突但要注意子程序调用时的参数传递。6.3 中断程序紧急事件的快速响应中断程序INT用来处理那些需要立即响应的紧急事件。正常程序是顺序扫描的一个扫描周期可能几毫秒到几十毫秒。如果某个信号来了需要马上处理等扫描周期结束就太晚了。中断程序可以打断正常扫描立即执行。中断的典型应用是高速计数、急停处理、位置捕捉。比如一个高速旋转的设备每转一圈给一个脉冲你需要精确捕捉脉冲到来的时刻用中断就能做到微秒级的响应。中断程序要尽量短小精悍因为中断执行期间正常程序是暂停的。如果中断程序太长会影响正常程序的扫描周期导致其他功能响应变慢。我的原则是中断程序里只做最紧急的事情比如置位一个标志位具体的处理逻辑放到主程序里根据标志位执行。7. 常见问题与排查技巧实录7.1 程序能下载但设备不动作这是现场最常见的问题。程序下载进去了PLC运行指示灯也亮着但设备就是不动。排查思路要按顺序来别东一榔头西一棒子。先查输入信号。PLC上对应的输入指示灯亮不亮不亮的话用万用表量一下输入端子有没有电压。有电压但指示灯不亮可能是输入端子坏了或者公共端接错了。没电压就查外部按钮、传感器、线路。再查程序逻辑。输入指示灯亮了但程序里对应的触点没导通用编程软件监控程序看触点的实时状态。如果输入为1但触点不导通说明程序里用的是常闭触点逻辑反了。如果触点导通了但输出线圈不得电说明前面的串联条件没满足逐个检查每个触点。最后查输出信号。输出线圈得电了但PLC输出指示灯不亮可能是输出端子坏了或者输出类型不对继电器输出和晶体管输出的负载能力不一样。指示灯亮了但设备不动查外部接触器、继电器、线路。实操心得我习惯在程序里给每个输出加一个“调试模式”标志位。调试模式下不管逻辑条件是否满足强制输出动作用来快速判断是程序问题还是硬件问题。这个方法能省很多排查时间。7.2 定时器时间不准定时器时间不准十有八九是时间基准搞错了。先确认你用的定时器编号对应的时间基准是多少。三菱的T0-T199是100msT200-T245是10msT246-T255是1ms。西门子的TON时间基准是1ms但PT的数据类型决定了实际范围。还有一个原因是扫描周期的影响。定时器是在每个扫描周期更新当前值的如果扫描周期波动很大定时精度就会受影响。对于精度要求高的场合要用硬件定时器或者高速计数器不要用普通定时器。另外注意有些PLC的定时器在触发条件断开后会保持当前值再次触发时从保持值继续计时。如果你需要每次触发都从零开始要在触发条件断开时复位定时器。7.3 计数器不计数或计数不准计数器不计数先检查计数脉冲是不是沿信号。用普通触点接计数输入计数器每个扫描周期都会累加看起来就像“不计数”或者“计数飞快”。必须用上升沿。计数不准可能是脉冲频率超过了PLC的响应速度。普通输入端的响应频率一般在几十赫兹到几百赫兹高速脉冲要用高速计数模块或者PLC自带的高速计数端口。用普通计数器接高速脉冲会丢脉冲。还有可能是复位信号干扰。如果复位信号和计数脉冲同时到来计数器会复位而不是计数。检查复位信号的触发条件确保它不会在计数过程中误触发。7.4 常见问题速查表现象可能原因排查方法程序下载后设备不动作输入信号未到位查输入指示灯和外部线路输出线圈得电但设备不动输出端子故障或负载问题查输出指示灯和外部接触器定时器时间偏差大时间基准设置错误确认定时器编号对应的基准计数器不计数计数脉冲不是沿信号改用上升沿触点计数器计数不准脉冲频率超过响应速度改用高速计数端口沿触点输出只闪一下沿触点只导通一个周期改用SET置位或自锁双线圈导致输出异常同一输出多处赋值合并到一个位置赋值跳转后输出保持跳转跳过了输出复位跳转前手动复位输出8. 从基本指令到复杂程序的进阶路径8.1 基本指令的组合威力很多人觉得基本指令太简单没什么好学的急着去搞高级功能。但我在现场看到的实际情况是能把基本指令用出花来的人才是真正的高手。一个复杂的自动化程序拆开来看无非就是触点、定时器、计数器、比较、传送这些基本元素的组合。我举个例子。一个多工位转盘控制系统需要控制转盘旋转、工位定位、气缸动作、产品检测、数据记录。听起来很复杂但拆解一下转盘旋转用定时器控制电机运行时间工位定位用计数器统计脉冲数气缸动作用SET/RST控制电磁阀产品检测用输入触点和计数器数据记录用MOV把数据存到寄存器。全是基本指令没有一行高级代码。所以我的建议是先把基本指令练到条件反射的程度。看到一个控制需求脑子里立刻能反应出用哪些指令、怎么组合。这个能力比会写几行高级代码重要得多。8.2 程序结构的优化思路基本指令用熟了之后就要考虑程序结构的问题。一个好的程序结构应该是主程序简洁明了功能模块清晰独立变量命名规范统一。主程序里只放最顶层的逻辑——模式选择、子程序调用、急停处理。具体的功能逻辑放到子程序里。这样主程序一眼就能看明白设备的工作流程调试的时候也容易定位问题。变量命名要有一套规则。我的习惯是输入用I开头输出用Y或Q开头中间变量用M开头定时器用T开头计数器用C开头数据寄存器用D开头。后面跟上功能描述比如I_StartBtn、Y_MotorRun、T_Delay5s。这样看程序的时候不用查注释就知道变量是干什么的。8.3 从梯形图到结构化文本的过渡梯形图适合逻辑控制但处理复杂运算和数据处理时就不太方便了。这时候可以考虑用结构化文本ST。ST像写代码一样写逻辑适合处理数组、循环、条件判断等复杂操作。但我不建议新手一上来就学ST。梯形图能帮你建立清晰的逻辑思维理解PLC的扫描机制和信号流。等你把梯形图玩透了再学ST就是水到渠成的事。反过来如果直接学ST很容易写出逻辑混乱、难以调试的程序。我个人的做法是逻辑控制用梯形图数据处理用ST两者混用。大部分PLC都支持多种语言混编你可以在梯形图程序里调用ST写的功能块各取所长。8.4 持续精进的学习方法PLC编程这件事光看书看教程是不够的必须动手。我的建议是找一个实际的小项目练手。比如给自己的工作室做一个自动照明控制或者给家里的鱼缸做一个自动喂食器。项目不用大但要有完整的输入、输出、逻辑、调试过程。练手的时候刻意用不同的指令实现同一个功能。比如延时启动你可以用定时器实现也可以用计数器配合时钟脉冲实现。对比不同方案的优缺点理解每种指令的适用场景。还有一点很重要多看别人写的程序。每个工程师都有自己的编程习惯和技巧看别人的程序能学到很多书上没有的东西。我刚开始工作的时候一有机会就翻老师傅的程序看看不懂的就问进步很快。实操心得我建议你建一个自己的“指令库”。把常用的功能块——比如电机启停控制、报警处理、模拟量滤波——写成标准的子程序或功能块以后做新项目直接调用。这样既能保证代码质量又能提高效率。我现在的指令库积累了上百个功能块做新项目时至少能省一半的编程时间。最后再分享一个小技巧。调试程序的时候善用强制功能和监控功能。强制功能可以强制某个变量为0或1用来模拟输入信号或者跳过某些条件。监控功能可以实时查看变量的当前值比用万用表量快多了。但要注意强制功能只在调试时用调试完一定要取消强制否则程序行为会不正常。我见过有人调试完忘了取消强制设备运行了一个月才发现问题查了半天才找到原因。