Accessing .NET Serial Ports from C#

Every PC I've ever used has had at least one. In fact, in times gone by it wasn't rare to see two, sometimes even three of them. What am I talking about?

The humble RS232 Serial port.

Some of the younger readers of this article might at this point be scratching their heads wondering what on earth this old duffer is talking about. Look on the back of your PC and look for anything that looks like this:

Figure 1: Identifying the RS232 port

Back in the mists of time (way before USB), these ports, known as RS232 Serial ports, were the primary means of connecting extra peripherals to your PC. Everything from mice to touch screens, modems, and even network-like connections to other computers went through these things at some time or another.

These days, however, serial ports are becoming a rare occurrence, with many newer machines omitting them entirely. In all honesty, I can't remember when I last saw one on a laptop, and the only machines that I now possess that still have physical ports on the back are the PC I'm typing this post on, and the rack of servers I have in the server room upstairs.

What's All This Got to Do with .NET?

Ever since its very beginning, .NET has had great support for any and all serial ports available on the hardware on which it's running. This comes in the form of the 'System.IO.Ports.SerialPort' object. The serial port object makes it amazingly easy to attach your serial-enabled PC to all sorts of equipment that still uses serial connections, which, granted is quite old, but still useable. Given that statement, however, I can still hear many of you mumbling and shaking your heads.

"What's the point if many PCs no longer have any ports on them?"

I can understand why many of you might be thinking and wondering why on earth I chose to do an article on an arcane, dying technology that appears to be of little use, but there's a little secret that I've yet to tell you. A huge amount of all these new-fangled USB gadgets that many people plug into their PCs these days actually appear to the host machine as something called a "COM Port".

These "COM Ports" are actually how serial ports are addressed in your PC. If you look in your Device Manager, for example:

Figure 2: The COM port listed in Device Manager

You might see something like this. In my case, this is actually a GPS device plugged into one of my USB ports with a serial port identifier of "COM45"

Now I actually do happen to know already what the settings for me to program this device are, so after starting up a console mode project in Visual Studio, I add the following code to Program.cs:

using System;
using System.IO.Ports;

namespace SerialPorts
   class Program
      static void Main(string[] args)
         SerialPort myPort = new SerialPort();

         myPort.DataReceived += MyPortDataReceived;
         myPort.PortName = "COM45";
         myPort.BaudRate = 4800;
         myPort.DataBits = 8;
         myPort.Parity = Parity.None;
         myPort.StopBits = StopBits.One;





      static void MyPortDataReceived(object sender,
         SerialDataReceivedEventArgs e)
         var myPort = sender as SerialPort;


That code gives us the following output:

Figure 3: GPS output

As you can see from the screen grab, what I actually have here is the actual GPS data being produced by the attached GPS device.

As far as Windows and .NET are concerned, you're simply just talking to a standard serial port; the mechanics of it being a USB or even any other type of physical connection make no difference at all. In my collection of gadgets, I have barcode scanners, temperature detectors, and all sorts of stuff.

Here's the best part, though; many mobile phones also show up as a GSM Modem and likewise most 3G USB modem sticks do too. This is interesting for lots of reasons, because with the correct commands you can send instructions to the modem and perform tasks like send SMS messages and make voice and data calls from within .NET code.

Describing the Sample Code

Working through the code, this is about the simplest example that can be put together. First off, you need to make sure you reference 'System.IO.Ports' We then proceed to 'new up' a serial port object that we call 'myPort'.

The first thing we add to this port is an event handler to handle any incoming data from the attached device. The event handler uses the .NET "as syntax" to cast the sender object to the correct type. This means you don't have to make your actual source port a global in your application.

We then simply just use ReadLine to get the next line of data available. I've done this for simplicity, but you could just as easy use one of the many other methods to get all the bytes available, one byte at a time or multiple strings. Different types of data will require different strategies, depending on how you need to process the data you receive. Often, this step is the hardest step involved in serial port programming.

If you want to send data back to the device, all the read methods have corresponding write methods, too. I could, for example, say:

myPort.WriteLine("My Serial Device Command");

and that would, as you might expect, send the line, followed by a carriage return to the device via its open port.

In the case of the demo here, this would have no effect because the GPS device I'm using only outputs data and ignores any input given to it. In the case of a mobile phone, however, there are all sorts of commands in the standard GSM Modem command set that you could send to it to perform all kinds of tasks.

The remaining lines of code all set up the initial parameters to the serial port, so that Windows knows exactly what to open and how. The "COM45" port name, if you remember, came from the Device Manager. The rest, as I said previously, came from the programming manual I received when I bought the GPS device.

The 'BaudRate' property is the speed at which the serial connection communicates with the PC. In our demo, 4800 represents 4800 bits per second. The data bit size of 8 tells Windows that our data comes in 8 bit chunks and that we have no parity checking and one stop bit.

If we do the math on this, we have 8 bits per item of data + 1 stop bit. That means we potentially have 9 bits for each single byte received. 4800 times 9 gives us approx 533 bytes per second, or just over half a K of data. A full explanation of how parity and stop bits work is beyond the scope of this article, but if you choose to peruse it further, there's plenty of material out there on the Internet. For our purposes, the faster the baud rate, the faster the device can send data to the host PC, and ultimately the faster you'll need to process it.

If you don't know the settings for the device you're programming, don't worry too much. You often can try different baud rates and other settings until the data you start to receive makes sense. In fact, many bits of software that scan for modems and other serial devices do just this. Be careful about sending data to the device, however, until you know the settings. Even incorrect settings will allow data to reach the device, but if that data is corrupt, it may cause the device to malfunction.

This was just a brief view at what's available under the hood. Many devices that you might not even realise are serial in nature appear in your Device Manager as COM ports. On top of that, you also can get USB/Serial cables that allow you to connect directly to other machines, such as server lights out boards and routers. With these kinds of cables, it's easily possible to write remote control software, or even MVC sites that communicate with gear on the server side, but allow an operator to simply use a browser on another machine to control that device.

Finally, the implementation of the serial port object in mono is also fully complete, which means your .NET code to control a serial device will run everywhere that mono does. I use C# on a Raspberry PI to control a radio-controlled car.

If you have any suggestions or ideas for articles you'd like to see, please feel free to reach out to me on Twitter as @shawty_ds, or come and hunt me down in the Lidnug Linked.NET users group on Linked-In that I help run. I'll be more than happy to produce articles on specific topics of interest.


  • Loan Tips

    Posted by Loanemu on 10/14/2015 03:30am

    Major thankies for the post. Will read on...

  • 10 bits per byte

    Posted by Mark Ward on 11/16/2014 07:33am

    Your math is only slightly off... While there are 8 data bits, 1stop bit, and no parity bit, there is ALWAYS a START bit, so (in your data example, there are 10 bites per byte.

  • biometric system based electronic voting machine using ARM9 microcontroller

    Posted by b.divya soundarya sai on 10/14/2014 10:54pm

    my project is finger-print based electonic voting machine using arm9 how can i transfer finger print data from central server,i.e pc into arm9 board using

  • Lots of devices out there

    Posted by scott purcell on 10/13/2014 07:48am

    I work in the industrial automation field and I can tell you there are still millions and millions of devices talking RS232. I have used machine mounted barcode scanners, scales, measuring instruments and a variety of data acquisition units all on RS232 or RS485 connections. Thanks for your article.

    • RE: Lots of devices out there

      Posted by Peter Shaw on 10/15/2014 12:26pm

      Hi Scott, I'm glad you found things useful. Yes I can well Believe there are tons of device out there still using serial. I work with a lot of telemetry kit, custom devices in vehicles, industrial GPS and such like so know exactly where your coming from.

  • IT Manager

    Posted by David Boccabellla on 10/13/2014 06:20am

    Oh thanks you.. Yes - Serial is an old technology however in process control that are thousands of devices that still happily chat at 9600 baud. Just because some executives thinks that serial is no-longer 'cool' does not mean at a legacy of equipment is going to change.

    • RE: IT Manager

      Posted by Peter Shaw on 10/15/2014 12:30pm

      Indeed David, I still have more than a few gadgets that happily chat away at 9600 baud. IN fact my server alert service in case my Broadband goes down, is an old SPV C600 with a serial port adapter soldered to the now broken USB port on it. I soldered a USB cable direct onto the motherboard, then soldered a serial UART onto the end of that, which via a traditional Serial port on the monitoring server allows me to send SMS.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date