2012-01-18 17 views
9

Sto sviluppando un programma che deve interagire con le porte COM.SerialPort non riceve alcun dato

Imparando da questo Q & A: .NET SerialPort DataReceived event not firing, faccio il mio codice in questo modo.

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

Il mio problema è l'evento DataReceived mai generato.

mie specifiche del programma sono:

  1. Proprio .net programmazione console
  2. Io uso VSPE da http://www.eterlogic.com
  3. Il mio computer ha COM1 e COM2 porte già.
  4. Ho creato COM2 e COM4 utilizzando VSPE.
  5. ho ottenere il risultato in uscita da MyString array (COM1, COM2, COM3, COM4)

Ma io ancora non so perché DataReceived evento non viene generato.


Aggiornato

Purtroppo, non riuscivo ancora a far fuoco DataReceived evento in alcun modo.

Quindi, ho creato un nuovo progetto sperando che affronti un modo per risolvere.

A quel nuovo progetto [solo Applicazione console], ho creato una classe di ...

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

Non sono sicuro che affronto fortuna o sfortuna, perché questa nuova classe potrebbe fare fuoco DataReceived evento che proviene da una vecchia applicazione per console ancora in esecuzione. È un miracolo per me che non ho idea di come ciò possa accadere.

Lascia che ti spieghi più in dettaglio in modo che tu possa darmi suggerimenti per un modo migliore.

  1. Infine ho creato 2 progetti di console.
  2. Il primo progetto è la classe che ho postato come domanda ieri.
  3. Il secondo progetto è la classe denominata MyTest che potrebbe attivare l'evento DataReceived dal primo progetto, nello stesso momento in cui due dei progetti sono in esecuzione.

Qualcuno potrebbe darmi suggerimenti su come combinare questi due progetti come un singolo progetto?

+1

IIRC 'DataReceived' è sparato dopo aver ricevuto un separatore di riga. Puoi confermare che il dispositivo sta effettivamente inviando più righe? – leppie

+0

@leppie: IIRC, si attiva dopo aver ricevuto più (o almeno) byte 'ReceivedBytesThreshold'. Quindi le domande sono: 1. quanti byte stai ricevendo? 2. Sei riuscito a leggere questi dati usando un'app terminale diversa? – Groo

+0

@Groo: Grazie, sembra più intuitivo :) – leppie

risposta

17
ComPort.Handshake = Handshake.None; 

Il problema non è che l'evento DataReceived non si attivi, il problema è che la porta seriale non riceve alcun dato. Ci sono pochissimi dispositivi seriali che non usano affatto l'handshaking. Se si imposta su Nessuno, il driver non accenderà i segnali DTR (Data Terminal Ready) e RTS (Request To Send). Quale dispositivo della porta seriale interpreta come "la macchina è spenta (DTR)" o "la macchina non è pronta per ricevere dati (RTS)". Quindi non invierà nulla e il tuo evento DataReceived non sparerà.

Se si in realtà si desidera Nessuno quindi impostare le proprietà DTREnable e RTSEnable su true. Ma è probabile che tu voglia HandShake.RequestToSend poiché il dispositivo sembra prestare attenzione ai segnali di handshake.

Se si verificano ancora problemi, utilizzare un altro programma di porta seriale come Putty o HyperTerminal per garantire che i parametri di connessione e comunicazione siano corretti e che il dispositivo sia reattivo. L'utilità PortMon di SysInternals offre una vista di basso livello dell'interazione del guidatore in modo da poter confrontare il bene con il cattivo.

+1

+1. In generale ci sono molte ragioni per cui gli eventi DataReceived non si attivano e quasi tutti sono perché non è stato ricevuto alcun dato intelligente. (In realtà non vengono inviati dati, il cavo non è inserito nella presa corretta, il cavo non sta facendo una buona connessione o è danneggiato, oppure le impostazioni a un'estremità o l'altra non sono corrette (velocità di trasmissione, stretta di mano, numero di bit, bit di stop o bit di parità, ecc.). –

+0

Siamo spiacenti, il secondo link dovrebbe essere qui: [serialport-datareceived-event-does-not-fire] (http://stackoverflow.com/questions/8907490/serialport-datareceived-event-does-not-fire) –

+0

Impostazione di DTREnable e RTSEnable su true work nel mio caso – fragmint

0

Non ho mai lavorato con VSPE, quindi non sono sicuro se questo causa il problema. Ho già lavorato con una porta COM e ho cercato il mio codice. L'unica differenza principale è il modo in cui dichiari l'evento.Hai:

ComPort.DataReceived += OnSerialDataReceived; 

ho in questo modo:

ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived); 

OnSerialDataReceived è il vostro EventHandler. Non sono sicuro che questo farà alcuna differenza, ma puoi provarlo. Spero che aiuti!

+0

hmm ... per me ha fatto la differenza. Potrebbe essere un problema di discussione. MSDN dice: L'evento DataReceived viene generato su un thread secondario quando i dati vengono ricevuti dall'oggetto SerialPort. (qui: http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2) il mio +1 per la risposta! BTW ... inizialmente avevo il nuovo codice ma l'ho rimosso dopo il suggerimento ReScharper. così, le persone, non sempre si fidano di ReSharper :) –

+6

Come per [questa risposta] (http://stackoverflow.com/a/863711/921321) questo non fa differenza, il campione in alto sta facendo uso della conversione del gruppo di metodi implicita, il risultato è lo stesso codice compilato del codice inferiore. – Lukazoid

0

Ho avuto un problema abbastanza simile. In un'applicazione grafica (C# win form) avevo una classe che incapsula un componente SerialPort. L'evento datareceived è stato attivato una sola volta, quindi i seguenti dati inviati non hanno generato alcun evento. Ho risolto il problema chiamando il metodo SerialPort.Close() nella mia forma principale. Funzione evento chiuso. Non ho idea del motivo per cui qualcosa cambia, ma ora funziona.

'Spero che questo può aiutare ...

+2

Ma cosa si fa quando è necessario mantenere la porta aperta? –

Problemi correlati