Ger*_*ner 7 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
Run Code Online (Sandbox Code Playgroud)
所以我必须将位0设置为在操作模式下设置VFD.然后我需要设置第2位来启动驱动器.
现在我发现了一个问题,其中描述了位操作,我发现这个解决方案应该可行,但我并不理解它.
有人可以解释为什么这有效或不起作用?
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;
}
Run Code Online (Sandbox Code Playgroud)
这确实是一个巧妙的技巧,可以在不分支的情况下进行一些修改。以下解释假设您了解按位运算符的工作原理。
让我们从重新排列表达式开始
(-val ^ command) & (1 << bit_nr)
Run Code Online (Sandbox Code Playgroud)
首先,我们交换-val和command
(command ^ -val) & (1 << bit_nr)
Run Code Online (Sandbox Code Playgroud)
然后应用分配律
(command & (1 << bit_nr)) ^ (-val & (1 << bit_nr))
Run Code Online (Sandbox Code Playgroud)
现在,认识到(假设二进制补码)如果val为 0,-val则为 0(未设置位),如果val为 1,-val则为 -1(设置所有位)
(command & (1 << bit_nr)) ^ (val ? (1 << bit_nr) : 0)
Run Code Online (Sandbox Code Playgroud)
所以赋值可以重写为 if 语句
if (val)
command ^= (command & (1 << bit_nr)) ^ (1 << bit_nr);
else
command ^= command & (1 << bit_nr);
Run Code Online (Sandbox Code Playgroud)
如果val为 1,则位置处的位bit_nr与其否定值进行异或运算,该值始终设置该位。如果val为 0,则该位与其自身进行异或,这始终会清除该位。所有其他位与 0 进行异或,保持不变。
这是一个更易读的无分支版本,它用按位运算换取移位:
uint16_t change_bit(uint16_t command, unsigned int bit_nr, unsigned int val) {
// Always clear the bit.
command &= ~(1u << bit_nr);
// Set the bit if val == 1.
command |= val << bit_nr;
return command;
}
Run Code Online (Sandbox Code Playgroud)