Quelle est la bonne façon de lire un port série using.NET cadre?

J'ai lu beaucoup de questions ici sur la façon de lire les données des ports série en utilisant la classe. net SerialPort, mais aucune des approches recommandées ne s'est révélée complètement efficace pour moi.

Voici le code que j'utilise pour maintenant:

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 des données parfois. J'ai essayé une manière différente de lire les données dans le gestionnaire d'événements mais sans chance.

Comme le. net 4.5 apporte de nouvelles possibilités pour en faire tâches asynchrones, comme avec la méthode ReadAsync qui semble utilisable sur un flux SerialPort, je suis curieux de voir quelle serait l'approche recommandée pour gérer ces cas.

23
demandé sur Yannick Blondeau 2012-12-07 03:45:44

2 réponses

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

 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 voulez-vous 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();
        }
  }
15
répondu MethodMan 2012-12-07 00:38:44

J'ai utilisé un code similaire à @MethodMan mais je devais garder une trace des données que le port série envoyait et rechercher un caractère de terminaison pour savoir quand le port série a été envoyé.

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
répondu 2016-01-06 21:28:28