
简介这份《欧姆龙ST编程中文手册》面向刚接触欧姆龙PLC结构化文本编程的工程师、自动化专业学生及设备调试人员旨在解决ST语言功能块使用、变量定义与编程规范不熟悉的问题。资源为单一PDF文档压缩包约2.26MB内容围绕CX-Programmer 6.1环境展开依次讲解功能块介绍与类型、功能块规格与限制、变量、将功能块定义转换为库文件、应用程序及版本升级信息并补充编程环境设置、基本语法、安全注意事项与应用注意事项目录层级清晰便于按章节检索。该手册已有7329人学习适合作为入门查阅与现场调试时的案头参考。读者可从中了解数字量/模拟量、计时器、计数器等常见功能块的组织方式掌握变量声明、赋值、条件与循环语句的写法并借助技术规格、实例规格和限制说明规避配置错误提升编程效率与程序可维护性。1. 手册定位先看你手里的 CPU 在不在支持清单里有人拿到编号 W447-CN5-02 的欧姆龙ST编程中文手册翻两页发现通篇在讲功能块、变量、实例以为拿错了书。这份文档的正身是 CX-Programmer 6.1 的功能块操作手册ST 只是它支持的两种算法描述语言之一另一条路是梯形图。它要解决的问题很具体把现场反复出现的逻辑——四点滤波、报警回差、阀位换算、工位互锁——打包成一个可复用、可反复实例化的块而不是每次复制几十行梯形图再改地址。适合手上跑着 CS1-H、CJ1-H、CJ1M、CP1H 这几类 CPU、又想把程序做成模块化结构的电气工程师如果你连 ST 的IF、FOR都没写过先补语法再来附录 B 只给规格不教入门。2. 功能块不是函数ST 在这套体系里到底占什么位置很多人第一次接触功能块会把它当 C 语言的函数理解写完之后发现调用两次、地址打架、内部变量互相污染这就是概念没对齐。这一章把三层结构拆开再说清 ST 在里面能干什么、不能干什么。2.1 定义、库文件、实例是三个不同的东西功能块定义是模板里面只有两样东西一份变量定义表输入、输出、输入输出、内部、外部一段用梯形图或 ST 写的算法。定义本身不占 PLC 的用户程序存储区也不产生任何运行数据。把定义打包导出得到的是一个库文件CX-Programmer 里以.cxf后缀保存这是唯一能在项目之间、工程师之间传递的单位。真正占用资源的是实例。你在梯形图里把功能块拖进回路给它起个名字比如FB_Filter_01这一刻才在内存里生成一份独立的内部变量副本。同一套滤波定义调四次就有四份Buf数组、四个写指针互不干扰。这跟传统子程序最大的差别在于子程序靠固定地址传参第二次调用必须换一套地址功能块靠实例名隔离第二次调用只要换个实例名。提示实例名在同一个任务内必须唯一跨任务重名在编译阶段就会报错不要指望下载时才发现。库文件的维护是这套机制里最容易被忽视的一环。现场调试时改了一版算法直接在主程序里改实例是可以的但下次别人从库里重新拖一个进来用的还是老版本。我一般会要求项目里留一份库文件的版本记录改完算法先更新库、再更新实例顺序反了就会出现同一个项目里两个实例行为不一致的玄学问题。2.2 ST 适合写什么梯形图适合写什么两种语言在同一个功能块里只能二选一定义的时候就要定下来。选型不是喜好问题是维护成本问题。梯形图适合互锁、时序、单点逻辑尤其是需要现场电工直接看懂的部分。ST 适合算术运算、循环、数组搬移、状态机、带多个分支条件的判断。举个具体例子把 12 路模拟量做限幅、标定、求平均梯形图要写几十个比较指令和加法指令改一个系数要翻三屏ST 里就是一个FOR循环加两行算式参数改在变量表里现场不用动程序。手册附录 B 给的 ST 规格覆盖了这些内容赋值、IF/ELSIF/ELSE、CASE、FOR、WHILE、REPEAT以及EXIT、RETURN这类流程控制。附录 A 给数据类型常用的有BOOL、INT、UINT、DINT、UDINT、REAL、WORD、DWORD还有对应的 BCD 类型。附录 C 单独讲外部变量这一块后面第 3 章会展开。下面这段是我常用的四点滑动平均用来演示 ST 在功能块里的典型写法(* 功能块4 点滑动平均滤波 *) (* 变量表登记 *) (* Input : In INT 原始采样值 *) (* Input : Rst BOOL 清零 *) (* Output : Ave INT 平均值 *) (* Internal : Buf ARRAY[0..3] OF INT *) (* Internal : WIdx INT 写指针 *) (* Internal : I INT 循环变量 *) (* Internal : Sum DINT 累加和用 DINT 防溢出 *) IF Rst THEN FOR I : 0 TO 3 DO Buf[I] : 0; (* 缓冲区全部清零 *) END_FOR; WIdx : 0; Ave : 0; RETURN; (* 清零周期直接返回不参与计算 *) END_IF; Buf[WIdx] : In; (* 新值覆盖最旧的一格 *) WIdx : WIdx 1; IF WIdx 3 THEN WIdx : 0; (* 环形指针回绕 *) END_IF; Sum : 0; FOR I : 0 TO 3 DO Sum : Sum Buf[I]; END_FOR; Ave : Sum / 4; (* 整数除法余数丢弃 *)逻辑上有三个点值得说。第一Rst用了RETURN提前退出避免清零周期把 0 也当成一次采样写进缓冲否则复位后前四个周期的平均值会偏小。第二累加用DINT而不是INT四点INT相加在极端值下会溢出INT的范围是 -32768 到 32767两路 30000 相加就翻车了。第三Sum / 4是整数除法如果你的采样值本身带小数要把Sum和Ave都改成REAL并且注意REAL在部分低端 CPU 上运算周期更长。参数上最常改的是缓冲深度。把ARRAY[0..3]改成ARRAY[0..7]同时把WIdx 3改成WIdx 7、除数改成 8三处必须同步改。漏改一处的结果是平均值恒偏小而且不报错这是纯逻辑错误编译器和手册都救不了你。2.3 支持边界型号、版本、任务类型三道门槛手册开篇就把适用范围写死了CX-Programmer 6.1 版本、CP1H 全系以及 3.0 版本以上的 CS1-H、CJ1-H、CJ1M。这三条里最容易踩的是版本——2.0 版及以下的 CS/CJ 系列 CPU 根本不支持功能块程序下载进去之后所有实例会被当成非法指令用户程序既不能编辑也不能执行。第二道门槛是任务类型。含功能块的程序可以正常上传和下载但含功能块的任务无法下载到任务单元中上传是允许的。这个不对称非常坑你在线上能读出来改完再写回去就失败现场如果没带备份只能现场重写。我的习惯是任务单元里的逻辑一律不用功能块改用普通子程序牺牲一点封装性换下载的确定性。第三道门槛是 CPU 单元内部的功能块规格手册 2-7 节按型号列了可用实例数、程序步骤数上限。实例不是免费的每个实例都要吃掉一块内部变量区规格表里那列数字是硬上限超了编译直接拦。2-8 节还给了功能块程序步骤数和实例执行时间做周期敏感的项目时要拿这张表估一下扫描时间增量别等上线才发现周期从 4ms 涨到 9ms。还有一条容易忽略的限制写在 2-3 节是一张禁用指令表。跨扫描周期、带跳转性质的控制指令基本都在里面功能块内部的算法被设计成每个周期从头执行到尾任何试图跳出这个模型的东西都会被拦。动手写复杂功能块之前先把这张表过一遍比写完再一条条删效率高得多。3. 在 CX-Programmer 6.1 里做出第一个能下载的功能块概念理清之后落到操作。这一章按真实顺序走一遍变量表怎么填、AT 怎么设、库文件怎么生成、实例怎么调、下载和备份怎么收尾。每一步都给出可对照的字段和判据。3.1 变量表五类变量各管什么功能块的变量表有五个方向填错方向是新手最常见的翻车点。判据很简单看这个数据从哪来、到哪去。变量类型数据来源能否被调用方赋值典型用途输入变量调用方传入能采样值、使能位、设定值输出变量算法内部产生只能读计算结果、状态标志输入输出变量调用方传入并被修改能累计量、需要回写的状态内部变量算法内部使用不能缓冲区、中间计算、循环变量外部变量直接绑定 I/O 地址不能需要 AT 设定的地址访问输入输出变量在新手眼里容易和输入变量混。区别在于语义输入变量是算之前就定好的值输入输出变量是算完可能被改、并且要带回给调用方的值。比如一个累计计数器功能块PV应该是输入输出变量因为每个周期它都会被算法加一调用方还要读它。内部变量和外部变量的分界线是地址。内部变量不绑定任何 I/O 地址纯内存外部变量必须带 AT 设定直接映射到实际地址。手册里反复强调的一条规则是分配到基本 I/O 单元、特殊 I/O 单元和 CPU 总线单元的地址无法注册为全局符号也就无法被指定为外部变量这类场景一律用带 AT 设定的内部变量兜住。注意功能块算法里的输入变量是在算法执行之前成批赋值的输出变量是在算法执行之后成批写出的。如果你的逻辑依赖执行到某一行时输入刚好变化这个时序假设不成立必须改用内部变量或外部变量。3.2 AT 设定与多字操作数的强制规则AT 设定是功能块里最需要敬畏的一栏。手册里的原话大意是当指令操作数要指定多个字中的首地址或末地址时操作数必须用带 AT 设定的变量或外部变量来指定或者变量的长度必须与指令要处理的数据长度完全一致。三种情况分别对应三种编译结果下面这张表是我自己整理的对照场景变量写法编译结果长度固定变量长度一致ARRAY[0..9] OF INT指令处理 10 字通过长度固定变量长度不一致ARRAY[0..9] OF INT指令处理 16 字编译报错长度由常量指定指令第二操作数为常量 16编译报错长度由变量指定指令第二操作数为INT变量不报错仅警告最后一行是真正危险的地方。编译器不报错只在输出窗口给一条警告很多人点掉就忘了。运行时的实际行为是指令会按变量里给的长度去读写超出数组元素数量的那部分照样执行比如数组注册了 10 个元素、指令要处理 16 个字多出来的 6 个字会被读写。如果这 6 个字正好被别的指令用着就是一次没有征兆的误动作。正确写法是用带 AT 设定的内部变量让地址和长度都显式固定下来(* 反例长度靠变量传入编译期查不出越界 *) FOR I : 0 TO Len - 1 DO Dst[I] : Src[I]; END_FOR; (* 正例长度固定数组元素数与指令处理长度严格一致 *) (* 变量表Src ARRAY[0..15] OF INTDst ARRAY[0..15] OF INT *) FOR I : 0 TO 15 DO Dst[I] : Src[I]; END_FOR;第一段的问题不在语法在于Len是运行期才知道的值编译器的静态检查够不着。如果业务上确实需要可变长度把上限写死在数组定义里运行时用IF Len 16 THEN Len : 16;做钳位宁可少搬几个字也不要越界。3.3 从定义到库文件再到实例调用顺序是这样的新建功能块定义、选语言梯形图或 ST、填变量表、写算法、编译、生成库文件、在主程序里调用。编译这一步会拦下大部分结构性错误变量方向填反、数组长度不匹配、用了禁用指令、实例重名。编译通过不等于逻辑正确但编译不通过一定有问题先把红字清完再谈仿真。生成库文件之后功能块会出现在项目树的库列表里可以直接拖进梯形图回路。拖动的时候 CX-Programmer 会让你填实例名和输入参数。这里有个细节输入参数如果是常量数值必须加前缀表示十进制、#表示十六进制也可以带、-号。原因在于不加前缀的纯数字会被当成 CIO 区地址解析你输入20它理解成 CIO 0020而不是数值 20。这个坑我在第一次用的时候踩得很实滤波器的设定值一直是个莫名其妙的地址值。调用之后的实例长这样FB_Filter_01是实例名后面跟的是参数绑定(* 主程序中的实例调用此处以 ST 形式示意参数绑定关系 *) (* 输入参数In 绑定 D100Rst 绑定 W0.00 *) (* 输出参数Ave 绑定 D200 *) FB_Filter_01(In : D100, Rst : W0.00, Ave D200);:是输入方向是输出方向这个符号在欧姆龙 ST 里是固定的写反了编译不过。变量名必须和功能块定义里的完全一致大小写敏感度按项目设置走我一般要求全大写省得跨项目迁移时出岔子。3.4 下载、在线编辑与 BKUP 灯下载本身没有特殊性含功能块的程序和普通程序走同一个通道。真正需要盯的是在线编辑之后的备份动作。CS1-H、CJ1-H、CJ1M、CP1H 这几类 CPU 在执行了在线编辑之后会把用户程序和参数区数据备份到内置闪存备份期间 CPU 单元前面的 BKUP 灯亮。这段时间里断电数据就不备份了下次上电跑的还是旧程序。现场调试最容易出的事故就是在这一刻拉了总闸,血泪经验是看到 BKUP 灯亮先等它灭再动任何开关。备份状态可以在 CX-Programmer 里查PLC 属性里打开存储器备份状态显示查看菜单里调出 PLC 存储器备份状态窗口。这个窗口我一般会在调试开始时一直开着比事后猜有没有备份成功靠得住。在线编辑还有一条副作用周期时间会延长。手册的安全注意事项里明确要求只有在确认周期延长不会造成不良影响之后才能做在线编辑否则输入信号可能读不到。做高速计数或者短脉冲捕捉的项目在线编辑前先把周期时间监控打开涨超过 20% 就别在production时段动。4. 数组和多字操作数编译期报错与运行期越界这一章单独拎出来讲是因为功能块里绝大多数莫名其妙的故障都出在这里。编译能过的写法不一定安全编译不过的写法反而可能是好事。4.1 首字末字为什么强制 AT欧姆龙的指令体系里很多指令的操作数是首地址长度的形式比如块传送、块比较、字符串处理。功能块的变量表如果不带 AT变量在内存里的位置由编译器分配你不控制它前后是什么。一旦指令按长度往后读读到的就是别人家的数据。所以手册的规则是由操作数指定多个字中的第一个或最后一个时这个操作数无法用普通输入变量充当必须用带 AT 设定的内部变量或者用外部变量。手册还补了一句更细的可以在内部数组变量中交替地指定第一个或最后一个元素意思是数组元素本身可以作为首地址的载体前提是数组长度和指令长度对得上。这条规则的实践版本是凡是涉及多字操作的变量表里一律显式写 AT地址自己排排完之后在注释里标明这段地址归谁用避免两个功能块抢同一片区域。4.2 长度不固定时的静默越界前面表格里那行长度由变量指定不报错只警告值得单独展开。手册举的例子很具体指令操作数长度为 16实际变量表里注册的元素数是 10指令会对超出元素数的那部分执行读写也就是对注册元素之后的 6 个字做读或写。如果这 6 个字还被其它指令用着就会发生意外动作。这类问题的排查成本极高因为现象是偶发误动作跟输入信号、扫描周期、甚至环境温度都看不出关联。我的做法是在功能块定义阶段就把所有数组长度写成常量宁可多定义几个不同长度的功能块也不做万能长度的通用块。长度可变的通用块看着优雅实际是把编译期能查出的问题推到了运行期这笔账不划算。还有一条相关的注意事项如果输入变量数据不是布尔格式输入参数里只写了数值比如20CIO 区地址中的实际值会被跳过。这句话和前面说的前缀问题是同一件事的两面绕不开。4.3 输入变量的成批传递时序功能块的执行模型是算法开始之前所有输入参数的值成批传到输入变量算法执行完之后输出变量的值成批写回参数。中间过程不传递。这意味着两件事。第一算法内部读输入变量读到的永远是本周期开始时的快照不会中途变化。第二如果某个输入值需要在算法执行到一半时被修改并且后续指令要用新值只能改用内部变量或外部变量。手册给的建议是需要在算法执行指令的过程中让数值经过参数到达输入变量时用内部变量或外部变量代替输入变量。从输出变量写回参数也是同样的时序。这条规则在单点逻辑里几乎无感一旦写带中间状态的状态机就会变成为什么我这个分支的判断用的还是旧值的经典疑问。提示写状态机时把所有中间状态放内部变量输入变量只在每个周期开头读一次并立刻转存到内部变量后面的逻辑全部基于内部变量跑能省掉一大类时序问题。5. 避坑与排查五条现场记录下面五条都是我在实际项目里遇到过、并且能在手册里找到对应条款的问题。每条按现象、原因、解决三段写能对号入座就直接用。5.1 下载成功但实例不执行现象程序下载完成编译无报错监控里实例的输入有值、输出恒为 0功能块内部变量一动不动。原因目标 CPU 是 2.0 版及以下的 CS/CJ 系列不支持功能块。程序能下进去但所有实例被当作非法指令既不编辑也不执行。手册在应用注意事项里写得很明确只是这条藏在正文中间容易漏。解决先确认 CPU 单元型号和版本对照手册开头的适用范围。不支持就只能改回普通子程序实现或者换 CPU。已经下进去的非法程序要重新下载一份不含功能块的版本清掉否则后续在线编辑会一直报奇怪的结构错误。5.2 常量参数变成了地址现象功能块调用时输入参数填了20运行结果完全不对监控发现该参数读到的值是一个跟预期无关的数字。原因不加前缀的纯数字被解析成 CIO 区地址20被理解成 CIO 0020 的当前值而不是常数 20。解决常量一律加前缀十进制写20十六进制写#0014。这条规则对手册里所有输入参数都成立包括定时器的设定值、比较指令的比较值。5.3 多字指令读写到了隔壁变量现象一个块传送相关的功能块运行一段时间后另一个完全无关的功能块的内部变量值被改了改的值还正好是本周期搬过来的数据。原因数组长度和指令处理长度不一致或者长度由变量指定导致编译器没拦住指令越界读写到了相邻区域。解决把数组长度和指令长度对齐长度写成常量。已经上线的项目如果改不动结构至少要在变量表里给相关数组前后各留一段空的填充变量当缓冲区用空间换安全。5.4 在线编辑后断电程序回到旧版本现象在线改了一段逻辑监控确认生效第二天早上上电发现改的东西没了。原因在线编辑后 CPU 会把程序备份到内置闪存备份期间 BKUP 灯亮这段时间断电备份没完成上电加载的还是旧程序。解决养成看 BKUP 灯的习惯灯亮期间不动电源。调试前打开 PLC 存储器备份状态窗口确认备份完成再收工。另外在线编辑会延长周期时间改完顺手看一眼周期监控涨太多要评估。5.5 任务单元写不回去现象从任务单元上传程序正常改完之后下载报错提示任务单元不支持。原因含功能块的任务无法下载到任务单元中上传是允许的。这个不对称是设计如此不是故障。解决任务单元里的逻辑不用功能块改用普通子程序。如果已经用了把功能块展开成等效的梯形图或子程序再下载。项目规划阶段就把这条定下来比后期返工省事。6. 把手册当查表工具三张索引表和一条核对习惯这份手册七百多页不可能通读我的用法是把它拆成三张索引表遇到问题直接定位页码而不是从头翻。第一张是型号支持表放在手册开头和 2-7 节。左边写你手上的 CPU 型号右边写三件事是否支持功能块、可用实例数上限、程序步骤数上限。这张表我一般抄在项目笔记第一页选型阶段就要用。CJ1M 和 CP1H 的实例上限不一样同一个程序从 CJ1M 迁到 CP1H 可能要重新分配实例。第二张是报错到条款的映射表靠编译器和手册对照积累编译/运行现象对应条款位置处置动作编译报错提示操作数长度不一致2-5 节操作数注意事项对齐数组长度与指令长度编译报错提示变量方向错误1-3 节变量定义检查输入/输出/内部方向编译通过但仅告警2-5 节长度由变量指定立即改为常量长度别放过实例不执行应用注意事项CPU 版本核对 CPU 版本是否 3.0 以上下载到任务单元失败应用注意事项任务单元改用普通子程序第三张是 ST 语法速查对应附录 B。不需要背写的时候把CASE、FOR、REPEAT三段的语法结构抄在便签上贴在显示器边一个月就记住了。附录 A 的数据类型表同理重点是INT和DINT的边界、REAL在哪些 CPU 上可用、BCD 类型和二进制类型的转换关系。真正让我少踩坑的是最后这条习惯每次新建功能块先把变量表全部填完、AT 全部标好、注释全部写完再动手写算法。听起来很笨但变量表是功能块的骨架骨架歪了后面全是补丁。我早年习惯边写算法边加变量结果一个功能块改到第三版的时候变量表里躺着七个没用的内部变量、两个方向填错的输入变量编译能过仿真也对上线第二周才发现某个内部变量和相邻功能块的 AT 区域重叠排查花了整整两天。从那以后我每次新建功能块都强制走一遍变量表填满 → AT 排布画在纸上 → 长度全部写成常量 → 注释补齐 → 再写第一行算法的流程多花二十分钟省下的是现场两天的返工。这份手册的价值不在于读一遍而在于把它当成一张随时能翻的规则表遇到报错先查表再动手别靠猜。希望帮到你。本文还有配套的精品资源点击获取