如何在 modbus 寄存器中存储有符号的 16 位值

How to store signed 16bit value in pymodbus register

我正在尝试实现一个 pymodbus 服务器。我在 ModbusSlaveContext 中使用 ModbusSparseDataBlocks。到目前为止这有效。客户端可以从每个实例化的寄存器写入和读取值。

但我对负值有疑问。客户需要 16 位有符号整数格式,他无法解释我的负值。

这是我用值填充寄存器的方式:

#write positive value (100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, 100)
#write negative value (-100) to IR[0x10] --> client can't read this, throws failure
context[0x00].setValues(4, 0x10, -100)

如何将有效的 16 位有符号整数写入寄存器?

(我正在使用 python 2.7 和 pymodbus 版本 1.2.0)

我发现下面的方法对我有用,但我不知道这是否是正确和安全的方法。

import struct

def signed(value):
    packval = struct.pack('<h',value)
    return struct.unpack('<H',packval)[0]

#write positive value (100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, signed(100))
#write negative value (-100) to IR[0x10] --> client interprets this correctly
context[0x00].setValues(4, 0x10, signed(-100))

您也可以简单地手动计算:

if value < 0:
    value = 2**16 + value
context[0x00].setValues(4, 0x10, signed(value))

看来您的库只能理解无符号的 16 位数字。如果您 bitwise-AND 在 Python 中使用 0xFFFF(16 位掩码)的有符号值,您将得到相同的结果:

你在做什么:

>>> import struct
>>> struct.unpack('<H',struct.pack('<h',-100))[0]
65436

Bitwise-AND:

>>> -100 & 0xFFFF
65436

所以你可以这样做:

context[0x00].setValues(4, 0x10, -100 & 0xFFFF)

正值不受影响,负值产生无符号 16 位 2 的补码值。

要将无符号 2 的补码 16 位值转换回有符号,测试符号位 (215) 并减去 216 如果存在:

value = value-2**16 if value & 2**15 else value

或等同于:

value = value-0x10000 if value & 0x8000 else value