2012-01-18 29 views
9

Estoy desarrollando un programa que necesita interactuar con los puertos COM.SerialPort que no recibe ningún dato

Al aprender de esto Q & A: .NET SerialPort DataReceived event not firing, hago mi código así.

namespace ConsoleApplication1 
{ 
class Program 
{ 
    static SerialPort ComPort;   

    public static void OnSerialDataReceived(object sender, SerialDataReceivedEventArgs args) 
    { 
     string data = ComPort.ReadExisting(); 
     Console.Write(data.Replace("\r", "\n")); 
    } 

    static void Main(string[] args) 
    { 
     string port = "COM4"; 
     int baud = 9600; 
     if (args.Length >= 1) 
     { 
      port = args[0]; 
     } 
     if (args.Length >= 2) 
     { 
      baud = int.Parse(args[1]); 
     } 

     InitializeComPort(port, baud); 

     string text; 
     do 
     { 
      String[] mystring = System.IO.Ports.SerialPort.GetPortNames(); 

      text = Console.ReadLine(); 
      int STX = 0x2; 
      int ETX = 0x3; 
      ComPort.Write(Char.ConvertFromUtf32(STX) + text + Char.ConvertFromUtf32(ETX)); 
     } while (text.ToLower() != "q"); 
    } 

    private static void InitializeComPort(string port, int baud) 
    { 
     ComPort = new SerialPort(port, baud); 
     ComPort.PortName = port; 
     ComPort.BaudRate = baud; 
     ComPort.Parity = Parity.None; 
     ComPort.StopBits = StopBits.One; 
     ComPort.DataBits = 8; 
     ComPort.ReceivedBytesThreshold = 9; 
     ComPort.RtsEnable = true; 
     ComPort.DtrEnable = true; 
     ComPort.Handshake = System.IO.Ports.Handshake.XOnXOff; 
     ComPort.DataReceived += OnSerialDataReceived;    
     OpenPort(ComPort);    
    } 

    public static void OpenPort(SerialPort ComPort) 
    { 
     try 
     { 
      if (!ComPort.IsOpen) 
      { 
       ComPort.Open();      
      } 
     } 
     catch (Exception e) 
     { 
      throw e; 
     } 
    } 
} 
} 

Mi problema es que el evento DataReceived nunca se activa.

Mis especificaciones del programa son:

  1. Sólo .net programación de la consola
  2. utilizo VSPE de http://www.eterlogic.com
  3. Mi equipo tiene puertos COM1 y COM2 ya.
  4. Creé COM2 y COM4 utilizando VSPE.
  5. me sale resultado de la salida de mystring serie (COM1, COM2, COM3, COM4)

Pero todavía no sé por qué DataReceived evento no se dispara.


Actualizado

Por desgracia, todavía no podía hacer para disparar DataReceived caso de ninguna manera.

Por lo tanto, he creado un nuevo proyecto con la esperanza de que enfrentaré una forma de resolverlo.

En ese nuevo proyecto [acaba de aplicación de consola], he creado una clase ...

public class MyTest 
{ 
    public SerialPort SPCOM4; 

    public MyTest() 
    { 

     SPCOM4 = new SerialPort(); 
     if(this.SerialPortOpen(SPCOM4, "4")) 
     { 
      this.SendToPort(SPCOM4, "com test..."); 
     } 

    } 

    private bool SerialPortOpen(System.IO.Ports.SerialPort objCom, string portName) 
    { 
     bool blnOpenStatus = false; 
     try 
     { 
      objCom.PortName = "COM" + portName; 
      objCom.BaudRate = 9600; 
      objCom.DataBits = 8; 

      int SerParity = 2; 
      int SerStop = 0; 

      switch (SerParity) 
      { 
       case 0: 
        objCom.Parity = System.IO.Ports.Parity.Even; 
        break; 
       case 1: 
        objCom.Parity = System.IO.Ports.Parity.Odd; 
        break; 
       case 2: 
        objCom.Parity = System.IO.Ports.Parity.None; 
        break; 
       case 3: 
        objCom.Parity = System.IO.Ports.Parity.Mark; 
        break; 
      } 

      switch (SerStop) 
      { 
       case 0: 
        objCom.StopBits = System.IO.Ports.StopBits.One; 
        break; 
       case 1: 
        objCom.StopBits = System.IO.Ports.StopBits.Two; 
        break; 
      } 

      objCom.RtsEnable = false; 
      objCom.DtrEnable = false; 
      objCom.Handshake = System.IO.Ports.Handshake.XOnXOff; 
      objCom.Open(); 
      blnOpenStatus = true; 

     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
     return blnOpenStatus; 
    } 

    private bool SendToPort(System.IO.Ports.SerialPort objCom, string strText) 
    { 
     try 
     { 
      int STX = 0x2; 
      int ETX = 0x3; 

      if (objCom.IsOpen && strText != "") 
      { 
       objCom.Write(Char.ConvertFromUtf32(STX) + strText + Char.ConvertFromUtf32(ETX)); 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
     return true; 
    } 
} 

No estoy seguro de que me enfrento a la buena suerte o mala suerte ya que esta nueva clase podría hacer fuego DataReceived evento que es de una aplicación de consola anterior que aún se está ejecutando. Para mí es un milagro que no tengo idea de cómo sucede esto.

Déjame contarte más detalles para que puedas darme una sugerencia de una mejor manera.

  1. Finalmente creé 2 proyectos de consola.
  2. El primer proyecto es la clase que publiqué ayer como pregunta.
  3. El segundo proyecto es la clase llamada MyTest que podría generar el evento de incendio DataReceived del primer proyecto, al mismo tiempo cuando se ejecutan dos proyectos.

¿Alguien podría darme sugerencias sobre cómo podría combinar estos dos proyectos como un solo proyecto?

+1

IIRC 'DataReceived' se activa después de recibir un separador de línea. ¿Puedes confirmar que el dispositivo efectivamente está enviando varias líneas? – leppie

+0

@leppie: IIRC, se dispara después de recibir más de (o al menos) bytes 'ReceivedBytesThreshold'. Entonces las preguntas son: 1. ¿Cuántos bytes estás recibiendo? 2. ¿Logró leer esta información usando una aplicación de terminal diferente? – Groo

+0

@Groo: Gracias, parece más intuitivo :) – leppie

Respuesta

17
ComPort.Handshake = Handshake.None; 

El problema no es que el evento DataReceived no se dispara, el problema es que el puerto serie no está recibiendo ningún dato. Hay muy, muy pocos dispositivos seriales que no usan ningún tipo de apretón de manos. Si lo configura en Ninguno, el controlador no encenderá las señales DTR (Data Terminal Ready) y RTS (Request To Send). Lo que un dispositivo de puerto serie interpreta como "la máquina está apagada (DTR)" o "la máquina no está lista para recibir datos (RTS)". Por lo tanto, no enviará nada y su evento DataReceived no se activará.

Si realmente quiere Ninguno, establezca las propiedades DTREnable y RTSEnable en verdadero. Pero es probable que desee HandShake.RequestToSend ya que el dispositivo parece estar prestando atención a las señales de handshake.

Si aún tiene problemas, utilice otro programa de puerto en serie como Putty o HyperTerminal para asegurarse de que los parámetros de conexión y comunicación son buenos y que el dispositivo es receptivo. La utilidad PortMon de SysInternals ofrece una vista de bajo nivel de la interacción del controlador para que pueda comparar lo bueno contra lo malo.

+1

+1. En general, hay muchas razones por las cuales los eventos DataReceived no se dispararán, y casi todos se deben a que no se han recibido datos inteligibles. (En realidad, no se están enviando datos, el cable no está enchufado en la toma correcta, el cable no está haciendo una buena conexión o está dañado, o su configuración en uno u otro extremo es incorrecta (velocidad en baudios, apretón de manos, cantidad de bits, bits de parada o bits de paridad, etc.). –

+0

Lo siento, ese segundo enlace debería haber estado aquí: [serialport-datareceived-event-does-not-fire] (http://stackoverflow.com/questions/8907490/serialport-datareceived-event-does-not-fire) –

+0

Configurar DTREnable y RTSEnable para que funcionen correctamente en mi caso – fragmint

0

Nunca he trabajado con VSPE, así que no estoy seguro si eso causa el problema. He trabajado con un puerto COM antes y busqué mi código. La única diferencia principal es la forma en que declaras el evento.Tiene:

ComPort.DataReceived += OnSerialDataReceived; 

lo tengo así:

ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived); 

OnSerialDataReceived es su manejador de sucesos. No estoy seguro de si esto hará alguna diferencia, pero puedes intentarlo. ¡Espero que esto ayude!

+0

hmm ... para mí hizo la diferencia. Podría ser un problema de subproceso. MSDN dice: El evento DataReceived se genera en una secuencia secundaria cuando se reciben datos del objeto SerialPort. (aquí: http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2) mi +1 por la respuesta! BTW ... inicialmente tenía el nuevo código pero lo eliminé después de la sugerencia de ReScharper. así que, gente, no siempre confíes en ReSharper :) –

+6

Según [esta respuesta] (http://stackoverflow.com/a/863711/921321) esto no hace diferencia, la muestra superior está haciendo uso de la conversión de grupo de métodos implícitos, que da como resultado exactamente el mismo código compilado que el código inferior. – Lukazoid

0

Tuve un problema bastante similar. En una aplicación gráfica (formulario C# win) tuve una clase que encapsula un componente SerialPort. El evento de datos recibidos solo se activaba una vez, luego los siguientes envíos de datos no desencadenaron ningún evento. Resolví el problema llamando al método SerialPort.Close() en mi función principal de evento Cerrado. No tengo idea de por qué eso cambia nada, pero ahora está funcionando.

'Espero que esto ayude ...

+2

¿Pero qué haces cuando necesitas mantener el puerto abierto? –

Cuestiones relacionadas