2012-01-18 184 views
9

我正在开发需要与COM端口交互的程序。SerialPort没有收到任何数据

通过从此学习Q & A:.NET SerialPort DataReceived event not firing,我让我的代码如此。

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

我的问题是DataReceived事件永远不会被解雇。

我的程序规范是:

  1. 只是.NET控制台程序
  2. 我用VSPE从http://www.eterlogic.com
  3. 我的电脑已经COM1和COM2端口。
  4. 我使用VSPE创建了COM2和COM4。
  5. 我从MyString的阵列(COM1,COM2,COM3,COM4)

输出的结果,但我还是不知道为什么不解雇DataReceived事件。


更新

不幸的是,我仍然不能让火以任何方式DataReceived事件。

因此,我创建了一个新项目,希望我将面临一种解决方法。

在新项目[只控制台应用程序],我创建了一个类...

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

我不知道,我面对的是运气好还是运气不好,因为这个新类可以使火DataReceived事件,来自仍在运行的旧版控制台应用程序。对于我来说这是奇迹,我不知道这是如何发生的。

让我告诉你更多的细节,让你可以给我更好的方法建议。

  1. 最后我创建了2个控制台项目。
  2. 第一个项目是我昨天发布的一个问题。
  3. 第二个项目是名为MyTest的类,它可以在第一个项目中激发DataReceived事件,同时当两个项目正在运行时。

任何人都可以给我建议如何将这两个项目作为一个单独的项目?

+1

IIRC DataReceived在接收到行分隔符后被触发。你能确认设备确实发送多行吗? – leppie 2012-01-18 09:03:30

+0

@leppie:IIRC,它收到超过(或至少)'ReceivedBytesThreshold'字节后触发。所以问题是:1.你收到多少字节? 2.您是否成功使用不同的终端应用程序阅读这些数据? – Groo 2012-01-18 09:07:04

+0

@Groo:谢谢,这似乎更直观:) – leppie 2012-01-18 09:08:22

回答

17
ComPort.Handshake = Handshake.None; 

问题不在于DataReceived事件没有触发,问题是串行端口没有收到任何数据。有很少的串口设备根本不使用握手。如果将其设置为None,则驱动程序不会打开DTR(数据终端就绪)和RTS(请求发送)信号。串行端口设备将其解释为“机器已关闭(DTR)”或“机器尚未准备好接收数据(RTS)”。所以它不会发送任何东西,并且DataReceived事件不会触发。

如果你真的想要None,那么将DTREnable和RTSEnable属性设置为true。但它很可能需要HandShake.RequestToSend,因为设备似乎注意握手信号。

如果仍然有问题,请使用另一个串口程序,如Putty或HyperTerminal,以确保连接和通信参数良好,并且设备响应。 SysInternals的PortMon实用程序提供了驱动程序交互的低级视图,因此您可以比较好与差。

+1

+1。一般来说,DataReceived事件不会触发的原因很多,而且几乎所有的原因都是因为没有收到可理解的数据。 (实际上没有数据正在发送,电缆没有插入正确的插座,电缆连接不良或损坏,或者一端或另一端的设置不正确(波特率,握手,比特数,停止比特或奇偶校验比特等)。 – 2012-01-18 13:18:26

+0

对不起,第二个链接应该在这里:[serialport-datareceived-event-does-not-fire](http://stackoverflow.com/questions/8907490/serialport-datareceived-event-does-not-fire) – 2013-06-26 22:43:03

+0

将DTREnable和RTSEnable都设置为true对我来说是可行的 – fragmint 2017-08-29 14:30:57

0

我从来没有使用过VSPE,所以我不确定是否会导致问题。之前我曾使用COM端口,并查找了我的代码。唯一的主要区别是你声明事件的方式。您有:

ComPort.DataReceived += OnSerialDataReceived; 

我有这样的:

ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived); 

OnSerialDataReceived是你的事件处理程序。我不确定这是否会有所作为,但您可以尝试。我希望这有帮助!

+0

嗯...对我来说,它造成了不同。可能是线程问题。 MSDN说:当从SerialPort对象收到数据时,DataReceived事件在辅助线程上引发。 (这里:http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2) 我的答案是+1! 顺便说一句...最初我有新的代码,但在ReScharper建议后删除它。所以,人们并不总是信任ReSharper :) – 2013-05-24 12:44:34

+6

按照[这个答案](http://stackoverflow.com/a/863711/921321)这个没有什么区别,顶端的例子是利用隐式方法组转换,这导致与底部代码完全相同的编译代码。 – Lukazoid 2013-12-15 22:09:39

0

我有一个非常类似的问题。在一个图形应用程序(C#win窗体)中,我有一个类封装了一个SerialPort组件。数据接收事件只发射一次,然后下面的数据发送没有触发任何事件。我通过在我的主体形式Closed事件函数中调用SerialPort.Close()方法解决了这个问题。 不知道为什么会改变任何东西,但现在它工作。

'希望这可以帮助...

+2

但是当你需要保持端口打开时,你会怎么做? – 2012-10-20 09:46:31