You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用net.wimpi.modbus实现ModbusRTU写保持寄存器故障求助

问题排查与修正方案

你的写入代码存在多个关键问题,导致无法完成Modbus RTU寄存器写入操作,具体问题和修正方案如下:

核心问题点

  • 请求初始化错误:使用无参构造WriteMultipleRegistersRequest(),未指定写入的起始寄存器地址和数量,设备无法定位目标寄存器;同时count设为57,和你要写2个寄存器的需求完全不符。
  • 未传入写入数据:代码中完全没有设置要写入寄存器的具体值,设备接收不到有效数据,无法执行写入操作。
  • 冗余且错误的功能码调用:ModbusRequest.createModbusRequest(0x05)是多余操作,0x05是写单个线圈的功能码,和写多个保持寄存器的功能码(0x16)冲突,且WriteMultipleRegistersRequest已内置正确功能码。
  • 未验证写入结果:没有获取写入响应并确认操作是否成功,无法排查设备返回的错误。

修正后的代码

结合你写入当前时间到地址55的2个保持寄存器的需求,修正后的代码如下(示例将时间拆分为两个16位值,可根据设备寄存器定义调整):

public static void WriteRTU(int RegAdr) throws IOException {
    SerialConnection con = null;
    ModbusSerialTransaction trans = null;
    WriteMultipleRegistersRequest Wreq = null;
    WriteMultipleRegistersResponse Wres = null;

    int unitid = 1;
    int ref = RegAdr; // 目标起始寄存器地址(传入55)
    int count = 2; // 要写入的寄存器数量
    int repeat = 1;

    ModbusCoupler.getReference().setUnitID(1);

    SerialParameters params = new SerialParameters();
    params.setPortName(SelectCOM.ComPortBox.getSelectedItem().toString());
    params.setBaudRate(SelectCOM.BaudRateBox.getSelectedItem().toString());
    params.setDatabits(SelectCOM.DataBitBox.getSelectedItem().toString());
    params.setParity(SelectCOM.ParityBox.getSelectedItem().toString());
    params.setStopbits(SelectCOM.StopBitBox.getSelectedItem().toString());
    params.setEncoding("rtu");
    params.setEcho(false);

    con = new SerialConnection(params);
    try {
        con.open();
    } catch (Exception e) {
        e.printStackTrace();
        return; // 连接失败直接终止操作
    }

    // 准备要写入的时间数据(示例拆分逻辑,按需调整)
    Calendar now = Calendar.getInstance();
    int timeSeg1 = now.get(Calendar.MINUTE) * 60 + now.get(Calendar.SECOND);
    int timeSeg2 = now.get(Calendar.HOUR_OF_DAY) * 31 + now.get(Calendar.DAY_OF_MONTH);
    Register[] registers = new Register[count];
    registers[0] = new SimpleRegister(timeSeg1);
    registers[1] = new SimpleRegister(timeSeg2);

    // 正确初始化写入请求:指定起始地址、传入寄存器数组
    Wreq = new WriteMultipleRegistersRequest(ref, registers);
    Wreq.setUnitID(unitid);
    Wreq.setHeadless();

    trans = new ModbusSerialTransaction(con);
    trans.setRequest(Wreq);

    int k = 0;
    do {
        try {
            trans.execute();
            // 获取响应验证写入结果
            Wres = (WriteMultipleRegistersResponse) trans.getResponse();
            if (Wres != null) {
                System.out.println("写入成功:起始地址" + Wres.getReference() + ",写入数量" + Wres.getWordCount());
            }
        } catch (ModbusException e) {
            e.printStackTrace();
            System.out.println("写入失败,错误信息:" + e.getMessage());
        }
        k++;
    } while (k < repeat);

    try {
        con.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

额外说明

  1. 时间值的拆分逻辑需根据你的设备寄存器定义调整,确保数据格式匹配设备要求。
  2. 调用该方法时传入55作为RegAdr,对应目标起始寄存器地址。
  3. 增加了连接失败的终止逻辑和写入结果验证,便于快速定位问题。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 06:36:03