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