我试图用C#编写一个Modbus
主程序,该程序通过RTU
串行连接将值写入单个从属设备的保持寄存器中。
void SerialTimerTick(object sender, EventArgs e) {
_sp.WriteLine(inputText.ToString());
slaveAddress = (byte)slaveAddressNumericUpDown.Value;
startAddress = (ushort)startAddressNumericUpDown.Value;
registerAddress = (ushort)registerNumericUpDown.Value;
targetRegisterValue = (ushort)targetValueNumericUpDown.Value;
modbusMaster.WriteSingleRegister(slaveAddress, registerAddress, targetRegisterValue);
SerialTimer.Enabled = false;
sendButton.Enabled = true;
}
问题是,当我尝试将写入请求发送到从属服务器时,出现以下错误:
System.TimeoutException:操作已超时。
在程序将这些数字输出到SharpDevelop中的调试控制台三次后发生,表明出现了三项尝试:
要解决此问题,我尝试使用断点来诊断问题,并且看来NModbus希望从属设备发出某种ACKNOWLEDGE
响应,以便确认数据是否正确发送,仅没有给出这样的答复。
当我查看从属设备的通信提要时,发现当主控和从属应用程序都在运行并且我的计算机使用两个USB到串行端口连接到其自身时,在从属设备端发生了 适配器:
Port COM 3 opened.
Port I/O buffers configured.
Port configured 256000,8,N,1
Timeouts configured (100ms/500ms)
Modem status : [CTS_][DSR_RING_]
RX: 0D 0A 0A 06 00 01
RX: 00 01 19 CA
RX: 01 06 00 01 00 01
RX: 19 CA
RX: 01 06 00 01 00 01
相反,我期望的是第一次尝试成功,并且40001寄存器将其值从零更改为一。我尝试更改NModbus版本,尝试弄乱IModbusMaster
对象的超时和尝试设置,还尝试完全删除异常,这似乎是我获得此异常的唯一方法程序可以正常工作,但是就我而言,这不是可接受的解决方案。
到目前为止,我唯一没有尝试过的就是更改我正在使用的从属应用程序,该应用程序目前是免费的PLC
模拟器,它是用C ++而不是C#编写的。这可能是问题的一部分,但我不确定。
我只使用Modbus了几周,并且正在使用NModbus库的较旧版本。任何帮助将不胜感激。
答案 0 :(得分:0)
我还没有使用过NModbus,但是我已经用C ++和C#编写了自己的Modbus“堆栈”,所以这个答案更多的是基于我对Modbus的经验,而不是基于NModbus的工作原理。
广播(从站地址0)时,Modbus命令除EXPT以外应有响应。 Modbus代码发送请求并等待响应应该是正常操作。如果在指定的时间内未收到响应,则可能会发生超时错误。
查看modbus规范;写单个寄存器功能应具有相同的请求和响应ADU(如果成功)。听起来您正在尝试将值1写入从站地址1寄存器1。在这种情况下,两个请求响应ADU均应为“ 01 06 00 01 00 01 19 CA”(“ 19 CA”为此正确的CRC PDU)。我确实看到了来自请求或响应的数据,但是似乎有些干扰:
assets/
仅进行测试,请尝试使用低得多的波特率(9600),并使用偶校验。某些USB到串行转换器的驱动程序参数可以调整。您是否在两个转换器上都启用了终结处理(第一个和最后一个设备都终结了)?是否可以配置NModbus响应超时?