C 设置位(位操作)

标签 c bit-manipulation plc

我正在为一个工业 plc 编程,我必须操作位以与 VFD 进行 profi-bus 通信。我得到一个 2byte 状态并且必须发送 2byte 命令。对于此操作,我必须设置位以使 VFD 运行。例如:

                   Byte n+1           Byte n
PLC    -->  --------------------- ---------------   --> VFD
            15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
            ---------+--------- | | | | -+- | | +- 0: Reglersperre / Freigabe
                     |          | | | |  |  | +--- 1: Freigabe / Schnellstopp
                     |          | | | |  |  +----- 2: Freigabe / Halt
                     |          | | | |  +-------- 3..4: reserviert = 0
                     |          | | | +------------5: Parametersatz-Umschaltung
                     |          | | +------------- 6: Reset
                     |          | +--------------- 7: reserviert = 0
                     |          |
                     |          +----------------- 8: Lüften der Bremse ohne Antreibsfreigabe
                     +---------------------------- 9..15: reserviert = 0

所以我必须设置位 0 以将 VFD 设置为运行模式。然后我需要设置位 2 以启动驱动器。

现在我找到了一个 question其中描述了位操作,我发现这个解决方案应该有效,但我不太明白。

有人可以解释为什么这有效或无效吗?

uint16_t change_bit(uint16_t command, unsigned int bit_nr, unsigned int val) {
  /* command = 2byte command; bit_nr = bit to manipulate;
     val = value bit should get (1;0) */
  command ^= (-val ^ command) & (1U  << bit_nr);
  return command;
}

最佳答案

这似乎行得通,但它非常令人惊讶并且不太清楚。有人认为它“太聪明了”。更清晰的方法可能是:

uint16_t change_bit(uint16_t command, unsigned int bit, bool value)
{
  const uint16_t mask = 1u << bit;
  if(value)
    return command | mask;
  else
    return command & ~mask;
}

其中有一个跳转(if),但聪明的编译器可能会优化它。如果它不是对性能非常关键的代码,那么清晰度通常会更好。

请注意,在进行位级操作时,使用无符号类型通常是个好主意。

关于C 设置位(位操作),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39325931/

相关文章:

c - 我该如何解决这个错误? (未定义对 'display_menu' 的引用)

c - 转换为 long double 的 Void 指针会产生垃圾

c - 优雅地杀死 C 的 pthread 中的阻塞线程?

c - 位移位和奇怪的输出

plc - "MOVE" block 的用途?

我的代码的更正和提示

c++ - 读取位性能

C 程序设计 - XOR 按位运算

java - 用于向 ROCKWELL PLC (1756-A10/A) 读取和写入数据的简单 APP

PLC程序引用软件