长电缆超时时串行通信超时

Dan*_*iel 14 c# timeout serial-port

我有一个应用程序通过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;
Run Code Online (Sandbox Code Playgroud)

//将端口添加到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);
         }

  }
Run Code Online (Sandbox Code Playgroud)

在尝试应用程序后,我从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
Run Code Online (Sandbox Code Playgroud)

我已将超时增加到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
Run Code Online (Sandbox Code Playgroud)

我尝试了几种不同的方法来读取串口,我认为当前的方法看起来最好,就是我的阅读代码中的while循环.

我没有包含其余的代码,因为它以前超时,我认为这是无关紧要的.

Wos*_*ame 5

如果您使用数百米的串行电缆(这本身就是一个硬件工程问题),那么我强烈建议在电缆的两端安装一个合适的收发器.电缆本身应采用EMC屏蔽且质量高.长距离的非屏蔽电缆可能是感应电压波动的受害者,可能会损坏设计不能处理长电缆的设备.

即使使用良好的电缆,您仍然会有相当大的电压降和电感/电容效应,这可能会阻止更高波特率的通信.以最低的波特率运行,您可以逃脱.


Dan*_*iel 1

正如我在问题中提到的,我能够使用其他软件读取硬件,因此它必须是软件错误。在调查了我可以在串行端口设置中操作的所有可能变量之后,我提出了关闭握手并让它始终被接受的想法。

经过一番挖掘,我得到了以下代码,增加了写入和读取超时。它解决了我的问题:

                            sp.ReadTimeout = 60000;
                            sp.WriteTimeout = 60000;

                            sp.DtrEnable = true;
                            sp.RtsEnable = true;
                            sp.Handshake = Handshake.None;
Run Code Online (Sandbox Code Playgroud)

我希望它将来对其他人有帮助,并感谢大家的帮助和努力。