Introduction: Serial Port Programming With .NET

Serial ports provide an easy way to communicate between many types of hardware and your computer. They are relatively simple to use and are very common among peripherals and especially DIY projects. Many platforms such as Arduino have built in serial communication so they are really easy to set up and use. Many times you may want your project to communicate with your computer in order to have a cool interactive output, a neat sensor that passes data to your computer, or anything else you could possibly dream up. In this tutorial, I will walk you through how to interface to a serial port on the computer side of things, using Microsoft's . net framework. The code examples in this tutorial are in C#, but can be easily transferred to Visual Basic, or Visual C++. This tutorial assumes that you have a very basic understanding of object oriented programing, and whatever language you choose to program in.

Since we are mainly going to be using the System.IO.Ports.SerialPort class, HERE is a link to the full documentation by MSDN if you want to check out the rest of the class.

I also found a great article explaining how to fix several common bugs relating to serial ports. Check it out if you get stuck with any odd errors.

Feel free to post questions or feedback! I am always happy to hear constructive comments so I can make improvements.

Step 1: Set-up and Open the Serial Port

We need to include two namespaces in order to use the SerialPort class:

using System.IO.Ports;
using System.IO;

We now need to instantiate a SerialPort object. There are several constructors to choose from to specify different frame formats but in general the easiest to use is the following:

SerialPort(string portName, int baudRate)

An example of this would be:

SerialPort mySerialPort = new SerialPort( “COM3”, 9600);

Here I am using COM3 at 9600 baud. You can find the full list of constructors in the link in the intro. Now that we have created our SerialPort object, we need to open the port using the Open() method. When we are done we will want to close it using the Close() method:

mySerialPort.Open();
mySerialPort.Close();

Several notes: when you use any operation that uses a serial port there is a good chance that an error will occur. For this reason we want to write our code for the serial port within a try – catch block. This will prevent our program from crashing if, for example we tried to open a port that didn’t exist. It is not necessary to instantiate our object within the try – catch block, but we want to open, close, read, and write within it.

//this simply creates a SerialPort object then opens and closes the port
SerialPort mySerialPort = new SerialPort( “COM3”, 9600);
try
{
mySerialPort.Open();
mySerialPort.Close();
}
catch (IOException ex)
{
Console.WriteLine(ex);
}

That’s really all there is for port setup! In the next step we will introduce how to read from a serial port.

Step 2: Reading From the Port

Now that we have created our serial port object and opened the port, we now want to read from the serial port. Here are the basic read functions: (there are several other, but these are the simplest and will work for most applications)

int readChar()  - returns the next char from the input buffer
int readByte() – returns the next byte from the input buffer
string readLine() – returns everything up to the newline character (‘\n’) in the input buffer
string readExisting() – returns everything in the input buffer

It should be noted that readChar() and readByte() both return integers not chars and bytes respectively. In order to convert them to their corresponding types, you will need to typecast them into their respective types:

char nextChar = (char)mySerialPort.readChar();
byte nextByte = (byte)mySerialPort.readByte();

The other two methods are pretty self-explanatory. In the next step I'm going to go a little more in depth about how we would go about reading from a port.

*Technical note*
It is worth noting that both ReadLine(), ReadExisting() return a string based off of decoded bytes from the input buffer. What does that mean? It means that for example if we received the bytes 0x48, 0x69, and 0x0A those would be decoded based off of the ASCII encoding to ‘H’ , ‘I’ , and ‘\n’. This is significant because if we wanted our hardware to send the numeric value of 65 (0x41), and we used ReadExisting() and printed the return value to a console window we would get an output of “A” not “65” because it decoded 0x41 and changed it to ‘A’. If you wanted to read the actual numeric value you should use readByte() or readChar() since they return integer values which are not decoded. The SerialPort class supports multiple encodings other than the default ASCII through the SerialPort.Encoding property; there is plenty of information about that in the link in the intro.

Step 3: Ways to Read From the Port

If we want to be continuously read from a serial port and, for the sake of example, display everything we read in a console window the simplest way to do this would be to do this would be to create a loop and repeatedly call one of our read methods. While this method gets the job done, there are some significant disadvantages to it. First, it is very limiting since you have to be constantly calling the same method over and over again and you’re stuck within the loop.

Another problem that arises with the read methods is that if there is no data in the input buffer when you call them, they will stall the execution of your program until there is valid data to read (this is similar behavior to the Console.ReadLine() method; the program doesn’t continue until the user hits enter). There are properties that you can set to force the method to return after a specific delay, but in general you don’t want your program to run slower than it has to.

A better way to be continuously reading is to check if there is data to be read in the input buffer using the SerialPort.BytesToRead property. This property returns the number of bytes in the input buffer that need to be read. With this we could set up a loop that will skip over the read code if there is nothing in the input buffer. Here’s an example:

while (true)
{
   try
   {
      if (mySerialPort.BytesToRead > 0) //if there is data in the buffer
      {
         mySerialPort.ReadByte(); //read a byte
      }
      //other code that can execute without being held up by read method.
   }
   catch (IOException ex)
   {
      //error handling logic
   }
}

This procedure certainly is more efficient that the previous method and will work for many simple situations where all you are really doing is continuously reading from the port. Let’s take a look at a different scenario. What if you were creating a large complex program that was handling many tasks and would not be able to work within the confines of an infinite loop? Luckily for you, the SerialPort class has created an event that is raised whenever there is new data in the input buffer. For anyone who doesn’t know what an event is, an event is something that interrupts your program when something important happens, calls a method to deal with the event, and then returns to where the program left off. In our case when data is received by the input buffer, the event will stop the program, call a method where we would most likely handle the data, and then go back to where our program left off. We will delve into this in the next step.

Step 4: Reading Using Events

The first thing we need to do is to tell our serial port what method to call when it receives data. This is done with the following line:
mySerialPort.DataReceived += new SerialDataEventHandler(mySerialPort_DataRecieved);

mySerialPort.DataReceived represents the method that is called to handle the event. We specify that method by the following part += new SerialDataEventHandler(mySerialPort_DataRecieved) which says use the method mySerialPort_DataRecieved when the event is raised. Next we have to actually create the method:

public static void mySerialPort_DataRecieved(object sender, SerialDataReceivedEventArgs e)
{
   //whatever logic and read procedure we want
}

That’s really all there is to it. Just one more note: you will want to make sure when using events that you declare your SerialPort object as a class level field so that you can use it in multiple methods including the event handler. Different methods and procedures fit different situations, so you will have to find one that works and that you like to use. I personally like using the events whenever possible since they are the most efficient and leave the program free to do other things, but everyone has their preferences. In the next step I am going to talk about how to write to a serial port.

Step 5: Writing to the Port

Good news! Writing to a port is incredibly easy! Here are the write methods that you can use:

Write(String data)
WriteLine(String data)
Write(byte[] data, int offset, int length)
Write(char[] data, int offset, int length)

The first two methods are almost identical, except that WriteLine() writes a newline character(‘\n’) after writing the data. The other two write methods are also similar; the only difference is the data type of the data to send. To use them, you provide an array of bytes or characters which will be written to the serial port.  The offset parameter just specifies what element of the array to start at i.e. If you pass it 0, it will start at the very beginning of the array; if you pass 1 it will start at the second element. The length parameter is simply the length of the array. Remember to perform these write operations within a try-catch block because they readily throw errors.

*Technical Note*
Remember encoding from step 2? The same concept is applied to Write() and WriteLine(). The call WriteLine(“Hi”) writes 0x41, 0x61, 0x0A (0x0A is the added ‘\n’ since we used WriteLine()). If we want to recognize them as characters on the hardware side you must have your own decoding logic present there.

Step 6: Conclusion

I hope this is helpful to you and your next project. This was something that I personally struggled to figure out so I hope that this will help you have an easier time learning how to interface over a serial port. Feel free to post comments, questions and feedback below.

Comments

author
cagatay (author)2017-01-12

amazing article, many thanks

author
SahandM96 (author)2016-12-14

Very nice,thank you .

author
PanagiotisS (author)2016-05-20

Very nice step by step tutorial.

+1 For going through event handlers :)

author
nassrallah84 (author)2015-07-19

could you please, tell me how to read the integer data from arduino uno in visual basic ?

author
SteveAnderson2k (author)2013-12-12

Thanks very much for responding, I wasn't sure how old this post was. But yes, the meat & potatoes of the program relies on listening to these com ports but it has to listen to all of them at the same time which I guess would be using the event handler. Since the ports most likely would be different on other systems using this program, I have a separate program that reads and writes configuration data to an SQL database. Once the main program is launched, it reads in the configuration info of the com ports from the sql database. These com ports are connected to several 3rd party databases, so I need to send heartbeats to each one at time intervals and expect to receive an acknowledgement back to make sure the far end is listening. I have a server connected to the port that would send a telephone number to this program, the program would look at the number, compare it against a list to determine which 3rd party database it belongs to and then send it out that comm port. The 3rd party database at the far end would then send that customers address information to the program, the data would be rearranged, and then sent back to the server requesting it. (in a nutshell) We've used software like this in the past but now with the XP & server 2003 going away we need to write our own, I've designed stuff in VB6 before but never used the MSComm so I'm sort of a newbie to all of this. I'll be doing it in .net though so I've got my hands full learning the intricacies. Sorry to talk your ear off, have a nice night -Steve (I tried to upload a diagram don't know if it took)

Design.jpg
author
SteveAnderson2k (author)2013-12-12

Thanks for an informative guide, I am looking to read port configurations from an SQL database, assign them to multiple com ports, and then listen on each port for data, then act upon that data. Is it possible to dimension the serial port object into an array of objects? I haven't had a chance to play around with it yet but thought I would ask first. Thanks in advance -Steve

author

If I understand your question correctly, what you can do is create and array or collection (List, ArrayList, etc.) to hold and control all of the SerialPort objects. From there polling would be easy (yet time consuming for your program) with a simple for loop. For event driven reading, the process is a little different and would involve the use of delegates in order to accommodate the multiple ports.