2016-09-22 67 views
0

这是我的代码C#串口接收挂起后数据

public void ClosePort() 
    { 
     if (comPort.IsOpen == true) 
     { 
      Thread CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang 

      CloseDown.Start(); //close port in new thread to avoid hang 
     } 
    } 

    private void CloseSerialOnExit(SerialPort port) 
    { 
     port.DiscardOutBuffer(); 
     port.Close(); 

     DisplayData(MessageType.Error, "Port communication has been closed" + " " + DateTime.Now + "\n"); 
    } 

为什么当我的应用程序收到了近是不行的数据?这是另一种解决方案吗?我的工作步骤是:

  1. 连接端口,
  2. 扫描和接收数据,
  3. 断开连接端口,并重复连接端口重新开始,但是当我们要开始连接端口,系统显示错误信息:

接入端口被拒绝。

我发生这种情况,因为港口实际上并没有关闭。如何关闭端口?

这是我在打开端口的代码

public bool OpenPort() 
    { 
     try 
     { 
      //first check if the port is already open 
      //if its open then close it 
      if (comPort.IsOpen == true) comPort.Close(); 

      //set the properties of our SerialPort Object 
      comPort.BaudRate = int.Parse(_baudRate); //BaudRate 
      comPort.DataBits = int.Parse(_dataBits); //DataBits 
      comPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), _stopBits); //StopBits 
      comPort.Parity = (Parity)Enum.Parse(typeof(Parity), _parity); //Parity 
      comPort.Handshake = (Handshake)Enum.Parse(typeof(Handshake), _parity); //Parity     
      comPort.PortName = _portName; //PortName 
      //now open the port 
      comPort.WriteTimeout = 400;//Write timeout, if the efficiency of the serial driver software, can effectively avoid the deadlock 
      comPort.ReadTimeout = 400;//Read timeout, ibid 
      comPort.Open(); 
      comPort.DtrEnable = false; 
      comPort.RtsEnable = false; 
      //display message 
      DisplayData(MessageType.Normal, "Port opened at " + DateTime.Now + "\n"); 
      //return true 
      return true; 
     } 
     catch (Exception ex) 
     { 
      DisplayData(MessageType.Error, ex.Message); 
      return false; 
     } 
    } 

这是我在comPort_datareceived代码

void comPort_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
      //determine the mode the user selected (binary/string) 
      switch (CurrentTransmissionType) 
      { 
       //user chose string 
       case TransmissionType.Text: 
        //read data waiting in the buffer 
        string msg = comPort.ReadExisting(); 
        //display the data to the user 
        DisplayData(MessageType.Incoming, msg + "\n"); 
        break; 
       //user chose binary 
       case TransmissionType.Hex: 
        //retrieve number of bytes in the buffer 
        int OpeCode = 0; 
        int RequestID = 0; 
        int Product = 0; 
        int IPenNo = 0; 
        string status = " "; 

        while (true) 
        { 
         DateTime time = DateTime.Now;    // Use current time. 
         string format = "dddddddd, MMMMM d, yyyy HH:mm:ss"; 
         string currentTime = time.ToString(format); 
         byte[] TrueData = new byte[256]; 

         try 
         { 
          int bytes = comPort.BytesToRead; 
          if (bytes == 0) continue; 
          //create a byte array to hold the awaiting data 
          byte[] comBuffer = new byte[bytes]; 
          comPort.Read(comBuffer, 0, bytes); 
          DisplayData(MessageType.Incoming, "Hexa :" + ByteToHex(comBuffer) + "\n"); 
          DisplayData(MessageType.Incoming, "Byte :" + bytes.ToString() + "\n"); 

          if (bytes == 3) 
          { 
           var lines = File.ReadAllLines(Fullpath).ToList(); 

           // Remove as many lines as you'd like from the end 
           if (lines.Count > 2) 
           { 
            lines.RemoveRange(lines.Count - 2, 2); 
           } 

           // Iterate backwards through the list until we've updated 2 (or more or less) lines 
           var linesUpdated = 0; 

           for (var i = lines.Count - 1; i >= 0 && linesUpdated < 1; i--) 
           { 
            if (lines[i].Contains("OK")) 
            { 
             lines[i] = lines[i].Replace("OK", "NG"); 
             linesUpdated++; 
            } 
           } 

           File.WriteAllLines(Fullpath, lines.ToArray()); 
           //DisplayData(MessageType.Incoming, "NG" + "\n"); 
          } 

          if (bytes == 2) 
          { 
           continue; 
          } 

          int etx_ok = 0; 

          for (int i = 0; i < bytes; i++) 
          { 
           if (comBuffer[i] == 0x02) 
           { 
            //DisplayData(MessageType.Incoming, "cek II:" + checkStatus + "\n"); 
            int length = comBuffer[i + 1]; 
            DisplayData(MessageType.Incoming, "Length=" + length.ToString() + "\n"); 

            if (String.IsNullOrEmpty(bytes.ToString())) 
            { 
             status = "NG"; 
            } 
            if (length + i + 1 != bytes && status == " ") 
            { 
             DisplayData(MessageType.Incoming, length.ToString() + " " + i.ToString() + " " + bytes.ToString() + " "); 
             status = "NG"; 
             DisplayData(MessageType.Incoming, "ERROR \n"); 
             //break; 
            } 
            else 
            { 
             status = "OK"; 
            } 

            DisplayData(MessageType.Incoming, "ini statusnya : " + status + "\n"); 

            if (comBuffer[length + i - 1] == 0x03) 
            { 
             DisplayData(MessageType.Incoming, "ETX OK\n"); 
             etx_ok = 1; 
             OpeCode = comBuffer[i + 2]; 
             DisplayData(MessageType.Incoming, "OpeCode=" + OpeCode.ToString() + ","); 
             RequestID = comBuffer[i + 3]; 
             DisplayData(MessageType.Incoming, "RequestID=" + RequestID.ToString() + ","); 
             int StoreCode = comBuffer[i + 4]; 
             DisplayData(MessageType.Incoming, "StoreCode=" + StoreCode.ToString() + ","); 
             int ProductBatteryTraining = comBuffer[i + 5]; 
             DisplayData(MessageType.Incoming, "ProductBatteryTraining=" + ProductBatteryTraining.ToString() + ","); 

             Product = ProductBatteryTraining >> 4; 
             DisplayData(MessageType.Incoming, " Product=" + Product.ToString() + ","); 
             int Battery = ProductBatteryTraining & 4; 
             DisplayData(MessageType.Incoming, " Batery=" + Battery.ToString() + ","); 
             int Training = ProductBatteryTraining & 1; 
             DisplayData(MessageType.Incoming, " Training=" + Training.ToString() + ","); 

             IPenNo = comBuffer[i + 6]; 
             DisplayData(MessageType.Incoming, "IPenNo=" + IPenNo.ToString() + ","); 

             int CrcCalc = comBuffer[length + i] + 0x11; 

             for (int j = 7, k = 0; j < length; j++, k++) 
             { 
              //syswrite STDOUT , "TrueDataX " . $length . "\n"; 
              DisplayData(MessageType.Incoming, "TrueDataX " + length.ToString() + "," + "\n"); 
              TrueData[k] = comBuffer[i + j]; 
             } 
             if (OpeCode == 0x63) 
             { 
              byte[] replyStr = new byte[] { 
             Convert.ToByte(0x45), Convert.ToByte(0x53), Convert.ToByte(0x4c), Convert.ToByte(0x14), Convert.ToByte(0x09), Convert.ToByte(0x00),        //#Length Change 
             Convert.ToByte(0x02), Convert.ToByte(0x08),Convert.ToByte(OpeCode), Convert.ToByte(RequestID),Convert.ToByte(Product-1), Convert.ToByte(IPenNo),          //#Reply Header Data     
             Convert.ToByte(0x00),                                   //#Reply Status  
             Convert.ToByte(0x03), Convert.ToByte(CrcCalc),                              //#Footer Data  
             Convert.ToByte(0xcc), Convert.ToByte(0xcc) 
             }; 

              comPort.Write(replyStr, 0, replyStr.Length); 

              //write file to textfile 
              //string path = @"d:\yosafat\testfile\tes1_Friday0916201614.33.txt"; 
              string IPenID = IPenNo.ToString(); 
              string appendText = ("IPen ID \t" + "Datetime\t\t\t\t\t" + "Status" + Environment.NewLine + IPenID + "\t\t" + currentTime + "\t\t" + status + Environment.NewLine); 
              File.AppendAllText(Fullpath, appendText); 
             } 
            } 
            else 
            { 
             OpeCode = 0; 
             //syswrite STDOUT , "ETX Bad Data" . $length . "\n"; 
             DisplayData(MessageType.Incoming, "ETX Bad Data" + length.ToString() + "\n"); 
             break; 
            } 
           } 
           if (etx_ok == 1) 
           { 
            break; 
           } 
          } 
         } 
         catch (Exception) { } 
        } 
      } 
     } 
    public static int GetFirstOccurance(byte byteToFind, byte[] byteArray) 
    { 
     return Array.IndexOf(byteArray, byteToFind); 
    } 
+0

'Close'和'Open'之间的时间间隔有多长?为什么你需要重复打开/关闭?我最好让端口保持打开状态。 – putu

+0

@IPutuSusila是的,我必须关闭端口,因为接收到的数据将保存到文本文件,当点击按钮断开将结束扫描和接收数据。 – yosafat

+0

当然,您需要关闭时,即通过断开按钮。那么,你的意思是,在你点击断开连接按钮后,当你点击连接时,错误会上升?你能告诉我们连接/打开串口的代码吗? – putu

回答

1

添加returncatchSerialPort.DataReceived事件处理程序,从while循环的情况下,exception发生退出。

while (true) 
{ 
    //... 
    try { 
     //... 
    } catch (Exception) { return; //add this} 
} 

其他线程Close端口后,读取数据(:comPort.Read(comBuffer, 0, bytes);此行)时,会发生Exception可能。如果没有return声明,您将永远不会退出while循环,GC将不会处理SerialPort。因此,当您尝试重新打开端口时,您将失败。

+0

非常感谢!这是我完全需要的。 – yosafat

1

为什么你在一个单独的线程中调用CloseSerialOnExit?同步调用它不是更容易吗?它真的需要很长时间吗?

无论如何,如果你需要它,你应该确保在线程完成之前Thread对象没有被GC'ed。你应该使CloseDown成为一个成员。

您也可以使用一些同步来查看ClosePort是否已在OpenPort的开始处结束。

Thread CloseDown = null; 
public void ClosePort() 
{ 
    if (comPort.IsOpen == true) 
    { 
     CloseDown = new Thread(() => CloseSerialOnExit(comPort)); //close port in new thread to avoid hang 
     CloseDown.Start(); //close port in new thread to avoid hang 
    } 
}