ST怎么写位掩码复位:WordVal := WordVal AND NOT 16#0004; (复第3位)

发布于 2026-03-15 05:47:01 · 浏览 2 次 · 评论 0 条

在结构化文本(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)为例,全程演示该语句如何工作:

  1. 第一步:写出当前值的二进制(16位补全)
    16#1237 → 拆成4位一组:1 2 3 7
    查十六进制→二进制对照表:
    10001200103001170111
    合并得:0001 0010 0011 0111

  2. 第二步:计算掩码 NOT 16#0004
    16#0004 = 0000 0000 0000 0100
    对其逐位取反(0变1,1变0):
    NOT 0000 0000 0000 0100 = 1111 1111 1111 1011

  3. 第三步:执行 AND 运算

    0001 0010 0011 0111   ← WordVal 原值
    AND
    1111 1111 1111 1011   ← NOT掩码
    -------------------
    0001 0010 0011 0011   ← 结果(第2位已变为0)

    对比原值 ...0111 和结果 ...0011:仅第2位由 10,其余位(第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-5AND 运算结果异常 声明为 WORDUINT(无符号16位)
字节序混淆 在Modbus通信中,误将 16#0004 当作高位字节处理 记住:ST中 WORD 是小端存储,但位操作与字节序无关,无需转换
在线修改未生效 下载程序后变量值不变 检查该语句是否在循环主程序(OB1)中执行,且未被 IF FALSE THEN 包裹
仿真测试误导 SCL仿真器显示 16#00044,误以为十进制 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 是通用性、效率、可读性平衡最好的方案。


八、终极验证法:三步确认写对了

  1. 静态检查:在编辑器中选中 16#0004 → 按快捷键查看其二进制(如TIA Portal按 Ctrl+Shift+B),确认是 0000 0000 0000 0100
  2. 动态监视:在PLC在线模式下,将 WordVal16#0004 同时加入变量表,单步执行该行,观察变化是否仅限第2位;
  3. 反向推演:若结果值为 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);

此方案消除硬编码,支持动态位号,且经编译器优化后执行效率与直接写掩码完全一致。


十、最后强调:安全逻辑中的不可妥协原则

在涉及人身安全或重大设备保护的回路中(如急停、光幕、安全门锁):

  • 绝不允许用 XORMOVE 替代 AND NOT
  • 必须在独立的安全PLC程序块中执行,不得与常规逻辑混合;
  • 复位操作必须由硬件按钮的上升沿触发P_TRIG),禁止电平保持;
  • 所有复位语句需通过双通道校验(如主从CPU同步执行并比对结果)。

这些不是“过度设计”,而是IEC 62061 SIL3认证的强制要求。

WordVal := WordVal AND NOT 16#0004; 这一行代码,背后是确定性、可追溯性、可验证性的工程底线。

评论 (0)

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

扫一扫,手机查看

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