我有一个通过rs232读取不同硬件的应用程序。它已经过测试,并且运行良好。对于最终的应用,我需要引入一些hunder m长电缆,这意味着我有rs485转换器。
当我运行我的应用程序来读取硬件时,我收到System.IO.Ports.SerialStream.Read的超时错误。我已将超时增加到20秒,但遗憾的是它没有解决问题
我尝试过不同的应用来读取硬件,即使读取频率为1秒,它们也能正常工作。
通信正在使用modbus协议,我认为这是当前阶段无关紧要,因为我没有到舞台接收任何东西。
我的代码看起来像这样: 首先是串口打开和初始化:
//get the right modbus data structure element
ModBus MB = (ModBus)s[0].sensorData;
//set up the serial port regarding the data structure's data
SerialPort sp = new SerialPort();
sp.PortName = MB.portName;
sp.BaudRate = Convert.ToInt32(MB.baudRate);
sp.DataBits = MB.dataBits;
sp.Parity = MB.parity;
sp.StopBits = MB.stopBits;
//Set time outs 20 sec for now
sp.ReadTimeout = 20000;
sp.WriteTimeout = 20000;
//将端口添加到List,读者可以访问 portList.Add(SP); sp.Open();
阅读硬件:
//get the right port for com
SerialPort sp = getRightPort();
ModBus MB = getRightModBusStructureelement();
try
{
//Clear in/out buffers:
sp.DiscardOutBuffer();
sp.DiscardInBuffer();
//create modbus read message
byte[] message = createReadModBusMessage();
try
{
sp.Write(message, 0, message.Length);
// FM.writeErrorLog output included for easier debug
FM.writeErrorLog(DateTime.Now + ": ModBus Message Sent");
FM.writeErrorLog(DateTime.Now + ": Read TimeOut = " + sp.ReadTimeout + " Write TimeOut = " + sp.WriteTimeout);
int offset = 0, bytesRead;
int bytesExpected = response.Length;
FM.writeErrorLog(DateTime.Now + ": start read");
while (bytesExpected > 0 && (bytesRead = sp.Read(response, offset, bytesExpected)) > 0)
{
FM.writeErrorLog(DateTime.Now + ": read - " + offset);
offset += bytesRead;
bytesExpected -= bytesRead;
}
}
catch (Exception err)
{
Console.WriteLine("ERROR Modbus Message to serial port ModBus: " + err);
FM.writeErrorLog(DateTime.Now + " - " + "ERROR Modbus Message to serial port ModBus: " + err);
}
}
尝试应用程序后,我从ErroLog.txt得到以下输出:
14/01/2016 17:18:17: ModBus Message Sent
14/01/2016 17:18:17: Read TimeOut = 20000 Write TimeOut = 20000
14/01/2016 17:18:18: start read
14/01/2016 17:18:38 - ERROR Modbus Message to serial port ModBus: System.TimeoutException: The operation has timed out.
at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count, Int32 timeout)
at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count)
at System.IO.Ports.SerialPort.Read(Byte[] buffer, Int32 offset, Int32 count)
at ProbReader.SensorReader.modbusReading(List`1 mm, Int32 spCounter)
14/01/2016 17:18:38: 0
14/01/2016 17:18:38: 0
我已将超时时间增加到60秒,以防万一,但错误相同:
15/01/2016 11:11:51: ModBus Message Sent
15/01/2016 11:11:51: Read TimeOut = 60000 Write TimeOut = 60000
15/01/2016 11:11:51: start read
15/01/2016 11:12:51 - ERROR Modbus Message to serial port ModBus: System.TimeoutException: The operation has timed out.
at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count, Int32 timeout)
at System.IO.Ports.SerialStream.Read(Byte[] array, Int32 offset, Int32 count)
at System.IO.Ports.SerialPort.Read(Byte[] buffer, Int32 offset, Int32 count)
at ProbReader.SensorReader.modbusReading(List`1 mm, Int32 spCounter)
15/01/2016 11:12:51: 0
15/01/2016 11:12:51: 0
我尝试了几种不同的方法来读取串口,我认为当前的方法在我的阅读代码中看起来最好是while循环。
我没有包含其余的代码,因为它超时之前,我认为它是无关紧要的。
答案 0 :(得分:5)
如果您使用数百米的串行电缆(这本身就是硬件工程问题),那么我强烈建议在电缆的两端安装合适的收发器。电缆本身应采用EMC屏蔽且质量高。长距离的非屏蔽电缆可能是感应电压波动的受害者,可能会损坏设计不能处理长电缆的设备。
即使使用良好的电缆,您仍然会有相当大的电压降和电感/电容效应,这可能会阻止更高波特率的通信。以最低的波特率运行。
答案 1 :(得分:4)
假设这是一个硬件问题(我想它也是,我必须解决类似的问题),我建议用串口旁边的设备服务器(通过以太网)替换数百米的串行电缆设备。设备服务器可以模拟PC上的COM端口,从而使串行电缆短路。
不幸的是,这些服务器比几米的电缆贵一点..
答案 2 :(得分:3)
请注意,RS232和RS485之间的区别在于RS232是全双工而RS485只是半双工。由于modbus是一种请求响应类型协议,因此这不是您的问题,但了解它非常重要。
由于此,RS232-RS485必须知道何时打开它的RS485发射器。这可以在不同的转换器上以不同方式完成,也可以是可配置的。这可以通过RS232具有但RS485缺少的附加控制线来完成。 RTS / CTS。 如果配置错误,响应方(等待请求响应)发送器可能已打开,然后无法接收任何内容。
手册中的示例是guide 这是瑞典的一种流行模式,有三种操作模式。它可以通过输入数据打开/关闭变送器,由DB9-RS232连接器上的RTS引脚控制,或者始终打开变送器(对于每个方向都有单独电线的RS422) http://ftc.beijer.se/files/C125728B003AF839/992C59EC02C66E00C12579C60051484E/westermo_ug_6617-2203_mdw-45.pdf
这很难,因为一些制造商并没有打印出它的实际工作方式。由于它不清楚DCE和DTE是什么,因此也非常容易错误地接线。
答案 3 :(得分:2)
假设这不是硬件/长电缆问题,您可以在代码中执行某些操作来处理错误:
您需要创建一个“正确”的错误处理程序,就像创建getRightPort
:
SerialPort sp = getRightPort();
假设内部有Collection
个串口项目并且您返回正确的项目,如果此SerialPort
出现错误,请确保重新创建错误SerialPort
object
使用相同的设置:
catch (Exception err)
{
Console.WriteLine("ERROR Modbus Message to serial port ModBus: " + err);
FM.writeErrorLog(DateTime.Now + " - " + "ERROR Modbus Message to serial port ModBus: " + err);
reinitRightPort(sp); //add this
}
方法reinitRightPort();
看起来可能类似于您首次发布的方式,只有很小的差异,如:
List<SerialPort>
SerialPort
,而是从输入参数中获取它。 SerialPort
object
可以使用该端口。这样的事情:
private void reinitRightPort(SerialPort sp){ //get SerialPort from outside of method
//Add whatever necessary here, to close all the current connections
//Plus all the error handlings
if (sp == null) //Read 3.
return;
sp.Close(); //Read 4. close the current connections
//get the right modbus data structure element
ModBus MB = (ModBus)s[0].sensorData;
//set up the serial port regarding the data structure's data
sp = new SerialPort(); //Read 2. sp is from outside the method, but use new keyword still
sp.PortName = MB.portName;
sp.BaudRate = Convert.ToInt32(MB.baudRate);
sp.DataBits = MB.dataBits;
sp.Parity = MB.parity;
sp.StopBits = MB.stopBits;
//Set time outs 20 sec for now
sp.ReadTimeout = 20000;
sp.WriteTimeout = 20000;
//portList.Add(sp); Read 1. no need to add this! It is already there!
sp.Open();
}
注意:执行此操作并确保端口运行良好后,只要有可能,您还可以将上面的reinitRightPort
方法与实际初始化相结合,并进行一些修改。但您可能想要做的第一件事是让您的串口工作正常。
但是如果错误源来自硬件/长电缆问题(例如 电缆放置在RS232或RS485中,或由于长电压下降 电缆或不兼容的硬件:简而言之,与此无关 然后,不幸的是,解决方案不能来自代码 同样。你必须找到真正的硬件问题。
答案 4 :(得分:1)
正如我在我的问题中提到的,我能够使用其他软件读取硬件,因此需要出现软件错误。在调查了我可以在串口设置中操作的所有可能变量后,我想出了转动握手并让它始终被接受的想法。
通过增加写入和读取时间,我可以通过一些挖掘来提供以下代码。它解决了我的问题:
sp.ReadTimeout = 60000;
sp.WriteTimeout = 60000;
sp.DtrEnable = true;
sp.RtsEnable = true;
sp.Handshake = Handshake.None;
我希望将来能帮助其他人,并感谢大家的帮助和努力。