2009-03-13 66 views
12

He intentado usar Readline() y se eliminan los datos, traté de usar Read() pero no estoy seguro de cómo tener un método de prueba de errores, ya que puedo obtener varios paquetes uno tras otro y no tengo forma de saber que va a haber otro paquete entrando. Entre paquetes, BytesToRead es 0, así que no puedo usarlo. Cuando lee datos en el búfer, ¿tiene un temporizador o pone el hilo en modo de suspensión para permitir que lleguen todos los paquetes?Lectura desde el puerto serie en C#

Estoy perdido. No sé qué probar después.

Debo mencionar que no tengo garantía de que la cadena que sale del puerto serie termine con \ n o \ r o \ r \ n. Simplemente necesito una forma infalible de leer TODOS los paquetes que vendrán de la báscula cuando el usuario presione IMPRIMIR en ella.

Alguien respondió aquí con la idea que me gustaba, esperando una cierta cantidad de tiempo para todos los paquetes, pero ellos borraron su respuesta. ¿Alguna posibilidad de que puedas volver a publicarlo?

Respuesta

23

¿Ha intentado escuchar el evento DataRecieved de la clase SerialPort?

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

No hay ninguna garantía de que los datos realmente leídos en el puerto serie es serialPort.BytesToRead. Sugeriría verificar el valor de retorno de serialPort.Read. – Roger

10

Pasamos por el mismo proceso hace un tiempo.

La única manera de leer "paquetes" es tener algún concepto de dónde están el inicio y el final de ellos en una secuencia.

De msdn:

Debido a que los datos de tampones clase SerialPort, y el flujo de contenidos en la propiedad BaseStream no, los dos pueden entrar en conflicto acerca de cuántos bytes están disponibles para leer. La propiedad BytesToRead puede indicar que hay bytes para leer, pero estos bytes pueden no ser accesibles para la secuencia contenida en la propiedad BaseStream porque se han almacenado temporalmente en la clase SerialPort.

Utilizamos un hilo de fondo (puede utilizar un BackgroundWorker) para leer los datos en un búfer. Si no puede establecer de manera confiable el carácter de terminación utilizando la propiedad SerialPort.Newline (porque, por ejemplo, ¡varía!) Necesitará implementar su propio sistema de detección de paquetes porque no podrá usar el SerialPort.Readline de bloqueo () método.

Podrías simplemente leer en un búfer de bytes usando SerialPort.Read() (o una cadena usando el método SerialPort.ReadExisting()) y generar un evento cuando detectas un paquete válido en los datos. Tenga en cuenta que Read() (y supongo que ReadExisting()) vacía el buffer de SerialPort, por lo que deberá guardar los datos en otro lugar.

Si configura SerialPort.ReadTimeout, puede manejar TimeoutException y tener una manera fácil de manejar las condiciones en las que su dispositivo no está transmitiendo. Esta es una buena manera de restablecer la detección de paquetes si está utilizando un número fijo de bytes o algún otro esquema no terminado. (use SerialPort.DiscardInBuffer() en un tiempo de espera si no necesita paquetes parciales).

Buena suerte

+0

por lo que sé que no hay un esquema de detección. Intentaré cronometrarlo, esperando unos milisegundos antes del procesamiento para permitir que lleguen los paquetes. No veo otra alternativa. Estaba usando ReadLine() durante 6 meses hasta que alguien notó un error en el que los datos se descartaban. – sarsnake

+0

Utilizamos muchas básculas industriales y normalmente puede establecer el carácter de terminación en el dispositivo. ¿Tienes control sobre los dispositivos de entrada para que puedas ver esto? ReadLine es * mucho * más fácil :) –

+0

hacemos: \ n (ascii 13). Lo que voy a tratar de hacer es leer el byte de datos por byte con SerialPort.ReadByte() y buscar 13. También voy a establecer SerialPort.NewLine en \ n (lo tengo configurado en \ r \ n ahora .... hmmm, tal vez ese sea el problema. Gracias! – sarsnake

3

Desde bytes pueden venir en cualquier momento, almacenamiento temporal de datos de entrada es crítica.Por lo que debe

  1. amortiguar los datos entrantes
  2. escanear su memoria intermedia para encontrar los datos completos
  3. eliminar los datos utilizados desde el buffer

Me pregunto si todavía tiene problemas con el puerto serie. Si es así, desarrollé un lenguaje de programación de puerto serie en C# y creo que resuelve casi todos los problemas con los que todos se encuentran.

¿Podría echar un vistazo y probarlo? Por ejemplo; Puede almacenar datos entrantes del puerto en serie como el siguiente y realizar operaciones de cadena fácilmente.

state Init 
    // define a global variable 
    our $BUFFER = ""; 
    jump(Receive); 
end state 

state Receive 
    recv(); 
    $len = length($DATA_PACKET); 
    if("$len > 0") { 
    $BUFFER += $DATA_PACKET; 
    call(Parser); 
    } 
end state 

state Parser 
    // check if buffer matchs regular expression pattern 
    if(match($BUFFER, "(?<WILLDELETE>.*?<STX>(?<DATA>.*?)<ETX>(?<CHECKSUM>[0-9A-F]{2}))")) { 
    // Received complete data 
    $lenData = length($WILLDELETE); 
    $BUFFER = remove($BUFFER, 0, $lenData); 

    // Do operations with the other parsed fields. $DATA and $CHECKSUM in this example. 
    } 
end state 

Proyecto está libremente disponible en SourceForge y si usted tiene alguna pregunta, por favor no dude en preguntar.

Project Homepage

Download Link

Cuestiones relacionadas