ST怎么写位掩码置位:WordVal := WordVal OR 16#0004; (置第3位)

发布于 2026-03-15 05:37:15 · 浏览 3 次 · 评论 0 条

在结构化文本(ST)编程中,对字(Word)类型变量的某一位进行置位(Set Bit),是电气自动化控制中最基础、最频繁的操作之一。它常用于启动特定功能模块、激活安全联锁、标记设备状态(如“已初始化”“急停触发”“通讯就绪”)等场景。本指南不依赖图形界面演示,仅通过纯文字与标准IEC 61131-3语法,手把手教你精准、可靠、可复用地实现“置第3位”操作,并延伸至任意位、多位置位、清零、翻转、判断等完整位操作体系。


一、先明确:什么是“第3位”?——位序编号规则必须统一

在PLC位操作中,“第3位”的说法极易引发歧义。关键在于确认位编号从0开始还是从1开始,以及字节内高位在左还是在右。IEC 61131-3 标准明确规定:

  • 所有整数类型(WORDDWORDINT 等)的位编号从0开始计数
  • 最低有效位(LSB)为第0位,即最右边一位;
  • WORD 是16位无符号整数,位号范围为 015,从右到左依次排列;

因此:

  • 第0位 → 2^0 = 1 → 十六进制 16#0001
  • 第1位 → 2^1 = 2 → 十六进制 16#0002
  • 第2位 → 2^2 = 4 → 十六进制 16#0004
  • 第3位 → 2^3 = 8 → 十六进制 16#0008

⚠️ 注意:题目中“置第3位”实际对应的是位编号为2的位(即第2位),因为“第1位”是位0,“第2位”是位1,“第3位”是位2。这是行业通用表述(类似“第1个元素下标为0”),但初学者极易误认为“第3位=位3”。本指南严格按 IEC 标准采用 位编号(bit number) 描述,避免歧义。

结论:WordVal := WordVal OR 16#0004; 的作用是 置位 WordVal 的第2位(bit 2),而非第3位。若需真正置位“第3位”(即位编号为3),应使用 16#0008


二、核心原理:为什么用 OR?——布尔代数不可替代

位运算的本质是逐位逻辑操作。OR(或运算)具备唯一不可替代的特性:任何位与 1 进行 OR 运算,结果恒为 1;与 0 进行 OR 运算,结果保持原值

设掩码 Mask = 16#0004(即二进制 0000 0000 0000 0100),其仅在 bit 2 处为 1,其余位全 0

对任意 WordVal 执行 WordVal OR Mask

  • bit 2:WordVal[2] OR 1 → 1(强制置位)
  • 其他位(bit 0,1,3…15):WordVal[i] OR 0 → WordVal[i](保持不变)

该操作不影响其他位状态,是安全、原子的置位方式。绝不可用 +(加法)替代,例如 WordVal := WordVal + 4; 在 bit 2 原为 1 时会引发进位,错误修改更高位(如 16#0004 + 4 = 16#0008),彻底破坏数据。


三、ST代码实操:4种写法,按需选用

以下所有写法均符合 IEC 61131-3 ST 语法,可在 Codesys、TIA Portal(SCL)、Unity Pro、KW Studio 等主流平台直接编译运行。

1. 直接十六进制掩码(最常用、最清晰)

WordVal := WordVal OR 16#0004; // 置 bit 2(习惯称“第3位”)

2. 使用 SHL(左移)动态生成掩码(适合变量位号)

bitPos : INT := 2; // 要置的位编号
Mask : WORD := SHL(1, bitPos); // 1 左移 2 位 → 16#0004
WordVal := WordVal OR Mask;

3. 使用 POW(幂函数)——不推荐,效率低且易出错

// ❌ 错误:POW 返回 REAL,不能直接赋给 WORD
// WordVal := WordVal OR WORD(POW(2.0, 2.0)); 

// ✅ 正确(但冗余):
WordVal := WordVal OR WORD(EXPT(2, 2)); // EXPT 是整数幂函数(部分平台支持)

注:EXPT 非所有平台内置,POW 返回浮点数需显式转换,且存在精度风险,强烈建议用 SHL 替代

4. 封装为可重用函数块(FB)

FUNCTION_BLOCK SetBit
VAR_INPUT
    IN      : WORD;   // 输入字
    BitNum  : INT;    // 要置的位编号(0~15)
END_VAR
VAR_OUTPUT
    OUT     : WORD;   // 输出字
END_VAR
VAR
    Mask : WORD;
END_VAR

Mask := SHL(1, BitNum);
OUT := IN OR Mask;

调用方式:

WordVal := SetBit(IN:=WordVal, BitNum:=2).OUT;

四、完整位操作速查表:一套指令覆盖全部需求

操作 ST 语句示例 说明
置位(Set) WordVal := WordVal OR 16#0004; 置 bit 2,其他位不变
清零(Reset) WordVal := WordVal AND NOT 16#0004; NOT 16#0004 = 16#FFFB,bit 2 强制为 0,其余不变
翻转(Toggle) WordVal := WordVal XOR 16#0004; XOR 同值为 0,异值为 1 → bit 2 取反,其余不变
读取(Test) BitState : BOOL := (WordVal AND 16#0004) <> 0; 若结果非零,则 bit 2 为 1;否则为 0
批量置位 WordVal := WordVal OR 16#000F; 置 bit 0~3(16#000F = 0000 0000 0000 1111
批量清零 WordVal := WordVal AND 16#FFF0; 清 bit 0~3(16#FFF0 = 1111 1111 1111 0000

✅ 关键细节:

  • NOT 运算符对 WORD 执行按位取反NOT 16#0004 = 16#FFFB(16位补码);
  • AND NOT Mask 是清零的标准写法,不可写作 AND !Mask! 是BOOL逻辑非,不适用WORD)
  • XOR Mask 是翻转唯一安全方式,比 IF...THEN...ELSE... 更高效、更原子。

五、典型应用场景与陷阱规避

场景1:启动信号双确认(防误触发)

// 仅当 Start_PB(启动按钮)和 Safety_OK(安全回路)同时为1时,才置位启动标志 bit 0
IF Start_PB AND Safety_OK THEN
    MotorCmd := MotorCmd OR 16#0001; // 置 bit 0(启动命令)
END_IF

场景2:故障代码叠加(多故障共存)

// 故障寄存器 FaultCode 是 WORD 类型
IF TempHigh THEN
    FaultCode := FaultCode OR 16#0001; // bit 0 = 温度过高
END_IF
IF PressureLow THEN
    FaultCode := FaultCode OR 16#0002; // bit 1 = 压力过低
END_IF
// 故障可同时存在,bit 0 和 bit 1 均为1 → FaultCode = 16#0003

⚠️ 高危陷阱:

  • 误用 = 赋值覆盖全字WordVal := 16#0004; 会清空所有其他位,不是“置位”而是“赋值”;
  • 位号越界SHL(1, 16) 在16位WORD中导致未定义行为(可能截断为 0 或溢出),务必确保 BitNum0..15
  • 未初始化变量WordVal 若未声明初始值,在某些平台可能为随机数,首次 OR 前应先初始化为 0
  • 符号类型误用INT 也是16位,但最高位为符号位。对 INT 使用 OR 16#8000 可能触发负数,位操作一律使用无符号类型 WORD/DWORD

六、调试技巧:如何验证位操作是否生效?

无需硬件,纯软件验证:

  1. 在在线监控窗口中,将 WordVal 变量显示格式切换为 二进制(BIN)
  2. 观察执行 OR 16#0004 后,第2位(从右数第3位)是否由 0 变为 1
  3. 或切换为 十六进制(HEX):若原值为 16#0000,执行后应为 16#0004;若原值为 16#000A(二进制 1010),执行后仍为 16#000A(bit 2 原已是 1OR 不改变)。

七、进阶:扩展至 DWORD(32位)与数组批量操作

DWORD 是32位,位号范围 0..31,掩码写法一致:

DWordVal := DWordVal OR 16#00000004; // 置 DWORD 的 bit 2
DWordVal := DWordVal OR SHL(16#00000001, 16); // 置 bit 16(即第17位)

对字数组批量置位(如控制16个阀门):

FOR i := 0 TO 15 DO
    Valves[i] := Valves[i] OR 16#0004; // 所有阀门统一置 bit 2(例如“校准完成”标志)
END_FOR

WordVal := WordVal OR 16#0004; 这一行代码背后,是位操作的确定性、高效性与工业级鲁棒性的集中体现。掌握它,就握住了电气自动化底层控制的钥匙。

评论 (0)

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

扫一扫,手机查看

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