Accessing .NET Serial Ports from C#

Wednesday Oct 8th 2014 by Peter Shaw
Share:

Dust off your serial port and find new uses for a nearly-forgotten data link.

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:

SerialPorts1
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:

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

         myPort.Open();

         Console.ReadLine();

         myPort.Close();

      }

      static void MyPortDataReceived(object sender,
         SerialDataReceivedEventArgs e)
      {
         var myPort = sender as SerialPort;
         Console.WriteLine(myPort.ReadLine());
      }

   }
}

That code gives us the following output:

SerialPorts3
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.

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved