在结构化文本(ST)编程中,对字(Word)类型变量的某一位进行置位(Set Bit),是电气自动化控制中最基础、最频繁的操作之一。它常用于启动特定功能模块、激活安全联锁、标记设备状态(如“已初始化”“急停触发”“通讯就绪”)等场景。本指南不依赖图形界面演示,仅通过纯文字与标准IEC 61131-3语法,手把手教你精准、可靠、可复用地实现“置第3位”操作,并延伸至任意位、多位置位、清零、翻转、判断等完整位操作体系。
一、先明确:什么是“第3位”?——位序编号规则必须统一
在PLC位操作中,“第3位”的说法极易引发歧义。关键在于确认位编号从0开始还是从1开始,以及字节内高位在左还是在右。IEC 61131-3 标准明确规定:
- 所有整数类型(
WORD、DWORD、INT等)的位编号从0开始计数; - 最低有效位(LSB)为第0位,即最右边一位;
WORD是16位无符号整数,位号范围为0至15,从右到左依次排列;
因此:
- 第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或溢出),务必确保BitNum在0..15; - 未初始化变量:
WordVal若未声明初始值,在某些平台可能为随机数,首次OR前应先初始化为0; - 符号类型误用:
INT也是16位,但最高位为符号位。对INT使用OR 16#8000可能触发负数,位操作一律使用无符号类型WORD/DWORD。
六、调试技巧:如何验证位操作是否生效?
无需硬件,纯软件验证:
- 在在线监控窗口中,将
WordVal变量显示格式切换为 二进制(BIN); - 观察执行
OR 16#0004后,第2位(从右数第3位)是否由0变为1; - 或切换为 十六进制(HEX):若原值为
16#0000,执行后应为16#0004;若原值为16#000A(二进制1010),执行后仍为16#000A(bit 2 原已是1,OR不改变)。
七、进阶:扩展至 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; 这一行代码背后,是位操作的确定性、高效性与工业级鲁棒性的集中体现。掌握它,就握住了电气自动化底层控制的钥匙。

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