12

I am developing program which need to interact with COM ports.

By learning from this Q&A: .NET SerialPort DataReceived event not firing, I make my code like that.

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

My problem is DataReceived event never gets fired.

My program specifications are:

  1. Just .net console programming
  2. I use VSPE from http://www.eterlogic.com
  3. My computer has COM1 and COM2 ports already.
  4. I created COM2 and COM4 by using VSPE.
  5. I get output result from mystring array (COM1, COM2, COM3, COM4)

But I still don't know why DataReceived event is not fired.


Updated

Unfortunately, I still could not make to fire DataReceived event in any way.

So, I created new project by hoping that I will face a way to solve.

At that new project [just console application], I created a class...

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

I am not sure that I face good luck or bad luck because this new class could make fire DataReceived event which is from older console application that is still running. It is miracle to me which I have no idea how this happen.

Let me tell you more detail so that you could give me suggestion for better way.

  1. Finally I created 2 console projects.
  2. First project is the class which I posted as a question yesterday.
  3. Second project is the class called MyTest which could make fire DataReceived event from First project, at the same time when two of the project is running.

Could anyone give me suggestions on how could I combine these two projects as a single project?

Community
  • 1
  • 1
Frank Myat Thu
  • 4,448
  • 9
  • 67
  • 113
  • 1
    IIRC `DataReceived` is fired after receiving a line separator. Can you confirm that the device is indeed sending multiple lines? – leppie Jan 18 '12 at 09:03
  • @leppie: IIRC, it fires after receiving more than (or at least) `ReceivedBytesThreshold` bytes. So the questions are: 1. how many bytes are you receiving? 2. Did you succeed in reading this data using a different terminal app? – vgru Jan 18 '12 at 09:07
  • @Groo: Thanks, that seems more intuitive :) – leppie Jan 18 '12 at 09:08
  • 2
    ComPort.DataReceived +=new SerialDataReceivedEventHandler(OnSerialDataReceived); – Saibal Jan 18 '12 at 09:12
  • 4
    @Saibal: What is the point of your comment? – leppie Jan 18 '12 at 09:28
  • I was looking at the code, and DataReceived expects a delegate. I am not sure if the code will compile the way it is. – Saibal Jan 18 '12 at 09:53

3 Answers3

25
    ComPort.Handshake = Handshake.None;

The problem is not that the DataReceived event doesn't fire, the problem is that the serial port isn't receiving any data. There are very, very few serial devices that use no handshaking at all. If you set it to None then the driver won't turn on the DTR (Data Terminal Ready) and RTS (Request To Send) signals. Which a serial port device interprets as "the machine is turned off (DTR)" or "the machine isn't ready to receive data (RTS)". So it won't send anything and your DataReceived event won't fire.

If you really want None then set the DTREnable and RTSEnable properties to true. But it is likely you want HandShake.RequestToSend since the device appears to be paying attention to the handshake signals.

If you still have trouble then use another serial port program like Putty or HyperTerminal to ensure the connection and communication parameters are good and the device is responsive. SysInternals' PortMon utility gives a low-level view of the driver interaction so you can compare good vs bad.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 1
    +1. In general there are many reasons why DataReceived events won't fire, and almost all of them are because no intelligble data has been received. (There is actually no data being sent, the cable isn't plugged into the correct socket, the cable isn't making a good connection or is damaged, or your settings at one end or the other are incorrect (baud rate, handshake, number of bits, stop bits, or parity bits etc). – Jason Williams Jan 18 '12 at 13:18
  • Sorry, that second link should have been here: [serialport-datareceived-event-does-not-fire](http://stackoverflow.com/questions/8907490/serialport-datareceived-event-does-not-fire) – Jason Williams Jun 26 '13 at 22:43
  • 2
    Setting DTREnable and RTSEnable both to true worked in my case – fragmint Aug 29 '17 at 14:30
0

I had a quite similar problem. In a graphical application (C# win form) I had a class which encapsulate a SerialPort component. The DataReceived event was firing only one time, but then any following data received didn't fire any event. I solved the problem by calling the Close method in my principal form Closed event function. No idea of why that changes anything, but now it's working.

ivcubr
  • 1,988
  • 9
  • 20
  • 28
Freak
  • 1
0

I have never worked with VSPE so I'm not sure if that causes the problem. I have worked with a COM port before and I looked up my code. The only main difference is the way you declare the event. You have:

ComPort.DataReceived += OnSerialDataReceived;

I have it like this:

ComPort.DataReceived += new SerialDataReceivedEventHandler(OnSerialDataReceived);

OnSerialDataReceived is your eventhandler. I'm not sure if this will make any difference, but you can try it. I hope this helps!

Carlito
  • 805
  • 10
  • 20
  • hmm... for me it made the difference. Could be a Thread issue. MSDN says: The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. (here: http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.datareceived.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2) my +1 for the answer! BTW... initially I had the new code but removed it after ReScharper suggestion. so, people, do not always trust ReSharper :) – Yaugen Vlasau May 24 '13 at 12:44
  • 6
    As per [this answer](http://stackoverflow.com/a/863711/921321) this makes no difference, the top sample is making use of implicit method group conversion, which results in the exact same compiled code as the bottom code. – Lukazoid Dec 15 '13 at 22:09