我正在为一个工业 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/