web-dev-qa-db-fra.com

Quelle est la bonne façon de lire un port série en utilisant .NET Framework?

J'ai lu beaucoup de questions ici sur la façon de lire des données de ports série à l'aide de la classe .NET SerialPort, mais aucune des approches recommandées ne s'est révélée totalement efficace pour moi.

Voici le code que j'utilise pour l'instant:

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

Et le gestionnaire d'événements:

void MyDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    int count = port.BytesToRead;
    byte[] ByteArray = new byte[count];
    port.Read(ByteArray, 0, count);
}

Mais il me manque encore parfois des données. J'ai essayé différentes manières de lire les données dans le gestionnaire d'événements, mais sans succès.

Comme .NET 4.5 offre de nouvelles possibilités d'effectuer certaines tâches asynchrones, comme avec la méthode ReadAsync qui semble être utilisable sur un flux SerialPort, je suis curieux de voir quelle serait l'approche recommandée pour gérer ces cas.

30
Yannick Blondeau

Pourriez-vous essayer quelque chose comme ceci, par exemple, je pense que ce que vous voulez utiliser est la méthode port.ReadExisting ()

 using System;
 using System.IO.Ports;

 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 
      SerialPortProgram(); 
    } 

    private static void 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 
        Console.ReadLine();
     } 

    private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
       // Show all the incoming data in the port's buffer
       Console.WriteLine(port.ReadExisting()); 
    } 
}

Ou si vous voulez le faire en fonction de ce que vous essayiez de faire, vous pouvez essayer ceci

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();
        }
  }
22
MethodMan

J'ai utilisé un code similaire à @MethodMan mais je devais garder une trace des données envoyées par le port série et rechercher un caractère de fin pour savoir quand le port série était terminé.

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
user1184321
    using System;
    using System.IO.Ports;
    using System.Threading;

    namespace SerialReadTest
    {
        class SerialRead
        {
            static void Main(string[] args)
            {
        Console.WriteLine("Serial read init");
        SerialPort port = new SerialPort("COM6", 115200, Parity.None, 8, StopBits.One);
        port.Open();
        while(true){
          Console.WriteLine(port.ReadLine());
        }

    }
}
}
1
Vimukthi Sineth