He leído un montón de preguntas acerca de cómo leer los datos de los puertos serie con el .NETO de la clase SerialPort pero ninguno de los recommanded enfoques han probado ser completamente eficiente para mí.

Aquí es el código que estoy usando por ahora:

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

Y el controlador de eventos:

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

Pero aún me faltan algunos datos, a veces. He tratado de manera diferente de la lectura de los datos en el controlador de eventos, pero no hubo suerte.

Como el .NET 4.5 trae nuevas posibilidades para hacer algunas tareas asincrónicas, como con el ReadAsync método que parece ser utilizable en un SerialPort corriente, tengo curiosidad por ver cuál sería el método recomendado para controlar esos casos.

  • Tu pregunta es muy vaga. «Estoy todavía faltan algunos datos, a veces,» es como decirle a su mecánico «mi coche hace un curioso ruido a veces» y le pregunta cuánto va a costar arreglar. Tal vez esta respuesta a una pregunta relacionada con la podría ayudar. Sin embargo, creo que hay que ser mucho más específico si usted desea ayudar, como está, no hay mucho que no puede ser contestada por mirar a otras preguntas sobre este tema.
  • Tienes razón, voy a poner un ejemplo real juntos para ilustrar mejor lo que está sucediendo…
  • La implementación de un protocolo de comunicación serie mediante RS232 o 485 es un muy, muy difícil tarea. Se requiere una gran cantidad de experiencia. He sido la implementación de este ya que el buen viejo DOS días y todavía quedan atascados en algunos de los errores más comunes. ¿Por qué no tratar de encontrar un confiable tercera parte que ofrece para lidiar con comunicaciones en serie? Ellos probablemente han desaparecido todos los muchos, muchos, muchos errores te vas a caer dentro de ti 🙂 Si este es un ejercicio que, a continuación, seguir adelante, es el dador de la gran satisfacción por último maestro de comunicaciones serie! 🙂

3 Comentarios

  1. 22

    Podría intentar algo como esto, por ejemplo, yo creo que lo que están queriendo utilizar es el puerto.ReadExisting() Método

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

    O es que usted quiere hacer sobre la base de lo que estaban tratando de hacer , puedes probar este

    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();
            }
      }
    • Gracias por tu ayuda, finalmente fui con ReadExisting se utiliza con un bloqueo de la colección. Todavía estoy planeando probar la nueva ReadAsync función, aunque…
    • no la processData() método requiere un mutex? Quiero decir, el datareceived evento podría desencadenar de nuevo cuando el processData() todavía se está ejecutando? ¿no es así? Así que se podría terminar con dos (o incluso más?) los subprocesos que se ejecutan en el interior de la processData() método….
    • No lo he probado en esa medida y con base en lo Yannick menciona en su comentario anterior estoy pensando que no iba a hacer una diferencia en caso de que continúe con la lectura de forma Asincrónica
  2. 4

    He utilizado un código similar a @MethodMan, pero tenía que seguir la pista de los datos del puerto serie fue el envío y buscar un carácter de terminación para saber cuando el puerto serie se realiza el envío de datos.

    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
        }
    }
    • ReadLine() ya lo hace por usted. Usted no necesita comprobar \n\r
  3. 1
        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());
            }
    
        }
    }
    }

Dejar respuesta

Please enter your comment!
Please enter your name here