In this tutorial we are going to learn How to program the serial port on a Windows/Linux PC using C# .
The main goals of the tutorial are
- Develop a cross platform serial communication App using C# and .NET Core(3.1)/.Net 5 to communicate with a USB device over Virtual COM port.
- Develop a serial communication App using C# and Dotnet Framework 4.5+ to communicate with a USB device over Virtual COM port.
- How to control the RTS and DTR pins of Serial Port using C# and .Net Core(3.1)/.Net 5 /Dotnet Framework 4.5+.
All the codes listed here are designed to run on command line and is intended to highlight the core serial programming concepts.
If you are looking for a GUI based serial programming tutorial check the link below.
Sourcecodes
- All the C soure files used in this tutorial can be downloaded from our GitHub Page.
- Browse CSharp(C#) Serial Programming Tutorial Repo on Github
- Download the Entire Repository as Zip Archive.
- Please note that the source codes on the website show only the relevant sections to highlight the process of programming the serial port.
- Please use the complete source codes from our github repo when building your own program.
Compilers and IDE's used
C# code is written and compiled using
- Visual Studio Community Edition on Windows 10
- Visual Studio code on Linux (Ubuntu)
Hardware Used
USB2SERIAL - Any easy to use multi protocol converter that can convert from USB to RS485/RS232/Serial.The Board comes with selectable voltage levels for interfacing with 5V and 3.3V logic families.
Selecting the COM port
To find out the COM number corresponding to your serial port,
- In Windows7, Open Device Manager by right clicking on My Computer icon and selecting "Manage → Device Manager".Under Ports(COM & LPT) you can see the parallel and serial ports (COM) detected by your system.
- In Windows 10, Type "Device Manager"on the serach box in the Taskbar.
If your PC has any hardware ports, it will be shown either as COM1 or COM2 under the Ports Section.
I am using a FTDI based USB to Serial Converter (USB2SERIAL) which is recognized as COM46.
If you double click on COM46,you can see the details of the corresponding port.
Displaying the available serial ports using C#
String[] PortNames = SerialPort.GetPortNames(); Console.WriteLine("Available Ports:"); |
SerialPort.GetPortNames() is a static method which can be used to get all the available Serial ports in your System.
It is a part of the System.IO.Ports namespace,so you have to include it.
It returns an array of available serial ports(COMxx in Windows and ttyUSBx in Linux).
Opening a serial port in C# (C Sharp)
Serial port communication is accomplished using the SerialPort Class provided by the Dotnet Framework.The namespace is also available in .Net Core 3.0 and up
The class is present in the System.IO.Ports namespace .In order to access the SerialPort class you have to include the System.IO.Ports namespace in your source file.
In Visual studio if everything is properly configured the auto complete feature will show the namespace while typing.
Writing into Serial Port using C# (C Sharp)
Now lets write a small program that will open a connection to serial port and configure BaudRate,Stop bits ,Parity etc and send a character to Microcontroller board connected to it.
The microcontroller and PC are interfaced using null modem cable and is shown at the bottom of this page.
usingSystem.IO.Ports; //namespace containing SerialPort Class namespace SerialPort_Tutorial try { MyCOMPort.Open(); // Open the port } Catch(Exception Ex) { } MyCOMPort.Write("A"); // Write an ascii "A" |
After you have typed/copied the code into the Visual Studio IDE.
Compile and Run it by pressing F5.the code will open a connection to the serial port ("COM46") ,write an ASCII " A " character and close the port.
If you are using the USB2SERIAL converter brought from this site, TX_RX_LED (D1) will blink signifying that a character is transmitted.
Please note that "COM46" is the serial port number assigned by my computer,the COM number will be different in your system.Please check the device manager and find out COM number assigned to your serial port or USB to serial converter.
If you have entered an invalid COM port number that do not exist in your computer (I have used COM4 to show that),Visual Studio will generate an exception.
In the above code we are creating a SerialPort object of the name MyCOMPort
SerialPort MyCOMPort = new SerialPort();
which is then use to configure the parameters and communicate with the serial port.After the SerialPort object MyCOMPort is created,We assign the name of the serial port to be opened to it.
MyCOMPort.PortName = "COM46";
then baud rate Parity bits and number of start stop bits are assigned .
Setting Parity,Stop/Start bits for Serial Port in C#
Parity can be selected as Even,Odd or None using Parity.Even , Parity.Odd ,Parity.None.
The good thing about the intellisense feature in Visual studio is that it will show all the available options when you type.
MyCOMPort.Parity = Parity.None;
You can see the options of Stop bits also in the same way.In the above program we are using one stop bit.
MyCOMPort.StopBits = StopBits.One;
Opening a SerialPort in C#
After the settings are configured we open the serial port usingMyCOMPort.Open();
Opening a serial port is a critical operation and may generate exceptions.It is our duty as the programmer to catch and handle these exceptions.
We should enclose the statement MyCOMPort.Open(); within a try catch() block and handle any exceptions that may arise.
You can make do with a single try catch block or use multiple blocks as shown below.This one helps to pinpoint the cause of the exception and makes it easy to debug the application.
try { MyCOMPort.Open(); // Open the port } catch (UnauthorizedAccessException Ex) { //Access is denied to the port } catch(ArgumentOutOfRangeException Ex) { //Parity, DataBits,Baudrate are not valid values } catch (ArgumentException Ex) { //The port name does not begin with \"COM\ } catch (IOException Ex) { //The port is in an invalid state } catch (InvalidOperationException Ex) { //Port on the current instance of the SerialPort is already open } |
After you have successfully opened the Serialport ,write a character or string using MyCOMPort.Write("A");
After the communication is over we close the port using MyCOMPort.Close();
Here is the screenshot of Program running on Windows 7 transmitting a ASCII character 'A' to the microcontroller.Here COM81 is the name of my COM port.
Reading from Serial Port using C# (C Sharp)
One problem with reading from Serial Port is that you need some data coming from the outside world through the serial port which you can read.
One way to solve is to use another computer and connect its serial port with your's using a NULL Modem cable.
Another way is to use a microcontroller board like Arduino,MSP430 Launchpad etc to transmit a string to your computers serial port.In this example i am going to use the later method,where a MSP430 Launchpad/ATmega328P will transmit a string of characters toward my PC using its UART which is then read by C# program running on the PC.
One thing to note is that Legacy PC's may have hardware based DB9 RS232 serial ports (quite rare now a days),When you are connecting your microcontroller board with PC make sure that it(microcontroller board) has an RS232 decoder circuit (usually based on MAX232).Connecting the outputs of a DB9 serial port directly to microcontroller pins will damage it.
PC to Microcontroller Serial Communication setup
In this example I am using a MSP430 launchpad which is connected to a laptop using a USB to Serial Converter (USB2SERIAL).USB2SERIAL provides access to the TTL outputs of FT232 (RXD and TXD ) through berg strip connectors which can then be directly connected to the UART of MSP430.
It also has selectable TTL voltage levels(3V and 5V) so that it can be directly connected to 3.3V microcontrollers like MSP430. The TXD(TTL) of MSP430 is connected to RXD (TTL) of USB2SERIAL and vice versa .Whatever the MSP430 microcontroller transmits is received by the PC through USB2SERIAL.
You can use any USB to Serial converter of your choice for this.
- The explanation of MSP430G2553 microcontroller side code can be found here.
- The explanation of ATmega328P microcontroller side code can be found here.
Here is a picture of the connection between the MSP430 and USB2SERIAL (USB to Serial/RS485 converter).Connections are similar for ATmega328P also.
Reading from the serial port is similar to writing to serial port.Most of the code remains same ,
instead of using MyCOMPort.Write() we use MyCOMPort.ReadLine().
We also set Read/Write Timeouts to keep the C# code from waiting for ever.After a set time has elapsed the ReadLine() function returns irrespective of whether it has received any data.Time is specified in Milliseconds.
// Set the read/write timeouts MyCOMPort.ReadTimeout = 500; MyCOMPort.WriteTimeout = 500; |
The data received in the PC serial port is read using MyCOMPort.ReadLine() and then printed on the screen.Here is the code for reading from serial port.
using System; namespace SerialPort_Tutorial //COM port settings to 8N1 mode
try
try Console.WriteLine(RxedData); // Write the data to console MyCOMPort.Close(); // Close port |
If you compile and run this program,the program will execute and wait for the string to be transmitted by the MSP430 microcontroller.
One thing to note that, is Console.ReadLine() will return only after encountering the end of line character "\n".
Please make sure that the microcontroller sends the "\n" character otherwise the Console.ReadLine() will never return and program will hang.
Press the reset button on the Launchpad board so that MSP430 will transmit the string "Hello from MSP430" .When the string is received by PC ,it is displayed on the screen using Console.WriteLine().
Code running on Windows 10 ,
Reading a string from ATmega328P
Read Time out occuring in Windows 10
Please note that i have modified the earlier program to be more informative by adding a few extra lines of code.In the last two examples (reading and writing to serial port code ),I have hard coded the COM port number in the program itself like this MyCOMPort.PortName = "COM46"; .In the new one,i have made the COM port selection interactive by adding the following lines
StringCOM_PortName; Console.Write("Enter the COM Port Number [eg COM32] ->"); COM_PortName = COM_PortName.Trim(); MyCOMPort.PortName = COM_PortName; |
Console.ReadLine() function is used to read the COM port number in the format "COM32".
The extra spaces present in the input value is trimmed by using
COM_PortName = COM_PortName.Trim(); .
Then the whole string is converted to upper case by using
COM_PortName = COM_PortName.ToUpper(); .
Finally the port name is assigned to
MyCOMPort.PortName = COM_PortName;
and then the port is opened. The full code is available in the zip file.
Controlling the RTS and DTR pins of Serial Port using C#
After reading and writing to the serial port,its time to play with the other pins of a serial port like DTR and RTS .
In Some USB to Serial Converters DTR and RTS pins are not available,only the RXD,TXD and Ground pins are available outside.
In USB2SERIAL all 9 pins are brought outside to berg strips which you can easily access.
One use of RTS and DTR pins is used to control the RS485 chips during a USB to RS485 conversion.
When you have to control some thing over several 100's of meters ,RS232 or USB will not be suitable.In such cases we have to use RS485 protocol, one problem with RS485 is that most PC's / Laptops will not have an RS485 port.You can solve that problem by using USB to RS485 converters like USB2SERIAL .
In USB2SERIAL RTS pin is used to put the RS485 chip in receive mode and DTR pin is used to put theRS485 chip in transmit mode.
Please note that in FT232 based USB to Serial converters (like USB2SERIAL) the RTS and DTR pins are inverted internally so setting the pins high will make then low and vice versa
The SerialPort Class in .NET Framework have two properties called RtsEnable and DtrEnable enable to control the RTS and DTR pins respectively.
The code shown below will show you how to control the pins.
using System; namespace SerialPort_Tutorial MyCOMPort.PortName = "COM46"; // Assign the name of the serial port to be opened MyCOMPort.RtsEnable = true; // RTS pin = 1 ,~RTS = 0 MyCOMPort.Close(); // Close port }//end of Main |
The RTS pin is set high usingMyCOMPort.RtsEnable = true; and it is set low usingMyCOMPort.RtsEnable = false; .
Since the pins are inverted internally (in FT232)
Setting the RTS pinMyCOMPort.RtsEnable = true; will make the pin LOW and
Clearing the pin usingMyCOMPort.RtsEnable = false; will make it HIGH,same goes for DTR pin also.
Here is a picture of RTS and DTR lines of USB2SERIAL connected to LED's .
Please note that the USB2SERIAL also has onboard LED's near the RS485 section to display the status of RTS and DTR lines used to control the RS485 chip.
Screenshot of the program executing on windows
Creating a Dotnet framework Project in Windows 10
For compiling the serial programming codes you have to create a C# .Net Framework Console project as shown below. Here our App runs on top of .Net Framework in Windows.
The System.IO.Ports reference will be automatically added to your project file.
All the codes in the tutorials are available as Visual Studio Project files (.sln) in the repo.
Creating a .NET Core Serial Comm Project in Windows 10
Here we are going to create a serial communication project for the .NET Core runtime on windows 10.
We will use the same source files .CS from our github repo.
We will use Visual Studio Community Edition to create the .NET Core Project.
Create a Console App which target the .NET Core runtime as shown below.
Please note that System.IO.Ports is not available in the NET Core Project by default .
If you compile a .cs file that use the System.IO.Ports classes like SerialPort,you will get an error stating that references are missing or "type name SerialPort cannot be found in the namespace System.io.Ports".
You have to install System.IO.Ports using the Nuget package manager.
In VS Community Ed,
Goto "Tools" → "Nuget Package Manager"→ "Manage Nuget Packages for Solution" as shown below.
Then type "System.IO.Ports" into search box and install it as shown below.
After the installation is complete ,Your code will compile without any issues.
Here is the output of the program running in Windows 10 on top of NET Core 3.1 runtime.
If you are interested,there is a small tutorial on how to control a robot using RS485 network from your PC .
You can also check out our RS485 Communication tutorial here