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



我正在尝试实现一个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)

看起来您的库只能识别无符号的 16 位数字。 如果在 Python 中使用带有 0xFFFF(16 位掩码)的有符号值按位 AND,您将获得相同的结果:

你在做什么:

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

按位-和:

>>> -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

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

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))

最新更新