三菱PLC的编程指令这个话题,隔三差五就有人在群里问一次。刚入行时我也抱着手册从第一页翻到最后一页,记了一堆指令名字,真到写程序的时候反而不知道用哪条。后来才慢慢想明白:指令多不是问题,问题是没理清它们背后的分类逻辑和适用场景。这篇内容就按照我实际学习和使用的路径来拆一拆,哪些指令必须熟,哪些可以现查,哪些很容易踩坑,尽量讲得实在一点。
1. 三菱指令体系为什么让新手觉得"又多又乱"?——先拆框架再记指令
1.1 三大分层:基础指令、应用指令与特殊指令
三菱PLC的指令大致可以分成三个层级。第一层是基础指令,也叫基本指令,数量不多,FX系列里也就二十几条,主要处理触点、线圈、置位复位、跳转这类最底层的逻辑。这一层是必须烂熟于心的,因为它直接对应梯形图里的每一个图形元素,你画出来的每一个常开触点、每一个输出线圈,背后都是一条基础指令。
第二层是应用指令,有些资料里也叫功能指令,数量就很庞大了。FX3U系列的应用指令有二三百条,从数据传送、比较、四则运算,到循环移位、数据处理、高速处理、通信控制,全都在这一层。新手看到这一堆就头大,其实完全没必要。应用指令的特点是"分类清晰、按需使用",你只需要先把最常用的那十几条练熟,比如MOV、CMP、ADD、INC这一类的,后面碰到具体功能再查手册不迟。
第三层是特殊指令和特殊功能模块的相关指令。比如PID控制指令、定位控制指令、通信指令等等,这些通常和具体硬件绑定,用什么模块才涉及什么指令。一般做常规开关量控制的项目,第三层基本碰不到。
我见过一些初学者,一上来就想把应用指令全部背熟,结果背了后面忘了前面,写出来的程序反而逻辑混乱。正确的做法是先打牢第一层,再把第二层里最常用的十几条用熟,剩下的交给手册——三菱的编程手册写得已经比较清楚了,按功能分类索引,查起来非常方便。
1.2 FX/Q/L系列之间的指令传承与差异
还有一个让新手困惑的点是:网上搜三菱PLC指令,出来的结果有的讲FX系列,有的讲Q系列,有的讲L系列,指令对不上号。这三个系列虽然同属三菱,但指令体系有差异。
FX系列是最常见的,小型PLC代表,教学和中小型设备上用得最多。FX3U的指令已经相当完整,基本上FX3U学会之后,看Q系列的指令不会太陌生。Q系列是中大型PLC,指令更丰富,特别是运动控制、多CPU、过程控制这些高端功能,指令数量明显更多。L系列可以看成Q系列的简化版,指令和Q系列接近,但定位在中小型。
从学习角度讲,从FX系列入手是最合理的路径。原因有两个:一是资料多,教材、视频、案例基本都是拿FX系列讲的;二是FX系列的指令结构足够典型,基础指令和应用指令的框架和Q系列是相通的。你掌握了FX3U的MOV、CMP这些指令的用法,换到Q系列,指令名称基本不变,变的只是操作数范围和软元件编号规则。
所以我的建议很直接:别管网上那些"三菱PLC全套指令"的资料,先把FX3U或者FX3G的手册啃透,就够了。
2. 基础指令的工程记忆法:LD、OUT、AND、OR到底在说什么
2.1 从按钮启动电机说起:触点类指令的梯形图直觉
基础指令里,最先碰到的就是触点类。LD是取常开触点,LDI是取常闭触点,AND是串联常开,ANI是串联常闭,OR是并联常开,ORI是并联常闭。
光看英文缩写很抽象,我一般建议直接按梯形图来理解。梯形图的左母线相当于电源正极,右母线方向相当于电源负极,中间就是一条一条的"电路"。LD就是"在这条电路的起点放一个常开开关",AND就是在已有的电路上"再串一个开关",OR就是在一条已有的并联支路上"再并一条支路"。这样一想,指令的用法其实和你画电气原理图时怎么放继电器触点是一模一样的。
举个最经典的电机启保停电路。启动按钮X0接常开,停止按钮X1接常闭,输出线圈Y0。梯形图的写法是:LD X0,再OR Y0(形成自锁),再ANI X1,最后OUT Y0。从思路上讲,启动按钮按下,X0导通,Y0有输出;松开启动按钮后,Y0的常开触点已经闭合,把自己这一路继续维持住,这就是自锁;停止按钮接的是常闭触点,按下去之后这一路断开,Y0失电。
这里有个细节值得多说一句:停止按钮为什么用常闭触点而不是常开?这是安全习惯。如果停止按钮用常开触点,一旦按钮的连线断了或者触点坏了,你按停止按钮根本没反应,电机停不下来,这是严重的事故隐患。用常闭触点的话,线路断了、触点坏了,电路自然断开,设备就停了,这叫"失电优先"。这个习惯在PLC程序里也一样,急停、停止、安全门这些信号一律用常闭输入配合常开指令,或者用常开输入配合取反逻辑,目的是保证故障时设备处于安全状态。
2.2 输出类与置位复位类指令的配合使用
输出指令除了最基础的OUT,还有一个非常重要的组合是SET和RST。SET是置位,RST是复位。它们的区别在于:OUT线圈是"跟随输入状态刷新的",输入通了它就有输出,输入断了它就没输出;但SET不一样,一旦执行过一次SET Y0,Y0会一直保持输出,直到程序里执行RST Y0,或者PLC断电(非保持型软元件)才会解除。
这个特性在做一些"动作完成后保持状态"的场景里非常方便。比如一个气缸伸出去顶住工件,到位之后不需要一直给电,用一个SET保持住就行,等加工完再 RST掉。这样写出来的梯形图,比用一堆自锁互锁逻辑要清爽得多。
但这里有一个特别重要的坑:同一软元件用了SET之后,就别在同一段程序里用OUT去控制它。这不是说语法报错,而是逻辑上会产生双线圈输出,程序扫描时后执行的会覆盖先执行的,最后Y0的实际状态完全取决于扫描顺序,这种程序调试起来非常痛苦。我见过有人在一个程序里用OUT Y0做了一个指示灯,又在另一个子程序里用SET Y0去点亮它,结果设备动作一切正常,就是指示灯偶尔不亮,查了半天。
2.3 块指令ANB/ORB:为什么连老手也偶尔会漏掉组合逻辑
接触点串联并联之后,就轮到两个稍微绕一点的指令:ANB和ORB。
ANB是把两个"块"串联起来。什么叫块?就是一段已经组合好的触点网络。比如左边一路是X0和X1并联,右边一路是X2和X3并联,现在要把这两块串在一起,按逻辑关系就是(X0 OR X1) AND (X2 OR X3)。直接写指令的时候,你没法用一条AND去串一整块,得用ANB。
ORB相反,是把两个块并联起来。比如(X0 AND X1) OR (X2 AND X3),这里两个块之间用ORB连接。
这个知识点难度不大,难的是新手写程序时常常在脑子里乱了套。我自己的经验是:遇到这种块组合,先在纸上把逻辑表达式写出来,再用"块"的概念去套。如果逻辑表达式是(A AND B) OR (C AND D),那就是两个串联块做ORB;如果是(A OR B) AND (C OR D),那就是两个并联块做ANB。
实际调试时,ORB和ANB出问题多半是"块"的划分不对,比如少写了一条ORB导致并联关系变成了串联。这种问题在仿真软件里能直接看出来,多练几次就有感觉了。
3. 定时器与计数器:时间控制和计数场景的底层逻辑
3.1 定时器编号背后的时间基准秘密
三菱FX系列的定时器编号不是随便用的,每一个编号都对应固定的时间基准,这个设计让不少从其他品牌转过来的人不太适应。
以FX3U为例,T0到T199是100ms定时器,定时范围0.1秒到3276.7秒;T200到T245是10ms定时器,范围0.01秒到327.67秒;T246到T249是1ms累积型;T250到T255是100ms累积型;FX3U还扩展了T256到T511,是1ms定时器。有累积两个字,意思是定时过程中如果输入断开,时间会保持住,重新接通后接着累计,而不是从零开始。
先记住一个关键点:定时器编号决定了最小计时单位,不是你在程序里设置K100就一定是1秒。T0是100ms定时器,K100就是0.1秒乘以100等于10秒;但同样的K100放到T200上,就是0.01乘以100等于1秒。初学者在这里犯错率极高,写了个延时启动结果设备提前动作或者迟迟不动作,都是因为没注意编号对应的基准时间。
定时器的K值范围也要留个心。K后面跟的是设定值,对16位定时器来说范围是1到32767。如果你算出来需要延时很长时间,比如5小时,直接死磕一个大K值是不现实的,更合理的做法是用定时器接力,或者用计数器配合定时器做累加计时。
3.2 计数器不只是数数:掉电保持与高速计数
计数器在三菱FX系列里也分几类。C0到C99是16位增计数器,其中C0到C15默认为普通计数,断电清零;C16到C199默认为锁存计数,断电后靠电池保持当前值。C200到C255是32位增/减计数器,可以双向计数。
计数器最常见的场景是计数并触发动作,比如传送带上每经过一个工件,传感器给一个脉冲,计数器加1,计到设定值就启动包装机构。这种场景用普通计数器就够了。
但如果你要数的脉冲频率很高,比如编码器输出每秒几千个脉冲,那普通计数器就无能为力了,这时候要用高速计数器。FX3U的高速计数器编号是C235到C255,它们和普通计数器最大的区别是:输入端子是固定的,不能随便改。比如C235默认对应X0端子,你要数编码器的A相脉冲,就必须接到X0上。这个限制在实际接线时特别容易出错,我身边就有同事在现场改了半天程序,最后发现是脉冲信号接错了端子,高速计数器根本没工作。
3.3 一个星三角切换案例读懂T和C的组合用法
把定时器和计数器放在一起看,最能体现它们价值的是典型的电机星三角降压启动控制。
启动瞬间电机先接成星形,此时每相绕组电压是线电压的1/根号3,启动电流小;延时几秒后切换到三角形接法,电机全压运行。这个"延时几秒"就是定时器的活。
程序逻辑大致是:按下启动按钮,主接触器吸合,星形接触器吸合,同时启动一个延时定时器T0,设为K50,如果T0是100ms基准,那K50就是5秒。5秒到后,先断开星形接触器,再吸合三角形接触器。这里要注意的是,星形和三角形接触器之间要有互锁,否则切换瞬间可能造成相间短路。定时器的常开触点在这里承担了"时间到了"的触发信号。
计数器在这个场景里也能配合使用,比如记录这台电机一天启动过多少次,用C10做个计数,到了设定次数就驱动一个报警输出,提醒维护人员检查接触器触点。定时器管"延时多长",计数器管"发生多少次",两者结合起来,很多时间类、次数类的控制需求就都有了着落。
4. 应用指令的正确打开方式:从MOV到比较指令,先掌握这几种
4.1 MOV指令为什么是"最像人话"的一条
应用指令里,我第一个推荐先吃透的是MOV(传送)指令。它的作用是把一个数据放到另一个地方,就好比你把一杯水倒进另一个杯子,源杯子里的水还在,目标杯子里有了同样的水。
在梯形图里,MOV的写法通常是MOV K100 D0,意思就是把常数100传送到数据寄存器D0里。也可以MOV D10 D20,把D10的值复制到D20。这个指令几乎没有理解门槛,但它是后面一切数据处理的基础——你要做运算,首先得把数据放到指定的寄存器里;你要给触摸屏显示一个值,也得先把值传到一个固定地址;你要做配方切换,无非就是把不同的常数MOV到对应的寄存器。
实际使用中有个细节需要注意:MOV是16位指令,它操作的是16位的数据。如果操作数是个32位数据,得用DMOV。比如从高速计数器的当前值寄存器读出数值,计数范围超过32767了,那普通MOV就装不下了,必须用DMOV。新手最容易在这里出问题——计数器显示的数不对,或者出现负数,大概率就是用了16位MOV去传32位数据。
4.2 比较指令CMP/ZCP:把"判断"写进梯形图
如果说MOV是"倒水",那比较指令CMP就是"称重"。CMP指令比较两个数的大小关系,然后给出三个标志结果:大于、等于、小于。
CMP D0 K100 这种写法,是把D0里的数值和100比较,比较结果不是直接输出到一个线圈上,而是通过三个标志位体现的。在FX3U里,比较结果会影响到M0、M1、M2(当D0作为操作数的首地址时,M0是小于标志,M1是等于标志,M2是大于标志,具体要看手册确认)。程序里就变成:M0接通表示D0小于100,M1接通表示D0等于100,M2接通表示D0大于100。
这种"比较出三态"的特性,在温度控制、压力控制这些场景里非常好用。比如某加热炉温度传感器读入D0,设定温度100度,CMP D0 K100之后,小于100就开加热器,等于100就保持,大于100就报警。用梯形图写出来,逻辑非常直白。
还有一个常用的变体是ZCP(区间比较),一次比较一个数是否落在某个区间里。比如ZCP K50 K80 D0,判断D0是否在50到80之间。这类指令的好处是省掉了多个CMP的堆叠,程序更干净。
4.3 加减运算与自加自减:数据处理的最小闭环
数据处理最终要落到运算上,加法ADD、减法SUB,以及自加INC、自减DEC,这四条指令在工程中出现的频率很高。
ADD D0 K1 D0,字面意思是D0加1存回D0,这在实际使用中其实就是"自加1",可以直接用INC D0代替。两者效果一样,但INC不需要给第二个操作数,写起来更简洁。减法同理,DEC是自减1。
这些指令最常见的应用是计数器累加、排产计数、批次统计。比如一个包装线上每完成一个包装,程序就把D100加1,产量数据通过触摸屏实时显示。传统的做法是用计数器C去计,但计数器数量有限,而且很多场景需要把计数值参与后续运算,这时候用D寄存器加INC指令就灵活得多。
运算指令还有个基本功是理解进制:常数K是十进制,常数H是十六进制。X输入端子的编号实际上是八进制,这一点也容易让人迷惑,比如X7后面是X10而不是X8或者X9。这个细节在写程序时不太影响,但涉及位元件组合或者通信地址时就会冒出来,早点知道没坏处。
5. 程序流程控制:当梯形图不只是从上到下扫描
5.1 CJ跳转如何实现手动/自动模式的切换
默认情况下PLC程序是从上到下逐行扫描执行的,但有了流程控制指令之后,你就可以打破这个顺序。CJ(条件跳转)指令的作用是:当条件满足时,跳过指定的一段程序,直接跳到标签处继续执行。
CJ最常见的工程应用就是手动和自动模式的切换。设备在手动模式下,自动程序里那些气缸动作、伺服定位逻辑根本不需要扫描,跳过去就行。这不仅是省扫描时间的问题,更关键的是避免手动状态下自动程序误动作。比如自动程序里有一条"某个条件满足就夹紧气缸"的指令,如果手动模式下你正在调整工件,这个条件刚好满足,气缸突然夹紧,可能就出安全事故了。用CJ把自动程序跳过去,从根源上避免了这种意外。
跳转要有目标,目标就是一个标签,在梯形图里用P编号来表示,比如CJ P10,意思就是跳到P10所在的位置继续执行。写的时候要注意标签不能重复,而且跳转之后的程序段要保证逻辑闭环,别跳来跳去最后连END都找不到了。
5.2 子程序调用与中断:什么时候值得用
子程序的思想和单片机里的函数很像。把一段功能完整、参数固定的逻辑独立出来,用CALL指令调用,程序主体就干净很多。比如一套设备有好几个轴,每个轴的初始化逻辑类似,抽成一个子程序,不同轴传不同的软元件参数进去,比复制粘贴一大段梯形图优雅得多。
FX系列的子程序编号是P0到P62(具体看型号),通过CALL P0这样的方式调用。子程序内部可以有自己的逻辑,执行完用SRET返回主程序。
中断指令则更特殊,它要求在事件发生的瞬间立即响应,而不是等程序扫描到那一行。三菱FX3U支持输入中断、定时器中断和高速计数器中断。比如一个设备需要实时捕捉一个快速信号,普通扫描周期可能来不及,就可以用输入中断,信号一上来立即执行中断子程序。
我的建议是:中断指令先了解有什么样的场景需要用,不用急着吃透。大多数常规项目根本用不上中断,用上了反而因为时序问题调试困难。等真正碰到"普通扫描周期不够用"的工况时,再回头来研究它,效率高得多。
5.3 FOR/NEXT循环在批量数据处理中的应用
FOR和NEXT是配合使用的循环指令。FOR K10表示下面的程序段要循环执行10次,遇到NEXT结束一次循环。循环体和FOR之间的程序会被重复扫描执行。
最典型的应用是批量初始化数据。比如设备有20组配方参数存在D100到D139,设备启动时需要把这20组数据全部清零。没有循环的话,你想清零就得写20条MOV K0 D100、MOV K0 D101……又臭又长。用循环配合变址寄存器,几条指令就搞定了。
这里要提醒一点:FOR的循环次数如果设得太大会导致扫描周期激增,影响设备响应。尤其是循环体里还有复杂的运算指令时,几百次循环可能让整个PLC扫描周期翻好几倍,导致输出反应迟钝。我建议循环次数控制在几百以内,如果确实需要海量数据处理,不如考虑用带高速处理能力的特殊功能模块,别让PLC主循环背太重的负担。
6. 实操避坑记录:指令数量不重要,用对才重要
6.1 32位指令的D和D+1成对陷阱
三菱FX系列的32位指令有个很容易被忽视的设计:数据的存储是"成对"的。比如32位数据存放在D0和D1两个寄存器里,D0放低位,D1放高位。当你用DMOV把一个32位数值传入D0时,程序会自动占用D0和D1。
这个设计的坑在于:你如果在这段程序的另一个地方单独使用D1,比如MOV K0 D1,就把高位数据破坏了,整个32位数值就变了。我第一次用DMOV处理高速计数器的当前值时,就踩过这个雷,后来发现程序里有个地方为了复位某一位,单独摸了D1一下,计数器数值直接乱套了。
所以使用32位指令的规矩是:规划地址时,凡是32位数据,名字段地址旁边要预留出一个寄存器,并且不要在别的逻辑里单独碰它。标注地址分配表的时候,D0和D1要一起标注为"高速计数值当前值(32位)",提醒自己别拆开用。
6.2 掉电保持区域与普通区域的区别
三菱FX系列的软元件默认分为普通区和锁存区(电保持区)。断电后普通区的状态清零,锁存区的状态保持。这个默认设置在FX3U里是可以通过参数修改的,比如D0到D199默认普通,D200到D511默认锁存(具体型号有差异,以手册为准)。
这个特性有时候是优点,有时候是坑。比如你用D100记当前产量,觉得断电清零是天经地义的,但实际它被默认设置了锁存,断电重启后产量还在,或者反过来你以为能保持结果没保持。更麻烦的是,锁存区在PLC上电后不会自动初始化,如果写程序时忘了复位这些软元件,设备重启后的初始状态可能是上一次运行留下的"脏数据"。
我的习惯是:在程序开头专门写一段初始化逻辑,对锁存区里需要上电清零的软元件统一复位。这样即使断电保持了数据,下一次启动时程序也能进入一个确定的初始状态,不会带着上一次的残留值运行。
6.3 高速计数器的固定端子谜题
前文提过高速计数器的输入端子是固定的。C235对应X0,C236对应X1,C237对应X2,基本就是这个规律。如果你在程序里用C237去数一个接在X5上的脉冲,它是完全没反应的,因为它根本不读X5的电平变化。这个限制让很多人调试时一头雾水,觉得程序明明写了高速计数器,就是数不出来。
除了接线端子固定,还有一点是高速计数器的使用需要设置输入滤波时间。三菱PLC的普通输入端默认有滤波,会滤掉窄脉冲,但高速计数器要求在硬件配置里把对应端子的输入滤波时间调到最小,或者启用高速输入功能。如果忘记设置,高速脉冲可能被滤掉一部分,计数结果偏小,而且毫无规律。
这个坑的最佳规避方式是在项目设计阶段就规划好:哪些信号是高速脉冲,接到哪些端子上,然后把这些端子的滤波时间设置写进项目启动检查清单里,别等到现场调试才发现。
6.4 程序结尾的END:一个容易被忽略的硬性规则
前面聊了那么多指令,还有一个最基础但绝对不能忘的:程序最后一定要有END指令。
END表示主程序扫描到此结束。如果你写了子程序、中断程序这些,也得注意它们放在END之外,主程序碰上END就停下,子程序是靠CALL驱动的。程序没有END,在线监控时整个流程会很奇怪,PLC可能会持续扫描所有指令直到程序末尾,如果末尾刚好有输出指令,可能会导致意想不到的输出。
我碰到过一种情况是:某同事写了一段梯形图,没有END,程序也能下载运行,但触摸屏上的状态刷新就变得不稳定。后来检查发现是他把END漏了,整个程序的扫描边界都乱了。补上END之后一切恢复正常。这些细节单独拿出来看都是小事,但恰恰是这些小事,决定了设备调试顺畅还是加班加点找问题。
回头再看"三菱PLC有哪些编程指令"这个问题,其实答案很简单——基础指令二十几条,常用应用指令十几条,剩下的按需查手册。真正拉开差距的不是背了多少指令,而是拿到一个需求时能不能想到用哪一类指令、怎么组织程序的整体结构。我从一开始死记硬背指令清单,到后来按"框架、分类、场景"去理解指令,写程序和调程序的效率都上了一个台阶。下次你要是觉得指令太多记不住,不妨先停一停,想想自己手里的这个设备,到底需要哪几类功能,再去找对应的指令,这条路走起来会轻松很多。