You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将Modbus-tk RTU Slave保持寄存器设为读取有符号整数

解决modbus-tk Slave设置为有符号整数的问题

刚好之前折腾过modbus-tk的Slave符号类型问题,你的情况我太懂了——-999的16位补码被当成无符号解析成64537,本质就是Slave默认按无符号整数处理寄存器数据,咱们只需要调整下数据类型的配置就行,分两种方法:

方法1:直接在寄存器定义时指定有符号类型

这是最省心的方式,modbus-tk本身提供了内置的有符号类型常量。你在给Slave添加寄存器区块的时候,加上data_type参数指定为cst.INT(16位有符号整数)就行,示例代码如下:

import modbus_tk
import modbus_tk.defines as cst
from modbus_tk import modbus_rtu

# 初始化RTU Slave(根据你的实际串口参数调整)
slave = modbus_rtu.RtuSlave(port="COM3", baudrate=9600, parity='N', data_bits=8, stop_bits=1)
slave.start()

# 添加保持寄存器区块,指定data_type为有符号整数
# 参数分别是:区块名、寄存器类型、起始地址、寄存器数量、数据类型
slave.add_block('holding_regs', cst.HOLDING_REGISTERS, 0, 10, data_type=cst.INT)

# 直接写入有符号整数-999到起始地址0
slave.set_values('holding_regs', 0, [-999])

这里的cst.INT对应16位有符号,还有cst.LONG(32位有符号)、cst.UINT(默认的无符号16位)等类型可选,按需使用即可。

方法2:手动做补码转换(兼容旧代码场景)

如果你的代码已经写得差不多了,不想改寄存器的定义,也可以手动把有符号数转成16位补码(无符号形式)写入,读取时再转回来:

# 把16位有符号整数转成无符号补码
def signed_to_unsigned_16(value):
    return value & 0xFFFF  # 这个写法比判断正负更简洁,自动处理补码

# 写入-999
slave.set_values('holding_regs', 0, [signed_to_unsigned_16(-999)])

# 读取时把无符号转成有符号
def unsigned_to_signed_16(value):
    return (value ^ 0x8000) - 0x8000  # 同样是简洁的补码转换方式

read_val = slave.get_values('holding_regs', 0, 1)[0]
signed_val = unsigned_to_signed_16(read_val)

别忘了主站的设置!

光改Slave还不够,你用的Simply Modbus Master软件也要对应设置数据类型——读取的时候选择Signed 16-bit Integer,这样软件才会把收到的十六进制值按有符号解析,显示正确的-999。

另外你提到官方示例只有Master的,其实modbus-tk仓库里有Slave的示例(比如rtuslave_example.py),核心逻辑就是通过add_blockdata_type参数控制符号,和上面的方法1一致。

内容的提问来源于stack exchange,提问作者Yang

火山引擎 最新活动