C# - 通过串口对设备进行轮询

问题描述 投票:2回答:1

面临一个问题。我需要使用Modbus协议通过串口轮询设备。

但是轮询设备需要很长的时间--大约2秒。

的确,我的程序还另外在一个单独的线程中不断地轮询设备,但我希望它更快。

也许有人能帮助我如何优化我的代码。我将非常感激。

public override RcResult ExecuteModBus(RcModBusDevice device, byte[] request, out byte[] answer)
    {
        answer = null;
        var result = new RcResult();
        OnLogMessage?.Invoke(this, "ExecuteModBus LOCK?");
        lock (communication)
        {
            OnLogMessage?.Invoke(this, "ExecuteModBus LOCK!");
            var dt = DateTime.Now;
            if (device != null)
            {
                serialPort.WriteTimeout = device.SendTimeout;
                serialPort.ReadTimeout = device.ReceiveTimeout;
            }
            serialPort.DiscardOutBuffer();
            serialPort.DiscardInBuffer();

            OnLogMessage?.Invoke(this, "REQUEST->:" + Utils.BytesToHex(request));
            try
            {
                serialPort.Write(request, 0, request.Length);
            }
            catch(Exception ex)
            {
                result.ErrorCode = 1;
                result.ErrorText = ex.Message;
                return result;
            }
            var tmp = new byte[0x2000];
            int dataLength = 0;
            try
            {
                for (int i = 0; i < tmp.Length; i++)
                    tmp[dataLength++] = (byte)serialPort.ReadByte();
            }
            catch (Exception ex)
            {
            }

            var crc = Utils.GetCRC(tmp, 0, dataLength - 2);
            if (crc[0] != tmp[dataLength - 2] || crc[1] != tmp[dataLength - 1])
            {
                result.ErrorCode = 1;
                result.ErrorText = "Bad CRC";
            }
            answer = new byte[dataLength];
            Array.Copy(tmp, 0, answer, 0, dataLength);
            OnLogMessage?.Invoke(this, "ANSWER<-:" + Utils.BytesToHex(answer));
            if (device != null)
                SaveToLog(DbID, device.DbID, dt, Utils.BytesToHex(request), DateTime.Now, Utils.BytesToHex(answer));
            if (dataLength == 0)
                result.ErrorCode = 1;
        }
        OnLogMessage?.Invoke(this, "ExecuteModBus UNLOCK");
        return result;
    }
c# optimization serial-port modbus
1个回答
2
投票

我在另一个论坛上找到了答案.错误是端口的读取超时。

var tmp = new byte[0x2000];
int dataLength = 0;
try
{
   while(true)
   {
      byte receiveByte= (byte)serialPort.ReadByte();

      // We received one byte. Check buffer size
      if (dataLength >= tmp.Length) 
      {
         // Buffer to small
         result.ErrorCode = 1; // Appropriate ErrorCode
         result.ErrorText = "Buffer Overrun";
         return result;
      }

      // Add it to receive buffer
      tmp[dataLength++] = receiveByte;

      // Set character Timeout after we received the first byte of the answer
      if (dataLength == 1)
      {
         // Set new character timeout according to Modbus spec.
         // At least 3.5 characters silence but here we take about 
         // 5 times more chars to be on the safe side
         //
         //                   10Bit/Byte     mS      ca. 5x3.5
         serialPort.ReadTimeout= (10    *   1000   *   18)      /   serialPort.Baudrate; 
      }

      // Don't eat CPU too aggressive (has to be proofed whether it really helps)
      Thread.Sleep(0);
   }
}
catch (TimeoutException ex)
{
   // Expected exception. No more character received in the specified
   // character timeout period
}
catch (Exception ex)
{
   // Other than (TimeoutException is an error condition
   result.ErrorCode = 1; // Appropriate ErrorCode
   result.ErrorText = ex.Message;
   return result;
}
© www.soinside.com 2019 - 2024. All rights reserved.