在结构化文本(ST)编程中,位掩码复位是电气自动化系统里最基础也最关键的底层操作之一。它不依赖任何图形化界面或封装函数,直接作用于寄存器级数据,用于精准清除某一位(bit)的状态,同时确保其余位完全不受影响。这种操作广泛应用于PLC控制逻辑中:比如复位某个故障标志、关闭特定输出通道、清除编码器就绪信号、或解除某台电机的“准备就绪”位。本文将手把手教你写对、用对、验对这条语句:
WordVal := WordVal AND NOT 16#0004;
并彻底讲清它为什么能复位“第3位”,以及你在实际工程中可能踩到的所有坑。
一、先搞懂这句话在干什么:不是“赋值”,而是“位级擦除”
这条语句表面看是赋值,实质是一次按位与(AND)+ 按位取反(NOT) 的组合运算。它不改变 WordVal 的其他15位,只把其中固定的一位强制置为0。关键在于:16#0004 是十六进制数,它对应的二进制是 0000 0000 0000 0100(16位),也就是只有从右往左数的第3位(索引为2)为1,其余全0。
✅ 正确理解位编号规则:
PLC和ST语言中,位编号从0开始计数,最右侧(最低有效位)是第0位。
所以16#0004=2^2=4→ 对应第2位(即常说的“第3位”)。
表格直观对照如下:
| 十六进制 | 二进制(16位) | 对应位号(从0起) | 说明 |
|---|---|---|---|
16#0001 |
0000 0000 0000 0001 |
第0位 | 最低位(LSB) |
16#0002 |
0000 0000 0000 0010 |
第1位 | |
16#0004 |
0000 0000 0000 0100 |
第2位 | 本文目标位(常被口语称“第3位”) |
16#0008 |
0000 0000 0000 1000 |
第3位 | |
16#0010 |
0000 0000 0001 0000 |
第4位 |
注意:“第3位”是日常口语说法;在代码、诊断工具、硬件手册中,务必使用第2位这个标准术语,否则查寄存器映射表会出错。
二、三步拆解执行过程:每一步都可验证
我们以 WordVal 当前值为 16#1237(即十进制 4663)为例,全程演示该语句如何工作:
-
第一步:写出当前值的二进制(16位补全)
16#1237→ 拆成4位一组:1 2 3 7
查十六进制→二进制对照表:
1→0001,2→0010,3→0011,7→0111
合并得:0001 0010 0011 0111 -
第二步:计算掩码
NOT 16#0004
16#0004=0000 0000 0000 0100
对其逐位取反(0变1,1变0):
NOT 0000 0000 0000 0100=1111 1111 1111 1011 -
第三步:执行
AND运算0001 0010 0011 0111 ← WordVal 原值 AND 1111 1111 1111 1011 ← NOT掩码 ------------------- 0001 0010 0011 0011 ← 结果(第2位已变为0)对比原值
...0111和结果...0011:仅第2位由1变0,其余位(第0、1、3…15位)全部保持不变。
最终结果 16#1233(二进制末4位 0011)可直接在PLC变量表中观察验证。
三、为什么不用 WordVal := WordVal XOR 16#0004;?——区别必须分清
初学者常混淆“复位”和“翻转”。这两条语句外观相似,但行为完全不同:
-
WordVal := WordVal AND NOT 16#0004;
→ 强制清零:无论原值第2位是0还是1,结果一定是0。 -
WordVal := WordVal XOR 16#0004;
→ 异或翻转:若原值第2位是1,则变0;若是0,则变1。结果不可控。
✅ 正确场景:
- 故障复位按钮按下时,必须确保故障位归零,不能因误按两次导致“又置1”。
- 安全链断开后,需确定性清除“安全使能”位,而非随机切换。
❌ 错误场景:
- 用
XOR实现复位 → 第二次触发会意外置1,可能重启设备或触发误动作。 - 在紧急停止逻辑中混用 → 违反IEC 61508 SIL2以上功能安全要求。
四、ST中必须遵守的语法细节(错一个字符就报错)
ST对空格、分号、大小写、进制前缀极其敏感。以下写法全部错误:
WordVal := WordVal AND NOT 16#0004(缺结尾分号;)wordval := wordval AND NOT 16#0004;(变量名大小写不一致,ST区分大小写)WordVal := WordVal AND NOT 0x0004;(0x是C语言前缀,ST只认16#)WordVal := WordVal AND NOT 16#0004;;(多一个分号)WordVal := WordVal AND NOT 16#0004 ;(分号前有空格,部分PLC编译器报错)
✅ 正确写法(一字不差):
WordVal := WordVal AND NOT 16#0004;
⚠️ 提示:在TIA Portal、Codesys、GX Works3等主流平台中,
16#必须紧贴数字,中间不能有任何空格;NOT是关键字,前后各需一个空格。
五、批量复位多个位:一次写对,永不改错
要同时复位第2位(16#0004)和第7位(16#0080),只需将掩码相加再取反:
WordVal := WordVal AND NOT (16#0004 + 16#0080);
→ 16#0004 + 16#0080 = 16#0084 → 二进制 0000 0000 1000 0100
→ NOT 16#0084 = 1111 1111 0111 1011
✅ 等价写法(更清晰):
WordVal := WordVal AND NOT (16#0004 OR 16#0080);
因为 OR 在此处与 + 效果相同(两掩码无重叠位),且语义更明确。
❌ 错误写法:
WordVal := WordVal AND NOT 16#0004 AND NOT 16#0080; // 缺括号!编译器解析为 (A AND NOT B) AND NOT C → 逻辑错误
正确必须加括号:
WordVal := WordVal AND NOT (16#0004 OR 16#0080);
六、实战避坑清单(来自十年现场调试经验)
| 风险点 | 现象 | 解决方案 |
|---|---|---|
| 变量类型不匹配 | WordVal 被声明为 INT(16位有符号)→ NOT 16#0004 得 -5,AND 运算结果异常 |
声明为 WORD 或 UINT(无符号16位) |
| 字节序混淆 | 在Modbus通信中,误将 16#0004 当作高位字节处理 |
记住:ST中 WORD 是小端存储,但位操作与字节序无关,无需转换 |
| 在线修改未生效 | 下载程序后变量值不变 | 检查该语句是否在循环主程序(OB1)中执行,且未被 IF FALSE THEN 包裹 |
| 仿真测试误导 | SCL仿真器显示 16#0004 为 4,误以为十进制 |
ST中 16# 开头=十六进制,4 单独出现=十进制,二者绝不等价 |
七、替代方案对比:什么时候该换方法?
| 方法 | 语法示例 | 适用场景 | 缺点 |
|---|---|---|---|
| 位掩码AND NOT | W := W AND NOT 16#0004; |
所有标准场景,推荐首选 | 需记忆掩码值 |
| SET/RESET指令 | MyBit R; |
复位单个布尔量(如 Q0.2) |
无法用于WORD内部位 |
| MOVE指令清零 | MOVE 16#FFFB, WordVal; |
已知掩码固定且频繁使用 | 掩码 16#FFFB 不直观,易写错 |
| 数组索引赋值 | WordArray[2] := FALSE; |
使用ARRAY[0..15] OF BOOL结构化变量 |
内存占用大,非所有PLC支持 |
结论:AND NOT 是通用性、效率、可读性平衡最好的方案。
八、终极验证法:三步确认写对了
- 静态检查:在编辑器中选中
16#0004→ 按快捷键查看其二进制(如TIA Portal按Ctrl+Shift+B),确认是0000 0000 0000 0100; - 动态监视:在PLC在线模式下,将
WordVal和16#0004同时加入变量表,单步执行该行,观察变化是否仅限第2位; - 反向推演:若结果值为
16#1233,手动计算16#1233 OR 16#0004,应严格等于原值16#1237(证明只清除了指定一位)。
九、延伸:用函数块封装,提升复用性(可选进阶)
若项目中需频繁复位不同位,可创建通用函数块 FB_ClearBit:
FUNCTION_BLOCK FB_ClearBit
VAR_INPUT
IN : WORD; // 输入字
BitNo : INT; // 要清零的位号(0~15)
END_VAR
VAR_OUTPUT
OUT : WORD; // 输出字
END_VAR
VAR
Mask : WORD;
END_VAR
// 生成掩码:1左移BitNo位,再取反
Mask := NOT (16#0001 SHL BitNo);
OUT := IN AND Mask;
调用方式:
FB_ClearBit(IN := WordVal, BitNo := 2, OUT => WordVal);
此方案消除硬编码,支持动态位号,且经编译器优化后执行效率与直接写掩码完全一致。
十、最后强调:安全逻辑中的不可妥协原则
在涉及人身安全或重大设备保护的回路中(如急停、光幕、安全门锁):
- 绝不允许用
XOR或MOVE替代AND NOT; - 必须在独立的安全PLC程序块中执行,不得与常规逻辑混合;
- 复位操作必须由硬件按钮的上升沿触发(
P_TRIG),禁止电平保持; - 所有复位语句需通过双通道校验(如主从CPU同步执行并比对结果)。
这些不是“过度设计”,而是IEC 62061 SIL3认证的强制要求。
WordVal := WordVal AND NOT 16#0004; 这一行代码,背后是确定性、可追溯性、可验证性的工程底线。

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