Qual é a maneira correta de ler uma porta série using.NET framework?

Li muitas perguntas sobre como ler dados de portas seriais usando a classe. net SerialPort, mas nenhuma das abordagens recommanded provou ser completamente eficiente para mim.

Aqui está o código que estou a usar por agora:

SerialPort port = new SerialPort("COM1");
port.DataReceived += new SerialDataReceivedEventHandler(MyDataReceivedHandler);

e o manipulador de Eventos:

void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    int count = port.BytesToRead;
    byte[] ByteArray = new byte[count];
    port.Read(ByteArray, 0, count);
}
Mas às vezes ainda me faltam alguns dados. Tentei uma maneira diferente de ler os dados no manipulador de eventos, mas sem sorte.

Como a. NET 4.5 traz novas possibilidades para fazer alguns tarefas assíncronas, como com o método ReadAsync que parece ser utilizável em um fluxo SerialPort, estou curioso para ver qual seria a abordagem recomendada para lidar com esses casos.

Author: Yannick Blondeau, 2012-12-07

2 answers

Você poderia tentar algo assim, por exemplo, eu acho que o que você está querendo utilizar é a porta .ReadExisting () Method

 class SerialPortProgram 
 { 
  // Create the serial port with basic settings 
    private SerialPort port = new   SerialPort("COM1",
      9600, Parity.None, 8, StopBits.One); 
    [STAThread] 
    static void Main(string[] args) 
    { 
      // Instatiate this 
      class new SerialPortProgram(); 
    } 

    private SerialPortProgram() 
    { 
        Console.WriteLine("Incoming Data:");
         // Attach a method to be called when there
         // is data waiting in the port's buffer 
        port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); 
        // Begin communications 
        port.Open(); 
        // Enter an application loop to keep this thread alive 
        Application.Run(); 
     } 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
       // Show all the incoming data in the port's buffer
       Console.WriteLine(port.ReadExisting()); 
    } 
}
Ou queres fazê-lo com base no que estavas a tentar fazer , podes tentar isto.
public class MySerialReader : IDisposable
{
  private SerialPort serialPort;
  private Queue<byte> recievedData = new Queue<byte>();

  public MySerialReader()
  {
    serialPort = new SerialPort();
    serialPort.Open();
    serialPort.DataReceived += serialPort_DataReceived;
  }

  void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e)
  {
    byte[] data = new byte[serialPort.BytesToRead];
    serialPort.Read(data, 0, data.Length);
    data.ToList().ForEach(b => recievedData.Enqueue(b));
    processData();
  }

  void processData()
  {
    // Determine if we have a "packet" in the queue
    if (recievedData.Count > 50)
    {
        var packet = Enumerable.Range(0, 50).Select(i => recievedData.Dequeue());
    }
  }

  public void Dispose()
  {
        if (serialPort != null)
        {
            serialPort.Dispose();
        }
  }
 15
Author: MethodMan, 2012-12-07 00:38:44

Usei um código semelhante ao @MethodMan, mas tive de acompanhar os dados que a porta série estava a enviar e procurar um carácter de terminação para saber quando a porta série acabou de enviar os dados.

private string buffer { get; set; }
private SerialPort _port { get; set; }

public Port() 
{
    _port = new SerialPort();
    _port.DataReceived += new SerialDataReceivedEventHandler(dataReceived);
    buffer = string.Empty;
}

private void dataReceived(object sender, SerialDataReceivedEventArgs e)
{    
    buffer += _port.ReadExisting();

    //test for termination character in buffer
    if (buffer.Contains("\r\n"))
    {
        //run code on data received from serial port
    }
}
 4
Author: , 2016-01-06 21:28:28