文章目录

ST保留字冲突:避免使用 END、PROGRAM 等关键字作为变量名

发布于 2026-03-19 12:48:33 · 浏览 7 次 · 评论 0 条

在结构化文本(Structured Text,ST)编程中,ENDPROGRAMFUNCTIONFUNCTION_BLOCKVARIFWHILEFOR 等是 IEC 61131-3 标准定义的保留字(Reserved Identifiers)。它们构成 ST 语言的语法骨架,用于声明程序结构、控制流程和数据区域。一旦将这些词用作变量名、数组名、函数调用名或自定义类型名,编译器将无法区分“语法指令”与“用户标识符”,直接报错或引发隐性逻辑错误——轻则编译失败,重则运行时跳过关键分支、覆盖内存、导致设备误动作。

以下为可立即执行的冲突规避指南,覆盖识别、检测、修复、预防四大环节,所有操作均基于主流 PLC 开发环境(如 CODESYS、TIA Portal、Unity Pro、Automation Studio)通用逻辑,无需额外插件。


一、明确哪些词绝对不可用作变量名

IEC 61131-3 标准将保留字分为五类。任何一类中的词,只要出现在 VAR 块、赋值语句左侧、函数参数列表或结构体成员声明中,即构成语法冲突。

  1. 程序结构关键字
    PROGRAMFUNCTIONFUNCTION_BLOCKMETHODACTIONCONFIGURATIONRESOURCE

  2. 声明与作用域关键字
    VARVAR_INPUTVAR_OUTPUTVAR_IN_OUTVAR_GLOBALVAR_TEMPVAR_EXTERNALEND_VAR

  3. 控制流关键字
    IFELSIFELSEEND_IFCASEOFEND_CASEWHILEDOEND_WHILEREPEATUNTILEND_REPEATFORTOBYEND_FOR

  4. 终止与返回关键字
    ENDRETURNEXIT

  5. 类型与转换关键字
    BOOLINTDINTREALSTRINGTIMEDATETODDTARRAYSTRUCTPOINTERTO_BOOLTO_INTTO_REAL 等所有标准类型名及类型转换函数名

⚠️ 注意:大小写不敏感。endEndEND 全部等效;programPROGRAM 同样被禁止。


二、快速识别已存在的冲突变量(3步排查法)

1. 扫描 VAR 块:查找非法左值

打开任意 POU(Program Organization Unit)的 ST 代码,在 VAREND_VAR 之间逐行检查:

  • 若某行形如 END : INT;PROGRAM_NAME : STRING;IF_FLAG : BOOL;,即存在冲突(ENDPROGRAMIF 均为保留字)。
  • 若某行形如 TIME : DINT;,也属冲突——TIME 是标准数据类型,不可重定义。

✅ 正确写法示例:

VAR
    bEnableMotor : BOOL;     // ✅ 使用描述性前缀 + 合法名称
    nSetSpeed    : INT;      // ✅ 小写开头,无保留字
    tDelay       : TIME;     // ✅ 类型名仅用于声明右侧,左侧不可用
END_VAR

❌ 错误写法示例:

VAR
    END      : BOOL;   // ❌ 保留字作变量名 → 编译器报错 "Syntax error: expected identifier"
    PROGRAM  : STRING; // ❌ 同上
    TIME     : DINT;    // ❌ 类型名作变量名 → 报错 "Identifier 'TIME' already declared as type"
    IF       : BOOL;    // ❌ 控制关键字作变量名
END_VAR

2. 搜索赋值语句左侧:捕获隐性冲突

BEGINEND_PROGRAM(或对应结束关键字)之间,查找所有 := 左侧的标识符:

  • END := TRUE; → 冲突:END 是终止关键字,不可赋值。
  • PROGRAM := 'RUN'; → 冲突:PROGRAM 是结构关键字。
  • FOR := 0; → 冲突:FOR 是循环关键字。

✅ 正确写法:

bRunFlag := TRUE;        // ✅ 描述性布尔变量
nLoopCounter := 0;       // ✅ 避免使用 FOR/WHILE/IF 等词根

3. 检查函数调用与结构体成员:防止间接冲突

  • 若定义了结构体 TYPE MOTOR_CTRL : STRUCT ... END_STRUCT,则结构体内成员不可命名为 ENDPROGRAM

    TYPE MOTOR_CTRL : STRUCT
        bStart      : BOOL;  // ✅
        nRPM        : INT;   // ✅
        END         : BOOL;  // ❌ 冲突!结构体成员仍受保留字约束
    END_STRUCT
  • 函数调用参数名亦需合规:

    MyFunction(ENABLE := TRUE, END_TIME := T#5S); // ✅ 参数名合法
    MyFunction(END := TRUE, PROGRAM := 1);        // ❌ 参数名非法

三、一键修复冲突变量的标准化流程

按顺序执行以下四步,确保修复彻底且可追溯:

1. 全局替换前先备份

  • 在开发环境中执行 File → Save As,另存为 MyProject_v2_backup.pro
  • 或导出当前 POU 为 .st 文本文件,本地存档。

2. 启用编辑器高亮与语法检查

  • CODESYS:勾选 Tools → Options → Editor → Syntax Highlighting,并开启 Real-time syntax checking
  • TIA Portal:在 Options → Settings → PLCSIM Advanced / Compiler 中启用 Show all warnings and errors
  • Automation Studio:Tools → Options → Editor → Highlight reserved keywords

此时,所有保留字在代码中将以深红色背景+白色文字高亮显示(具体颜色依主题而定),便于肉眼定位。

3. 执行精准替换(推荐正则表达式)

在支持正则的编辑器(如 VS Code、Notepad++、CODESYS 内置编辑器)中,打开全部 .st 文件,执行以下替换:

查找内容(正则) 替换为 说明
\b(END|PROGRAM|FUNCTION|FUNCTION_BLOCK|VAR|IF|WHILE|FOR|RETURN|EXIT)\b g_$1` | `\b` 表示单词边界,避免匹配 `END_OF_CYCLE` 中的 `END`;`$1 引用捕获组,保留原词根
\b(BOOL|INT|DINT|REAL|STRING|TIME|DATE|TOD|DT|ARRAY|STRUCT)\b(?!\s*:) `t_$1` | 仅匹配非声明位置的类型名(如 `TIME := T#1S` 中的 `TIME`),`(?!\s*:)` 排除 `TIME : TON;` 这类合法声明 | ✅ 替换后效果: ```pascal // 替换前(错误) VAR END : BOOL; PROGRAM : STRING; TIME : DINT; END_VAR // 替换后(正确) VAR g_END : BOOL; g_PROGRAM : STRING; t_TIME : DINT; END_VAR ``` > 💡 命名规范建议: > - `g_` 前缀 = global scope(全局变量) > - `b_` 前缀 = boolean > - `n_` 前缀 = numeric (INT/DINT) > - `t_` 前缀 = time/duration > - `s_` 前缀 = string > 统一前缀既规避冲突,又提升可读性与维护性。 #### 4. **重新编译并验证逻辑完整性** - 执行 `Build → Rebuild All`。 - 若编译通过,进入在线调试模式,监控新变量 `g_END` 是否按预期更新(例如,原 `END := TRUE` 逻辑是否被 `g_END := TRUE` 完全替代)。 - 对照原始需求文档,逐条验证功能点:启动/停止、计时、状态切换等行为未因变量名变更而偏移。 --- ### 四、长效预防机制:从源头杜绝冲突 #### 1. **建立团队级命名白名单** 在项目根目录下创建 `ST_NAMING_RULES.md`,强制规定: - 禁止使用完整保留字(含大小写变体); - 禁止在变量名中**连续包含**保留字字符序列(如 `ENDBIT`、`PROG_CTRL`、`IF_STATE`),因其易被误读且部分旧版编译器会触发模糊匹配警告; - 允许使用缩写(如 `bEn` 代替 `bEnable`),但缩写必须为行业通用(`bEn`、`nSpd`、`tDly`),禁用自创缩写(如 `bE`、`nS`)。 #### 2. **配置编辑器自动校验** 在 CODESYS 中,通过 `Tools → Scripting → Editor Events` 添加脚本,实现实时拦截: ```python # auto_check_reserved.py reserved_words = { "END", "PROGRAM", "FUNCTION", "FUNCTION_BLOCK", "VAR", "IF", "WHILE", "FOR", "RETURN", "EXIT", "BOOL", "INT", "DINT", "REAL", "STRING", "TIME" } def on_text_changed(editor): text = editor.get_selected_text() or editor.get_text() for word in reserved_words: if re.search(rf"\b{word}\b", text, re.IGNORECASE): editor.show_message(f"⚠️ 保留字 '{word}' 不可用作变量名", "Error") ``` TIA Portal 用户可启用 `PLC → Options → Check naming conventions` 并导入自定义规则 XML。 #### 3. **CI/CD 流水线自动扫描(适用于大型项目)** 在 Git 提交钩子(pre-commit)或 Jenkins 构建步骤中加入 Shell 脚本: ```bash #!/bin/bash # scan_st_reserved.sh find . -name "*.st" | while read file; do grep -nE '\b(END|PROGRAM|FUNCTION|IF|WHILE|FOR|RETURN|EXIT|BOOL|INT|DINT|REAL|STRING|TIME)\b' "$file" \
grep -v "^\s*//" grep -v "^\s\/\" && exit 1

done
echo "✅ 所有 .st 文件通过保留字检查"


返回非零码即中断构建,强制开发者修正后再提交。

---

### 五、典型误用场景与纠正对照表

| 场景描述 | 错误代码片段 | 风险等级 | 正确方案 |
|----------|--------------|----------|-----------|
| 将 `END` 用作状态标志位 | `END := bCycleComplete;` | ⚠️⚠️⚠️ 高(编译失败) | `bCycleDone := bCycleComplete;` |
| 用 `PROGRAM` 记录当前运行程序号 | `PROGRAM := 3;` | ⚠️⚠️⚠️ 高(语法错误) | `nActiveProgID := 3;` |
| 以 `TIME` 存储毫秒计数值 | `TIME := nMsCounter;` | ⚠️⚠️ 中(类型混淆,可能隐式转换错误) | `nMsCounter := nMsCounter;`(直接用变量名)或 `tElapsedTime := TIME_TO_TOD(TIME());`(若真需时间类型) |
| 在结构体中定义 `IF` 成员 | `TYPE ALARM : STRUCT IF : BOOL; END_STRUCT` | ⚠️⚠️⚠️ 高(结构体解析失败) | `TYPE ALARM : STRUCT bAlarmActive : BOOL; END_STRUCT` |
| 函数参数名为 `FOR` | `MyFunc(FOR := 10)` | ⚠️⚠️ 高(调用语法解析异常) | `MyFunc(nRepeatCount := 10)` |

---

### 六、进阶提醒:保留字与厂商扩展的叠加风险

部分厂商在 IEC 61131-3 基础上添加专属关键字,例如:

- Siemens TIA Portal:`AT`, `AT %MB100`, `RETAIN`, `NON_RETAIN`
- Beckhoff TwinCAT:`PRAGMA`, `FB_INIT`, `FB_EXIT`
- Rockwell Logix:`INIT`, `MAJOR_FAULT`, `MINOR_FAULT`

这些词虽非国际标准保留字,但在对应平台中同样不可用作变量名。务必查阅所用 PLC 厂商的《ST 语言参考手册》附录“Reserved Identifiers”,将其一并纳入白名单。

例如,在 TIA Portal 中使用 `AT` 作为变量名:
```pascal
VAR
    AT : INT; // ❌ 编译报错:"'AT' is a reserved keyword"
END_VAR

应改为 nAnalogThresholdnAtValue


修正后的变量名必须满足三个条件:非保留字、具描述性、符合团队命名规范。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文