Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am attempting to create a small application to collect data received from an external sensor attached to COM10. I have successfully created a small C# console object and application that opens the port and streams data to a file for a fixed period of time using a for-loop.

I would like to convert this application to use the dataReceived event to stream instead. After reading the Top 5 SerialPort Tips , I still can't seem to get this to work and don't know what I am missing. I rewrote the console application so that all the code is in Main and is pasted below. Can someone please help enlighten me as to why the event handler port_OnReceiveDatazz is not being called even though I know that there is data being sent to the port by the hardware?

Thanks

Thanks to @Gabe , @Jason Down , and @abatishchev for all the suggestions. I am stumped and can't seem to get the event handler to work. Perhaps it has something to do with the device. I can live with just reading the port in a thread and streaming the data straight to file.

namespace serialPortCollection
{   class Program
        static void Main(string[] args)
            const int bufSize = 2048;
            Byte[] buf = new Byte[bufSize]; //To store the received data.
            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler
            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream
            // Wait for data or user input to continue.
            Console.ReadLine();
            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
            SerialPort spL = (SerialPort) sender;
            const int bufSize = 12;
            Byte[] buf = new Byte[bufSize];
            Console.WriteLine("DATA RECEIVED!");
            Console.WriteLine(spL.Read(buf, 0, bufSize));

Shouldn't it be:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

**Nevermind, the syntax is fine (didn't realize the shortcut at the time I originally answered this question).

I've also seen suggestions that you should turn the following options on for your serial port:

sp.DtrEnable = true;    // Data-terminal-ready
sp.RtsEnable = true;    // Request-to-send

You may also have to set the handshake to RequestToSend (via the handshake enumeration).

UPDATE:

Found a suggestion that says you should open your port first, then assign the event handler. Maybe it's a bug?

So instead of this:

sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);
sp.Open();

Do this:

sp.Open();
sp.DataReceived += new SerialDataReceivedEventHandler (port_OnReceiveDatazz);

Let me know how that goes.

yes I tried that as well. port_OnReceivedDatazz still doesn't get called even though I know for sure that data is being received. – Azim J Jan 21, 2009 at 19:03 setting DtrEnable and RtsEnable to true seems to break communication and when I close the port the device fails its internal self-test :( – Azim J Jan 21, 2009 at 19:22 You may also need to play with CtsHolding and DsrHolding as well. I haven't used this stuff in a little while, so I can't exactly how they work. If you're enabling the rts and dtr stuff, you'll need to check the cts/dsr holding before doing writes. – Jason Down Jan 21, 2009 at 19:38 ok. I will look at the CtsHolding and DsrHolding Properties. I also noticed you suggest I should add the event handler after opeing the port. thanks – Azim J Jan 21, 2009 at 19:53

First off I recommend you use the following constructor instead of the one you currently use:

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

Next, you really should remove this code:

// Wait 10 Seconds for data...
for (int i = 0; i < 1000; i++)
    Thread.Sleep(10);
    Console.WriteLine(sp.Read(buf,0,bufSize)); //prints data directly to the Console

And instead just loop until the user presses a key or something, like so:

namespace serialPortCollection
{   class Program
        static void Main(string[] args)
            SerialPort sp = new SerialPort("COM10", 115200);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler
            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream
            Console.ReadLine();
            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
       // My Event Handler Method
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
                Console.Write(b.ToString());
            Console.WriteLine();

Also, note the revisions to the data received event handler, it should actually print the buffer now.

UPDATE 1

I just ran the following code successfully on my machine (using a null modem cable between COM33 and COM34)

namespace TestApp
    class Program
        static void Main(string[] args)
            Thread writeThread = new Thread(new ThreadStart(WriteThread));
            SerialPort sp = new SerialPort("COM33", 115200, Parity.None, 8, StopBits.One);
            sp.DataReceived += port_OnReceiveDatazz; // Add DataReceived Event Handler
            sp.Open();
            sp.WriteLine("$"); //Command to start Data Stream
            writeThread.Start();
            Console.ReadLine();
            sp.WriteLine("!"); //Stop Data Stream Command
            sp.Close();
        private static void port_OnReceiveDatazz(object sender, 
                                   SerialDataReceivedEventArgs e)
            SerialPort spL = (SerialPort) sender;
            byte[] buf = new byte[spL.BytesToRead];
            Console.WriteLine("DATA RECEIVED!");
            spL.Read(buf, 0, buf.Length);
            foreach (Byte b in buf)
                Console.Write(b.ToString() + " ");
            Console.WriteLine();
        private static void WriteThread()
            SerialPort sp2 = new SerialPort("COM34", 115200, Parity.None, 8, StopBits.One);
            sp2.Open();
            byte[] buf = new byte[100];
            for (byte i = 0; i < 100; i++)
                buf[i] = i;
            sp2.Write(buf, 0, buf.Length);
            sp2.Close();

UPDATE 2

Given all of the traffic on this question recently. I'm beginning to suspect that either your serial port is not configured properly, or that the device is not responding.

I highly recommend you attempt to communicate with the device using some other means (I use hyperterminal frequently). You can then play around with all of these settings (bitrate, parity, data bits, stop bits, flow control) until you find the set that works. The documentation for the device should also specify these settings. Once I figured those out, I would make sure my .NET SerialPort is configured properly to use those settings.

Some tips on configuring the serial port:

Note that when I said you should use the following constructor, I meant that use that function, not necessarily those parameters! You should fill in the parameters for your device, the settings below are common, but may be different for your device.

new SerialPort("COM10", 115200, Parity.None, 8, StopBits.One);

It is also important that you setup the .NET SerialPort to use the same flow control as your device (as other people have stated earlier). You can find more info here:

http://www.lammertbies.nl/comm/info/RS-232_flow_control.html

Hi Thanks. I have modified my code as you suggested but the event handler still doesn't get called. – Azim J Jan 21, 2009 at 19:20 Are you sure the handshaking is setup properly? What serial port settings have you used in the past (in hyperterminal or whatever) to be able to communicate with it? – Gabe Jan 21, 2009 at 19:55 In your last edit you get the event to fire by sending data in the write thread. The write thread just simulates my device sending data. – Azim J Jan 21, 2009 at 20:16 That's correct. I don't actually have your device, so I had to simulate it somehow. It sounds like either the device is not sending data, or your serial port is not configured properly. How have you communicated with the device in the past? – Gabe Jan 21, 2009 at 21:23 With the default settings when I create the serialport object. So in fact the Console.WriteLine in my for-loop does print out data being received. But the event handler never gets called. – Azim J Jan 21, 2009 at 21:37

I was having the very same problem with a modem that had previously worked and then one day just stopped raising the DataReceived event.

The solution in my case, very randomly, was to enable RTS e.g.

sp.RtsEnable = true;

No idea why that worked on this particular bit of kit (not a comms man at all really), nor why it had worked and then stopped but it may help somebody else one day so just posting it just in case...

Thanks for information. unfortunately, I know longer have the hardware so I can't test. In the ended I ended up just continuously reading the port instead of using the event handlers. I will keep your suggestion in mind if we revisit this code. – Azim J Mar 14, 2011 at 19:09

Be aware that there are problems using .NET/C# and any COM port higher than COM9.

See: HOWTO: Specify Serial Ports Larger than COM9

There is a workaround in the format: "\\.\COM10" that is supported in the underlying CreateFile method, but .NET prevents using that workaround format; neither the SerialPort constructor nor the PortName property will allow a port name that begins with "\"

I've been struggling to get reliable communications to COM10 in C#/.NET. As an example, if I have a device on COM9 and COM10, traffic intended for COM10 goes to the device on COM9! If I remove the device on COM9, COM10 traffic goes to the device on COM10.

I still haven't figured how to use the handle returned by CreateFile to create a C#/.NET style SerialPort object, if I knew how to do that, then I think I could use COM10+ just fine from C#.

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center. – Community Jan 19, 2022 at 10:16

First of all change your line to:

sp.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);

Second, be aware that DataReceived is fired every time a byte arrives - so the data you read is likely to be a single character each time, and "buffer" will never hold an entire message if you overwrite it every time you handle the event.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.