使用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(); } }
额外说明
- 时间值的拆分逻辑需根据你的设备寄存器定义调整,确保数据格式匹配设备要求。
- 调用该方法时传入
55作为RegAdr,对应目标起始寄存器地址。 - 增加了连接失败的终止逻辑和写入结果验证,便于快速定位问题。
内容的提问来源于stack exchange,提问作者Capitan Latinamerica
相关产品推荐
相关产品推荐

