简介:本资源是面向工业自动化初学者与欧姆龙PLC现场工程师的ST语言编程入门手册,系统解决梯形图程序员向结构化文本(ST)编程转型中的语法理解、功能块应用及工程实践问题。手册覆盖ST语言核心特性、CX-Programmer 6.1编程环境配置、变量声明与赋值、条件/循环语句、数字/模拟I/O、定时器计数器、数据处理等高级功能块的使用方法,并专章强调安全规范与设备commissioning注意事项,内容紧扣CS1-H、CJ1-H、CJ1M、CP1H等主流欧姆龙CPU单元。资源为单文件PDF格式,共1个2.26MB文档,排版清晰、术语规范,含完整目录、功能块规格表、实例说明及版本升级信息,便于快速查阅与实操对照。目前已有7278人学习下载,可作为欧姆龙ST编程的权威参考指南与现场调试速查手册。
1. 欧姆龙ST编程中文手册:不是翻译文档,而是PLC逻辑落地的“方言词典”与调试黑匣子解码器
你手头拿到的《欧姆龙ST编程中文手册》,大概率不是一本能直接当教材用的“入门到精通”,而是一份夹在IEC 61131-3标准、欧姆龙NJ/NX系列硬件特性、CX-Programmer/CX-One工程环境三者缝隙里的实操型技术契约文本。它不解释“为什么ST比梯形图更适合做运动控制”,但会明确告诉你WHILE循环在NJ控制器中触发一次扫描周期时,EXIT语句是否影响当前循环体剩余语句的执行顺序;它不教你怎么写PID,但会在“函数块调用规则”小节里用加粗字体标出:“当FB实例被多次调用且含静态变量时,各实例的静态变量互不共享——除非显式声明为GLOBAL”。这本手册的真实价值,是让某高校自动化实验室的A同学,在调试一条包装产线的视觉定位+伺服追剪逻辑时,靠查“ST中数组索引越界行为定义”这一行小字,避开了连续三天无法复位的PLC停机故障。它适合两类人:一类是刚从三菱/西门子平台转来、对欧姆龙特有的VAR_GLOBAL RETAIN语法感到陌生的工程师;另一类是已经能写基础ST但总在通讯中断后变量值异常、定时器未清零等“玄学问题”上反复翻车的现场调试员。它解决的不是“会不会写”,而是“为什么这么写才不会在凌晨两点被电话叫醒”。
2. ST语言在欧姆龙平台上的真实定位:从IEC标准到NJ/NX硬件特性的三层适配
2.1 为什么欧姆龙ST不是“标准ST”?硬件指令集与编译器的隐性约束
IEC 61131-3标准定义了ST语法骨架,但欧姆龙NJ/NX系列PLC的底层执行引擎(即其固件中的ST运行时)对标准做了关键裁剪与增强。最典型的例子是位操作指令的不可替代性:标准ST允许用AND,OR,XOR对整型变量做按位运算,但欧姆龙编译器在生成机器码时,若检测到操作数为WORD或DWORD且参与的是I/O映射区地址(如%IW0001),会强制插入专用硬件指令WAND/WOR——这类指令在手册“系统函数”章节第4.7节有独立表格说明,但不会在ST语法示例中主动提示。这意味着,如果你写:
VAR input_word : WORD := 16#FF00; mask : WORD := 16#00FF; result : WORD; END_VAR result := input_word AND mask; // 看似标准,实则触发WAND硬件指令这段代码在CX-Programmer中编译无错,但若你后续想把result直接赋给一个BOOL数组(如bool_array[0] := (result <> 0);),编译器会报错Type mismatch: cannot convert WORD to BOOL——因为WAND指令的输出被编译器视为“受保护的硬件寄存器类型”,而非标准WORD。手册第5.2节“数据类型隐式转换规则”表格第3行明确列出:WAND/WOR/WXOR结果仅允许赋值给WORD/DWORD或同类型指针,禁止任何向BOOL、INT的隐式降级。这是纯标准ST文档绝不会提及的硬性约束。
提示:该约束在CX-One V4.0及以后版本中仍存在,V4.3新增了
TO_BOOL()显式转换函数,但手册中该函数仅出现在“新功能速查表”附录,主章节未展开用法。
2.2 CX-Programmer工程结构如何绑架ST代码组织?POU、全局变量与RETAIN的连锁反应
欧姆龙ST代码不能脱离CX-Programmer的工程树独立存在。一个典型NJ项目包含三个强耦合层:
- POU(Program Organization Unit)层级:
MAIN程序、FB功能块、FC函数必须严格按“调用链”嵌套,且FB内部若声明VAR_GLOBAL RETAIN,其生命周期绑定到整个PLC运行周期,不受MAIN重启动影响; - 全局变量表(Global Variable Table):此处声明的
VAR_GLOBAL变量,其地址空间独立于POU,但手册第3.8节强调:“当同一变量名在POU内VAR与全局表中同时存在时,POU内引用优先级高于全局表——但编译器不报错,仅静默采用POU内定义”; - RETAIN区域管理:手册第6.1节用加粗警告:“
VAR_GLOBAL RETAIN变量在PLC断电后由超级电容维持,但若电容老化导致维持时间<100ms,该变量将丢失。此时VAR RETAIN(非global)变量因依赖RAM备份机制,反而更可靠。”
这种设计导致一个经典翻车场景:某跨平台系统开发者将西门子SCL中习惯的“全局配置结构体”直接移植为欧姆龙VAR_GLOBAL RETAIN,结果在产线电压波动时,结构体中部分字段(如config.enable_flag)被重置为初始值,而其他字段(如config.max_speed)却保留旧值——根本原因是RETAIN区域按字节粒度备份,而结构体字段内存布局未对齐,电容维持失效时发生部分写入。手册第6.4节“RETAIN变量初始化流程图”末尾用小号字体注明:“建议对多字段结构体使用VAR RETAIN并手动实现INIT逻辑,而非依赖VAR_GLOBAL RETAIN自动恢复。”
2.3 ST与欧姆龙专有指令的共生关系:何时必须放弃“纯ST”?
欧姆龙NJ系列的运动控制、EtherCAT主站、安全逻辑等功能,无法仅用ST语法实现,必须调用特定FB。例如:
- 启动一个轴的原点回归,不能写
axis_home := TRUE;,而必须调用MC_HomeFB,并传入AxisNo,Mode,Velocity等参数; - 读取一个EtherCAT从站的诊断信息,需调用
ECAT_GetDiagInfoFB,其输出参数DiagData是ARRAY[0..15] OF BYTE,而手册第8.5节明确要求:“该数组必须声明为VAR_IN_OUT,且调用前需用FILL指令预置全0,否则返回数据首字节恒为16#FF”。
这意味着,一份“合格”的欧姆龙ST程序,本质是ST逻辑 + 欧姆龙FB调用 + 必要的系统函数(如ADR(),SIZEOF())的混合体。手册第7章“系统函数与FB调用规范”用整整12页表格列出每个FB的输入/输出参数类型、执行条件、错误代码含义——比如MC_MoveAbsolute的Execute输入端,手册强调:“必须为上升沿触发(即前一周期FALSE,当前周期TRUE),若持续TRUE超过2个扫描周期,FB将进入ERROR状态且ErrorID返回16#8005”。这个细节在标准IEC文档中不存在,却是现场调试中最常被忽略的“定时器陷阱”。
3. 手册核心章节的实战拆解:从“查不到”到“秒定位”的检索路径
3.1 “ST语法速查表”(第2章)不是起点,而是终点:先建模再查表
新手常犯的错误是打开手册直奔第2章“ST语法速查表”,试图背下所有关键字。但欧姆龙ST的关键差异在于上下文敏感性。例如CASE语句:
- 标准ST中
CASE x OF 1: ...; 2: ...; ELSE ...; END_CASE是合法的; - 但在欧姆龙中,若
x是BOOL类型,手册第2.4节脚注③警告:“CASE的判断变量必须为INT,DINT,WORD,DWORD,BOOL类型需先用TO_INT()转换,否则编译通过但运行时ELSE分支恒执行。”
因此,正确路径是:
- 在CX-Programmer中新建ST POU,写下你的逻辑框架(如
CASE mode OF ... END_CASE); - 编译,观察错误提示(如
Error 1207: CASE selector type not supported); - 打开手册第2章,按错误代码1207反查——手册在页眉标注“参见2.4节脚注③”,而非在正文中罗列所有错误码。
手册的“速查表”本质是编译器错误码的映射索引,而非教学大纲。我一般会把常用错误码(1201-1299)打印成A4纸贴在显示器边框,比翻手册快3倍。
3.2 “系统函数与FB参数表”(第7-8章):表格列名暗藏执行时序玄机
手册第7章的函数表看似枯燥,但列名设计直指执行本质。以MOVE函数为例,表格包含以下列:
| 参数名 | 类型 | 方向 | 必需 | 描述 | 备注 |
|---|---|---|---|---|---|
IN | ANY | IN | 是 | 源数据 | 支持INT,REAL,STRING等 |
OUT | ANY | OUT | 是 | 目标地址 | 必须为可写地址(如%MW100,var_name),不可为常量 |
EN | BOOL | IN | 否 | 使能端 | 默认TRUE,若为FALSE则OUT保持上次值 |
ENO | BOOL | OUT | 否 | 使能输出 | 仅当EN=TRUE且执行成功时为TRUE |
注意“备注”栏最后一句:“仅当EN=TRUE且执行成功时为TRUE”。这意味着ENO不是简单的“执行完成标志”,而是“执行成功标志”。若IN为REAL而OUT为INT,会发生截断但ENO仍为TRUE;但若OUT指向一个非法地址(如%MW99999),ENO将为FALSE且ErrorID被置位。这个逻辑在手册第7.2节“ENO行为规范”中有详细时序图,但新手往往只看表格忽略文字说明,导致用ENO做流程控制时出现“明明失败了却继续往下走”的诡异现象。
3.3 “RETAIN变量管理”(第6章):一张图看懂断电数据生死线
手册第6章的核心是图6.1“RETAIN变量生命周期示意图”,但它被埋在15页文字之后。这张图实际揭示了三个生死攸关的节点:
- 断电瞬间:超级电容开始供电,
VAR_GLOBAL RETAIN进入维持模式; - 电容耗尽临界点(约100ms):若此时PLC未恢复供电,
VAR_GLOBAL RETAIN全部丢失,但VAR RETAIN因已备份至Flash,仅丢失最后一次未同步的修改; - 上电初始化阶段:
VAR RETAIN从Flash加载,VAR_GLOBAL RETAIN从电容恢复(若存活),此时若两者同名变量值冲突,手册第6.3节规定:“VAR RETAIN加载值覆盖VAR_GLOBAL RETAIN恢复值”。
这个规则直接决定故障恢复策略。例如,某图像处理Demo中需保存相机曝光时间参数,若定义为VAR_GLOBAL RETAIN exposure_time : REAL;,断电后可能丢失;改为VAR RETAIN exposure_time : REAL;并配合MAIN中IF first_scan THEN exposure_time := 100.0; END_IF;,则既保证默认值安全,又支持运行时修改持久化。
4. 避坑:欧姆龙ST编程中5个血泪换来的“手册没明说但必须知道”的真相
4.1 现象:ST程序下载后PLC立即报错Error 16#4001(内存溢出),但工程总大小显示仅占RAM 65%
原因:欧姆龙NJ系列的ST编译器在生成机器码时,会对ARRAY类型进行静态内存预分配,且分配量=数组长度×单元素最大可能尺寸。例如ARRAY[0..999] OF (a: INT; b: REAL; c: STRING[20]);,编译器按c的STRING[20](占20字节)计算,总分配=1000×(2+4+20)=26,000字节,远超实际使用量。手册第3.5节“数组内存计算规则”表格第2行小字注明:“编译器以结构体中最大字段尺寸为单位分配连续内存,不进行字段级压缩。”
解决:拆分大数组,或改用POINTER TO动态申请(需手动NEW/DELETE),手册第3.9节“指针使用限制”强调:“NEW仅支持STRUCT和基本类型,不支持STRING。”
4.2 现象:FOR循环中i变量在循环体末尾被修改,但下一次迭代i仍按步进值增加
原因:欧姆龙ST的FOR是确定性循环,循环变量i的初值、终值、步进值在循环开始前已固化。循环体内对i的赋值仅影响本次循环体,不影响下次迭代的i值。手册第2.5节“FOR循环执行机制”图2.5用虚线箭头标明:“循环变量更新仅由TO/BY子句驱动,与循环体内赋值无关。”
解决:需改变逻辑时改用WHILE循环,或用EXIT提前跳出。
4.3 现象:两个FB实例调用同一VAR_GLOBAL变量,但一个实例修改后另一个实例未感知
原因:VAR_GLOBAL变量在编译时被分配固定地址,但若FB声明中未用REF关键字传递该变量,编译器会为每个FB实例创建独立副本。手册第4.3节“全局变量传递规则”表格第1列明确:“VAR_GLOBAL变量作为FB输入参数时,若未声明为VAR_INPUT REF TO,则传递值拷贝而非地址引用。”
解决:在FB接口中声明input_ref : REF TO INT;,调用时用input_ref := ADR(global_var);。
4.4 现象:TON定时器在ST中使用TON(IN:=start_flag, PT:=T#5S);,但Q输出延迟远超5秒
原因:欧姆龙ST中TON是函数块(FB),必须在每次扫描周期调用,且IN端需保持TRUE至少一个扫描周期。若start_flag是单次脉冲(如按钮上升沿),TON仅被调用一次,ET(已过时间)从0开始计,但下一个扫描周期IN变FALSE,TON复位,Q永不置位。手册第7.6节“定时器FB调用规范”强调:“TON/TOF必须置于MAIN或循环调用的POU中,且IN信号需维持至少PT的1/10时间。”
解决:用R_TRIG捕获上升沿后,置位一个BOOL中间变量,用该变量驱动TON.IN。
4.5 现象:字符串比较IF str1 = str2 THEN ... END_IF;始终为FALSE,即使内容相同
原因:欧姆龙STRING类型包含隐藏的长度字节(第0字节)。str1与str2若声明为STRING[10],但实际内容均为'ABC',其内存布局为[3, 'A', 'B', 'C', 0, 0, 0, 0, 0, 0],而=运算符比较的是全部10字节。手册第3.7节“STRING比较规则”注明:“=比较整个声明长度的内存块,包括未填充的0字节。”
解决:用STR_EQUAL(str1, str2)系统函数(手册第7.8节),或手动比较str1[0] = str2[0] AND str1[1..str1[0]] = str2[1..str2[0]]。
5. 进阶技巧:用手册“反向工程”CX-Programmer的隐式行为,把调试时间砍掉70%
5.1 从错误代码反推编译器内部状态:建立你的个人错误码速查库
欧姆龙编译器的错误码是理解其执行逻辑的密钥。手册虽列出常见错误码,但未分类。我按调试场景整理了高频错误码的“行为指纹”:
| 错误码 | 触发场景 | 隐含编译器状态 | 应对动作 |
|---|---|---|---|
1207 | CASE变量类型非法 | 编译器已解析CASE结构,但类型检查失败 | 检查变量声明类型,勿用BOOL作selector |
1605 | FB调用时IN_OUT参数类型不匹配 | 编译器已绑定FB实例,但参数地址解析失败 | 检查IN_OUT参数是否为变量地址(非常量/表达式) |
4001 | 内存溢出 | 编译器已完成内存规划,但总需求超限 | 查ARRAY/STRUCT声明,用SIZEOF()验证 |
8005 | MC_系列FB执行超时 | 运行时检测到硬件响应超时(非编译错误) | 检查Execute是否为单周期脉冲,确认硬件连接 |
提示:在CX-Programmer中,双击错误列表中的错误码,光标会跳转到对应代码行——但不会高亮显示相关手册页。我的做法是,在VS Code中建一个
omron_errors.md文件,把上述表格存为Markdown,调试时Ctrl+F搜索错误码,3秒内定位根因。
5.2 利用手册“未声明的默认值”做安全兜底:让PLC自己救自己
手册中大量参数有“未声明即生效”的默认行为,这些是构建鲁棒逻辑的基石。例如:
TON的PT参数若未指定,默认为T#1S(手册第7.6节脚注①);MC_MoveAbsolute的Acceleration参数若为0,编译器自动设为MaxAccel/2(手册第8.3节“参数默认值表”);VAR声明中若无初始化值,INT/REAL默认为0,BOOL默认为FALSE,但STRING默认为''(空字符串),且第0字节长度为0(手册第3.7节“变量初始化规则”)。
这些默认值可被主动利用。例如,在安全逻辑中,定义:
VAR safe_mode : BOOL; // 未初始化,默认FALSE emergency_stop : BOOL; // 未初始化,默认FALSE END_VAR // 主逻辑中无需写 safe_mode := FALSE; // 因为首次扫描时safe_mode已是FALSE,可直接用于条件判断 IF NOT safe_mode AND emergency_stop THEN // 执行急停动作 END_IF;这样避免了因忘记初始化导致的“默认TRUE”风险。手册虽未强调“默认值即安全值”,但所有默认值均经欧姆龙安全认证测试,比人工初始化更可靠。
5.3 手册附录的“隐藏彩蛋”:用“指令执行周期表”预判性能瓶颈
手册最后附录的“各指令平均执行周期(μs)”常被忽略,但它能提前预警性能问题。例如:
MOVE指令:INT→INT为0.1μs,STRING[100]→STRING[100]为12.5μs;FIND函数(查找子串):平均25μs,最坏情况达200μs;MC_Home:单次调用约800μs,且占用专用运动控制资源。
若你的MAIN程序扫描周期目标为2ms,而其中包含10次FIND调用,最坏情况耗时2000μs,已占满周期。此时必须重构:用STR_EQUAL替代FIND做相等判断,或把字符串处理移到低频POU中。手册附录的数字是实测值,不是理论值——它来自欧姆龙实验室用NJ501-1300控制器在满载条件下的测试,比任何仿真都真实。
我带过的某导师曾用这张表说服客户放弃“在PLC中实时解析JSON”的方案:STRING操作在欧姆龙平台上天然低效,与其花3周优化,不如用PC端处理后通过EtherCAT下发结构化数据。手册附录没有说这句话,但数字本身就在说话。
希望帮到你。
本文还有配套的精品资源,点击获取