Serial Port rs232

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 35

SerialPort (RS-232 Serial COM Port) in

C# .NET
Posted Wed, Mar 23 2005 19:28 by coad

.NET has a great class called SerialPort (MSDN reference) part of .NET 2.0 and is freely available
in C# Express on MSDN. It is easy to use.  Here’s how…

BTW, this article is about communicating through the PC's Serial COM RS-232 port using
Microsoft .NET 2.0 or later by using the System.IO.Ports.SerialPort class. If you're looking for USB
info, see here.

Example Application & Sample Code: SerialPort Terminal

SerialPortTerminal.zip via ClickOnce

To start off, here is sample code in a terminal application which you can try out to see how the
SerialPort class is used.  This requires Visual Studio 2010 to compile, which can be obtained free
viaC# Express.  It is just a simple little application with basic support for text or binary (hex)
modes to send and receive data.  A nice feature or two is auto-detection of installed COM ports
that update at runtime if you plugin or remove USB-to-Serial adapters, also you can change the
DTR and RTS levels and monitor the CTS, DSR, and CD lines.

Build Note: You will receive an error that Visual Studio isn't able to find NoahCode.pfx.  This is
expected as it is the click-once certificate for publishing and is NOT NEEDED for normal code use. 
Just go to Project Properties > Signing > Click on Create Test Certificate.  that’s it

Get Connected 
You can obtain USB to Serial adapters and have just about as many ports on your PC as you like. I
carry around two adapters with a null modem (wikipedia) between them so I can create a
loopback to send & receive through to separate ports on most any computer. I'd recommend doing
the same for when writing code for the serial port.

If you'd like to quickly and easily create your own external devices to communicate with the PC, I
recommend starting with the Arduino, NetDuino (like an Arduino but programmed in C#),
or Parallax BASIC Stamp modules.  All three have many accessories and sensors available (such as
LCDs, RF, Sounds, AD & DA, etc).  sparkfun.com is a great place to look. After that you could
migrate to anAtmel Microcontroller (recommended) or Microchip PIC.

Write Data Out 


Here is an example of how easy it is to use the new SerialPort control.  Very simply, here is how you
can send a bit of data out the port.

// This is a new namespace in .NET 2.0


// that contains the SerialPort class
using System.IO.Ports;

private static void SendSampleData()


{
// Instantiate the communications
// port with some basic settings
SerialPort port = new SerialPort(
"COM1", 9600, Parity.None, 8, StopBits.One);

// Open the port for communications


port.Open();

// Write a string
port.Write("Hello World");

// Write a set of bytes


port.Write(new byte[] {0x0A, 0xE2, 0xFF}, 0, 3);

// Close the port


port.Close();
}

Read Data From Port 


Now let's take a look at what it takes to read data in from the communications port. This
demonstrates reading text.

1. Create a new "Console Application" and replace all the default class code with this code
2. Add a reference to "System.Windows.Forms" to the project

3. Run w/ F5, to exit the app, press Ctrl-Break.

4. Get Connected with two USB to Serial adapters and a null modem

5. Use another app, the code above, or the SerialPortTerminal.zip example to send data and
watch it come in with this code

#region Namespace Inclusions


using System;
using System.IO.Ports;
using System.Windows.Forms;
#endregion

namespace SerialPortExample
{
class SerialPortProgram
{
// Create the serial port with basic settings
private SerialPort port = new SerialPort("COM1",
9600, Parity.None, 8, StopBits.One);

[STAThread]
static void Main(string[] args)
{
// Instatiate this class
new SerialPortProgram();
}

private SerialPortProgram()
{
Console.WriteLine("Incoming Data:");

// Attach a method to be called when there


// is data waiting in the port's buffer
port.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);

// Begin communications
port.Open();

// Enter an application loop to keep this thread alive


Application.Run();
}

private void port_DataReceived(object sender,


SerialDataReceivedEventArgs e)
{
// Show all the incoming data in the port's buffer
Console.WriteLine(port.ReadExisting());
}
}
}

Listing Available Ports 


One of the (several) new methods that is supported, and one I'm very glad is finally here, is the
ability to obtain a list of the COM ports installed on the computer (ex: COM1, COM2, COM4). This
is definately helpful when you want to present the list of ports avalible for the user to select from
(as in the SerialPortTerminal.zip Win App example).

foreach (string s in SerialPort.GetPortNames())


Console.WriteLine(s);

Sending Files 
Here are two helpful little methods for sending files through the serial port. Of course, these are
the bare essentials and as always, you should check to make sure the port is open first
(port.IsOpen) and use try/catch around trying to open a file, but you get the gist with this code.
The binary sending routine is limited to about 2GB (the size of an int), but this should be okay for
most uses. 

using System.IO;

private static void SendTextFile(


SerialPort port, string FileName)
{ port.Write(File.OpenText(FileName).ReadToEnd()); }

private static void SendBinaryFile(


SerialPort port, string FileName)
{
using (FileStream fs = File.OpenRead(FileName))
port.Write((new BinaryReader(fs)).ReadBytes(
(int)fs.Length), 0, (int)fs.Length);
}

RS-232 Project Photos 


Each of these involve RS-232 serial port communications.

Just what's needed to get started with microcontrollers, 


a Basic Stamp, mini LCD display, power, and RS-232 port.
Two USB to Serial adapters with a null modem 
to loopback and test your serial software.

The brains to a mini automated radio station that let me 


control my PC & home using my HAM radio from around town.

Port Wiring Notes

DB9 Male (Pin Side) DB9 Female (Pin Side)


DB9 Female (Solder Side) DB9 Male (Solder Side)
------------- -------------
\ 1 2 3 4 5 / \ 5 4 3 2 1 /
\ 6 7 8 9 / \ 9 8 7 6 /
--------- ---------

DB9 Female to DB9 Female Null-Modem Wiring


2 | 3 | 7 | 8 | 6&1| 5 | 4
---- ---- ---- ---- ---- ---- ----
3 | 2 | 8 | 7 | 4 | 5 | 6&1

9-pin 25-pin Assignment From PC


------ ------ ------------------------- ------------
Shield 1 Case Ground Gnd
1 8 DCD (Data Carrier Detect) Input
2 3 RX (Receive Data) Input
3 2 TX (Transmit Data) Output
4 20 DTR (Data Terminal Ready) Output
5 7 GND (Signal Ground) Gnd
6 6 DSR (Data Set Ready) Input
7 4 RTS (Request To Send) Output
8 5 CTS (Clear To Send) Input
9 22 RI (Ring Indicator) Input

- RTS & DTR are binary outputs that can be manually set and held
- DCD, DSR, CTS, and RI are binary inputs that can be read
- RX & TX can not be set manually and are controlled by the UART
- maximum voltages are between -15 volts and +15 volts
- binary outputs are between +5 to +15 volts and -5 to -15 volts
- binary inputs are between +3 to +15 volts and -3 to -15 volts
- input voltages between -3 to +3 are undefined while output voltages
between -5 and +5 are undefined
- positive voltages indicate ON or SPACE, negative voltages indicate
OFF or MARK

Protocol Development 
If you are making your own serial interface/protocol, you really must have a good standard in
place. Serial data flows into the com port byte by byte and must be buffered and parsed correctly.
Think of it this way, if a terminal sent your computer "Hello World" it may come in as four
OnComm triggers: "H", "ello", " Wo", and "rld"

The best protocols are usually a mix of these methods.  Here are three simple protocol techniques:

1. Beginning and Ending ("Start" & "Stop") Codes 


This is good for sending text as it lets everybody know when text starts and ends. You
simply tack on a non-normal byte at the beginning and end of the text. For example, you'd
use '---' to signify the start of the string and '===' to signify the end. So you would use:
com.Output = "---Hello World==="; 
 
2. Fixed Length Codes 
Used for specific commands. You can create your own codes to send and specify what they
mean. Say I want to control the lighting in a house, I'd setup a protocol of commands like
this: 
1st byte = House Code, 2nd byte = Light Code, 3rd byte = On or Off (0 for off, 1 for on) 
So to turn on the 11th light in my house (house code #3) I'd use: 
com.Output = new byte[] {3, 11, 0}; 

3. Prefixed Data Packet 


This is probably the most common and flexible but requires the most coding. Just prefix
your data packet with the length of the data. The prefix must be a fixed size, such as two
bytes which would allow a data packet of up to 65,535 bytes. Then the receiver knows how
much data is in the packet because it always takes the first two bytes and uses the rest as
the data packet. 
Example: com.Output = ((char) 00) + ((char) 11) + "Hello World";

Other Resources 
Here are some additional sites, libraries, tutorials, etc. These are links that I just found around the
net and am providing for convenience (they are not endorsed).
 RS-232 on Wikipedia
 SerialPort on MSDN

o Search on Google #1, #2, #3

The Final Say 


The new SerialPort class in .NET 2.0+ rocks! It is much easier to use than getting the old
MSComm.ocx control going in a .NET app, contains new functionality, is a 'native' .NET control,
has docs built into the MSDN Library, and is easy to use.

Frequently Asked Questions (FAQ)


I'm adding this section (as of 8/10/06) to address the common questions I get on this post and
through e-mail.  Chances are, if you ask a good question in the comments here, I'll post it here for
others to see easily. Some of the most popular topics
are usb, device, cable, lines, power, packets,bridge, permissions, help.

1. Q: When updating a control (like a text box) while in the DataRecieved event, I
get an error. 
A: The SerialPort class raises events on a separate thread than the main form was create
on.  Windows Forms controls must be modified only on their original thread.  Thankfully
there is an easy way to do this.  Each Windows control has a "Invoke" method which will
run code on the control's original thread.  So to put the recently received data into a text
box (txtLog), this would do it:   txtLog.Invoke(new EventHandler(delegate { txtLog.Text
+= comport.ReadExisting(); });   You can see this more in action in the "Log" event of
"Terminal.cs" my sample code project, SerialPortTerminal.zip. 
 
2. Q: I can't find the System.IO.Ports namespace. 
A: Using Visual Studio 2003?  The new namespace, and SerialPort class, is part of .NET 2.0
and Visual Studio 2005.  It is not included in .NET 1.x (and Visual Studio 2003).  Even if
you have .NET 2.0 or Visual Studio 2005 installed, you can not access the class from
within Visual Studio 2003. 
 

3. Q: I only have .NET 1.1, what can I do? 


A: Upgrade to .NET 2.0.  Seriously, it's free.  In fact, you can get the great C# and VB
Visual Studio Interactive Development Environment (IDE) editors for FREE now with C#
Express andVB Express.  The .NET Framework Software Development Kit (SDK) for
command-line development is also free.  If you really must stay in .NET 1.1, you can use a
3rd party library. 
 

4. Q: I'm sending data to my device, but it is not responding. 


A: First make sure the device will respond using a standard app like Hyperterminal.  Check
the settings (baud rate, data bits, stop bits, etc) and make sure they match with your
code.  Try sending binary data via binary arrays.  Many devices expect a carriage return at
the end of a command, so be sure to send 0x0D or \n.  String data can be easily converted
to a binary array using: 
byte[] data = System.Text.ASCIIEncoding.Default.GetBytes("Hello World\n"); 
com.Write(data, 0, data.Length); 
Many devices require several carriage returns first to sync baud rates, so send several,
like: com.Output("".PadLeft(9, '\n'));  It you're communicating with a modem, make sure
Echo Back is turned on.  Send "ATE1\n".  Other than this, just keep trying and playing
around with it.  It can be hard because you don't see the response from the device as
easily as you would with a terminal app. 
 
5. Q: When I put received data to a text box or rich text box, I get a strange
symbols. 
A: The default font of text boxes is designed only to show standard characters.  Try using
"CharMap" (a free tool in WinXP, click "Start", "Run", type "CharMap", enter).  "Terminal"
is a font designed to show classic ASCII characters and is what most terminal apps (like
my sample code and Hyperterminal) use.  There are also many ASCII codes that won't
display correctly.  This is why I choose to show the hex data instead of an ASCII string a
lot of the time.  System.Convert.ToString(mybyte, 16) will convert a byte to a string hex
code, for example: byte b = 13; string s = Convert.ToStrong(b, 16).PadLeft(2, '0'), then s
will contain "0D".  See the "ByteArrayToHexString" and "HexStringToByteArray" methods
in my sample app,SerialPortTerminal.zip. 
 

6. Q: What about USB communications?  How can I do USB? 


This blog post isn't about USB.  Believe me, I wish the .NET framework supported USB
natively, and I'm doing what I can here at Microsoft to see USB get into the framework in
the future.  For now, you can use a USB to Serial adapter.  I use a lot of these.  They plug
into the USB port, then appear just as a SerialPort to the PC.  

For native USB devices, microcontroller vendors such as Microchip, Atmel, and TI make


chips that do this for projects as well as have chips that support USB natively (I'm using
thePIC18F14K50).  There is a lot of info and USB C# libraries readily available online with
a quick search, try USB C#, which turns up resources like this great article or this USB HID
C# open source project.  

For simple USB-to-Serial bridges that allow your device to communicate via RS-232 but
connect via USB to the PC, check out the section below on USB-to-Serial Bridge Chipsets 
 

7. Q: Can I use the sample code here in my own projects (commercial or not)? 
Yes!  All sample code on my blog is free public domain material.  I'm not a legal guy so I
don't know the exact words to use, but I'll try...  I'm not responsible for any problems! 
Use at your own rick etc.  However, have at it, if it helps you out, fantastic, that's what it's
here for. 
 

8. Q: When using SerialPort.Open() (or SerialPort.PortOpen = true) I get the


exception "UnauthorizedAccessException" or the error "An unhandled exception
of type 'System.Runtime.InteropServices.COMException' occurred in
axinterop.mscommlib.dll" 
It may be one of a few factors: 

o It may require Administrative privileges to use the port.

o The port may already be open by another program, only one app can use a port at
a time.

o The port may not exist on the computer (this happens a lot).  Verify the port
you're trying to open is listed in the Device Manager (FAQ #9).

o The name being provided is not exactly correct. 


Use the full name of the port when opening, like "COM1" (not "1") 
 

9. Q: How do I know what COM ports are on my PC? 


Use the Device Manager ("Start", "Run", "devmgmt.msc") and look for the "Ports" node
(see below).  If you don't see a Ports node, it's because there are no Serial or Parallel
ports installed in the PC.  You can also use System.IO.Ports.SerialPort.GetPortNames() to
return the list of available ports.  Many laptops these day's don't have a serial port.  You
can get more serial ports very easily today with USB to Serial adapters. 
 
 

10. Q: How do I communicate with my specific device?  Modem, Mobile Phone,


LED/LCD Display, Scanner, GPS, GSM/GPRS, CDMA, test equipment, etc 
This post is specific to device independent serial port communications.  RS-232 is a
hardware standard and there are hundreds (if not thousands) of software protocols that
are created for communicating over RS-232.  An analogy would be that physical telephone
hardware is used around the globe (like the RS-232 hardware standard), but there are
hundreds of languages people can speak through the phone to each other to communicate
(the software protocol).  You will need to find information about the protocol used for your
specific device elsewhere.  I'd recommend looking on the manufacture's website,
writing/calling the manufacture, or searching online for your specific device.  Sometimes
you can find fans or hackers of a device that congregate on a forum.  Some protocols can
be found through wikipedia, like the GPSNMEA 0183 serial protocol that GPS units use to
send their data via a serial connection.  Honestly the RS-232 communications is the easy
part, I personally find the more interesting challenge is writing software for the particular
protocol in use.  Best of luck in finding specifications on the protocol you’re device uses! 
 

11. Q: What control lines can I manually manipulate? 


Control lines on an RS-232 serial port were introduced to provide flow control of serial
data.  Even though a modem or PC may be rated for a particular baud rate, it doesn’t
always mean that the device can process the data that fast.  For example, bits may flow in
through a modem at 2400 bps (bits per second) but in the early days a PC couldn’t
process the data fast enough, so it would toggle control lines to tell the modem that it was
read for more data or to ‘pause’ send it data.  Now since PCs are quite fast these lines are
mostly ignored.  They can be used as a simple way to toggle an LED or send or receive
high or low states. RTS/CTS control flow is one such technique which is supported natively
by the control via the Handshake property. 

Lines marked ‘Output’ in the table can be set by the serial port to a high or low state (True
or False) and the ‘Input’ lines can be read as high or low.  You can use
the PinChanged event to be notified when one of the input pins changes. 
The Handshake property can be set to use RTS/CTS (uses hardware control lines) or
XON/XOFF (uses software) or both. 

Control Name DB9 Pin SerialPort I/O


Line Property
DTR Data Terminal 4 DtrEnable Output
Ready
RTS Request to Send 7 RtsEnable Output
CTS Clear to Send 8 CtsHolding Input
DSR Data Set Ready 6 DsrHolding Input
CD (or Data Carrier 1 CDHolding Input
DCD) Detect
12.
For detecting a Ring Indication, see the next question. 
 

13. Q: How do you detect the Ring Indicator line? 


There isn’t a property off of the SerialPort class to test the current state of the Ring
Indicator (DB9 pin 9), but there is an event that gets triggered, PinChanged.   You can
attach an event listener to PinChanged and when the event is called,
SerialPinChangedEventArgs is passed with a EventType property of type SerialPinChange
which will indicate if a ring indication was detected.  Here is an example: 

comport.PinChanged
+= newSerialPinChangedEventHandler(comport_PinChanged);
 
void comport_PinChanged(object sender, SerialPinChangedEventArgs e)
{
  if (e.EventType == SerialPinChange.Ring) RingDetected();
}

14. Q: What pins can I use for powering devices, a high signal, or for boolean input &
output? 
The TX & RX pins carry the standard serial signal, but the other pins can be used as
high/low input/output pins.  The output pins (4 DTR or 8 CTS), supply 5 to 15 volts (15v is
proper RS-232 standard, 5v is what you’ll usually get) when high and low is 0 to -15
volts.  They only supply flea current (very little current) so they're not meant to be used
for powering any devices (like USB is designed for).  However, they can be used as a
reference voltage or for switching to one of the input pins for a high or low signal.  The
input pins (1 DCD, 6 DSR, 8 CTS, and 9 RI) can be used to detect a high or low signal. 
Proper RS-232 signal levels are -15v for a low and +15v for a high (compared to ground,
pin 5).  A MAX232 or similar chip takes a TTL 0-5v input and produces the -15v to +15v
levels.  However, most PC RS-232 COM ports will accept a 0v for low and 5v for high, but
it is not guaranteed and alters from PC to PC.  If you want a simple "toggle high", just hold
pin 4 DTR high, and switch it to pin 1 DCD.  The .NET SerialPort class has easy to use
properties for switching the output pins high or low and for detecting the current level of
the input pins.  I have been able to use pin 4 DTR for a very low current (20ma max) PIC
processors, but not reliably.  I prefer to always supply external power and use pin 4 as a
signal to turn on or off my device.  I'll attach pin 4 to a transistor that switches my power
source to my PIC to turn it on or off. 
 
15. Q: What about ‘packets’?  Does RS-232 support any commands or data
segregation?  OR  Data comes in at seemingly random times? 
Serial data flow through RS-232 has nothing to do with ‘packets’.  It’s just a stream of
bytes in and out.  There is no guarantee that data arrives together. 

Packet Protocols 
Any notion of data compartmentalization (packets) would have to be coded by you for your
unique use.  Much of my time working with serial has been spent on defining useful packet
like protocols, that usually include some type of header, command structure, and CRC
check.  For example, the first two bytes are the packet length, the next two bytes is the
command, next two bytes are parameters, and the last byte is a CRC.  Then my apps
would buffer incoming data and look in the buffer for valid packets.  Of course it differs
depending on the device you’re working with and your specific needs.  USB does have
specific communications protocol defined, one of them being command based, like the little
packet just mentioned.  But with USB, you’re able to get the whole command and
parameter together at once, with serial you have to create the protocol yourself, buffer,
and parse the data. 

Buffering Incoming Data 


Since bytes may come in at any time, buffering incoming data is critical.  For example, you
may send a command out to your device, and the response back to the PC could trigger a
single DataReceived event with all the 30 bytes of response data in the receive buffer.  Or
more likely, it could be any number of separate triggers of the DataReceived (up to the
number of bytes received), like 4 triggers, first with 2 bytes, then 15 bytes, then 1 byte,
then 12 bytes.  Don’t look for a complete response in a single DataReceived call, instead: 
1. buffer the incoming data 
2. then scan your buffer to find complete data 
3. remove the used data from the buffer 

To buffer incoming data, use a coding pattern like this: 


(download the code SerialComBuffering.zip) 

using System;
using System.IO.Ports;
using System.Collections.Generic;
 
namespace SerialComBuffering
{
  class Program
  {
    SerialPort com = new SerialPort(SerialPort.GetPortNames()[0],
      9600, Parity.None, 8, StopBits.One);
    List<byte> bBuffer = new List<byte>();
    string sBuffer = String.Empty;
 
    static void Main(string[] args)
    { new Program(); }
 
    Program()
    {
      com.DataReceived +=
        new SerialDataReceivedEventHandler(com_DataReceived);
      com.Open();
 
      Console.WriteLine("Waiting for incoming data...");
      Console.ReadKey();
    }
 
    void com_DataReceived(object sender,
      SerialDataReceivedEventArgs e)
    {
      // Use either the binary OR the string technique (but not both)
 
      // Buffer and process binary data
      while (com.BytesToRead > 0)
        bBuffer.Add((byte)com.ReadByte());
      ProcessBuffer(bBuffer);
 
      // Buffer string data
      sBuffer += com.ReadExisting();
      ProcessBuffer(sBuffer);
    }
 
    private void ProcessBuffer(string sBuffer)
    {
      // Look in the string for useful information
      // then remove the useful data from the buffer
    }
 
    private void ProcessBuffer(List<byte> bBuffer)
    {
      // Look in the byte array for useful information
      // then remove the useful data from the buffer
    }
  }
}

                                               
 

16. Q: How do you detect when a device is connected or disconnected? 


Simply put, the device usually starts or stops sending data.  There are no built in events
when a device connects or disconnects.  But there are a few tricks you can do, if you’re
creating the serial device yourself, then you have more options.  I’ve had my devices (and
PC apps) send a constant “are you there” set of bytes, like 00 00 11 11 00 00 hex (I’d use
a ‘are you there’ custom ‘packet’ as in Q13 above) till a device on the other end responds. 
You could also use hardware, that’s what some of the other signals lines are for (CDC,
DSR, RTS, CTS, RI), you can tie one of these high and then catch an event when the line
goes high so you know there’s a device there, when it goes low the device is gone. 
 
17. Q: How do I transfer files? 
If you’re interested in sending entire files between computers or to a device, you have two
primary choices.  First choice is to write your own protocol for breaking a file into
manageable packets, detecting errors, sending/receiving, etc.  Second choice is to use a
protocol already created, like XModem, YModem, ZModem, etc.  These protocols were
created long ago specifically to send files over a serial connection with features like error
correction, being able to resume transfers, compression, etc.  I’m only aware of
commercial implementations for .NET right now, like Sax Software’s CommStudio.  If
anyone find an open source implementation, please let me know! 
 

18. Q: Where can I get USB-to-Serial cables? 


USB-to-Serial adapter cables allow you to get a standard RS-
232 DB9 cable by plugging in the adapter to your USB port. 
You can use several of these to get multiple DB9 ports.  Many
laptops, even desktops, don’t have serial ports these days
which makes these particularly handy. 
  
Every so often I source a good cable for a decent price,
typically around $12.  Here is the deal I’m currently
using. http://amzn.to/JnZ7ag 
  
Be forewarned, not all cables are created equally!  There are two issues to contend with…

1. There are a number of companies that create USB chipsets that emulates an RS-
232 port.  Some are much more compatible with PCs and Macs than others.  For
example, the Prolific and FTDI chipset are used in the most compatible adapters
(unlike Ark Micro, or others).  Those companies produce WHQL (Windows
Hardware Quality Labs) certified drivers and the drivers are built into most
Windows and Mac systems already.  So when shopping for a cable, be sure to
check the chipset manufacture.  Here are some handy links to drivers in case you
need them.

1. Prolific Chipset Drivers

2. FTDI Chipset Drivers

2. Standard RS-232 signals range from 3 to 15 volts (plus or minus), 0 is not a valid
signal.  The USB-to-Serial interface chips used in these cables produce 0 to 5 volts,
standard TTL level logic.  While this works for some PCs, and certainly most
microcontrollers, it is not 100% compatible.  The ‘correct’ USB-to-Serial cables
incorporate an additional line level driver, like the MAX232, that take the 0 to 5
volts and convert it to an appropriate +/- 12 volts for RS-232.  The problem is that
many low-quality cables exist out there without this line level driver chip. 
 

2. Q: How can I best interface with my microcontroller?  USB-to-Serial Bridge


Chipsets 
If you are building your own devices, usually with some
type of microcontroller, and want to interface with the PC,
you can certainly use RS-232 either plugged straight into
your PC or via a USB-to-Serial adapter cable, but another
option is to use an USB-to-Serial bridge chipset directly in
your project (what is inside of the USB-to-Serial adapter
cables).  This allows your device to use RS-232 internally,
but connect to a computer via USB and you as a project
designer never need worry about the USB interface or
drivers (your device and PC software just see serial RS-
232).  You could use a native USB microcontroller
(without an RS-232 bridge), such as the PIC18F14K50, but that requires writing your own
USB drivers and a much deeper understanding of the USB infrastructure (both in hardware
and software).  That particular PIC also comes with a Serial emulator and drivers like
below.  This article is focused on serial RS-232, so I’m covering the USB-to-Serial bridges
here. 
  
These modern ICs don’t require external crystals, can power your device from USB Power,
provide clock sources for your micro if you like, and come with Windows Certified (WHQL)
drivers that are actually included in Windows Vista and beyond (also built in Mac drivers). 
Here are a few…

1. FTDI FT232RL 
The FTDI chips are most popular in electronics projects and used by companies like
Parallax and the Arduino Duemilanove.  They also have the best support in terms
of evaluation modules, well written datasheet, and product availability. product
info,evaluation modules, buy from Mouser, drivers 
 

2. Prolific PL-2303HX 
These are the chips used in the most popular USB-to-Serial cables.  They are
slightly less costly than the FTDI chips in bulk, but are not quite as well supported
in the US market. product info  
 
3. TI TUSB3410 
Another option from Texas Instruments.  I haven’t used this chip.  Product Info 
 

p.s. For trying it out and prototyping, I personally recommend this particular FTDI
evaluation board, the UM232R since it plugs into typical solderless protoytpe
breadboards and has most of the pins easily accessible.  Last priced it was $20 from
Mouser. 

 
 

3. Q: How do I automatically detect the baud rate of a device? 


The PC doesn’t have built-in automatic baud detection, but there is an easy trick to
implement basic baud detection for many devices.  If there is a known call & response to
the device you can set the baud rate of the port to one setting, open the port, send the
call, see if you get the expected response, and if not close the port, set a different baud
rate, and repeat.  For my own devices I’ve had some of them send a known character
string (could be anything, like 000ABCD) after they receive a high on the DTR line.  This
way my serial code can set DTR high, see if it gets the ABCD at one baud rate and if not,
close the port, set another baud rate, open the port, turn DTR high, and try again.  If the
baud rates match the characters will be read correctly, if not then the characters will be
jumbled.  This can be done with many other devices as well if there's a known call and
response, like sending a modem an AT command with an expected response code. 
 
4. Q: May I have permissions to use your code? 
Yes!  The code and samples here are released under the MIT License.  
 

5. Q: How can I get more support?  What are my support options?

 Read this FAQ section!  :) 

 You can try leaving a comment below.  Perhaps someone knows the answer

 Read the official MS documentation, MSDN on SerialPort

 See if the article Wikipedia on RS-232

 Try doing a search and look for other content. SerialPort C#, Serial Com C#, serial
port .net

 Post a question in the .NET Base Class Library in MSDN Forums

This article will demonstrate how to write and receive data from a device connected to a serial port in C#
and .NET. We will be writing the received data to a TextBox on a form, so this will also deal with threading.
In the past, to communicate with a Serial Port using .Net 1.1, you had to either use the Windows API, or use a
third-party control. With .Net 2.0, Microsoft added this support with the inclusion of the SerialPort class as
part of the System.IO.Ports namespace. Implementation of the SerialPort class is very straight-forward. To
create an instance of the SerialPort class, you simply pass the SerialPort options to the constructor of the class:

// all of the options for a serial device


    // ---- can be sent through the constructor of the SerialPort class
    // ---- PortName = "COM1", Baud Rate = 19200, Parity = None,
    // ---- Data Bits = 8, Stop Bits = One, Handshake = None
    SerialPort _serialPort = new SerialPort("COM1", 19200, Parity.None, 8,
StopBits.One);
    _serialPort.Handshake = Handshake.None;

To receive data, we will need to create an EventHandler for the "SerialDataReceivedEventHandler":

// "sp_DataReceived" is a custom method that I have created


    _serialPort.DataReceived
+= newSerialDataReceivedEventHandler(sp_DataReceived);

You can also set other options, such as the ReadTimeout and WriteTimeout:

// milliseconds _serialPort.ReadTimeout = 500;

_serialPort.WriteTimeout = 500;

Once you are ready to use the Serial Port, you will need to open it: 

// Opens serial port 


_serialPort.Open(); 

Now we are ready to receive data. However, to write this data to the TextBox on a form, we need to create a
delegate. .Net does not allow cross-thread action, so we need to use a delegate. The delegate is used to write
to the UI thread from a non-UI thread.

// delegate is used to write to a UI control from a non-UI thread


private delegate void SetTextDeleg(string text);
We will now create the "sp_DataReceived" method that will be executed when data is received through the
serial port:
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Thread.Sleep(500);
    string data = _serialPort.ReadLine();
    // Invokes the delegate on the UI thread, and sends the data that was
received to the invoked method.
    // ---- The "si_DataReceived" method will be executed on the UI thread
which allows populating of the textbox.
    this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data
});
}

Now we create our "si_DataReceived" method:

private void si_DataReceived(string data) { textBox1.Text = data.Trim(); }


We can now receive data from a serial port device and display it on a form. Some devices will send data
without being prompted. However, some devices need to be send certain commands, and it will reply with the
data that the command calls for. For these devices, you will write data to the serial port, and use the previous
code to get the data that will be sent back. In my example, I will be communicating with a scale. For this
particular scale, sending the command "SI\r\n" will force it to return the weight of whatever is on the scale.
This command is specific for this scale. You will need to read the documentation of your serial device to find
commands that it will receive. To write to the serial port, I have created a "Start" button on the form. I have
added code to it's Click_Event:

private void btnStart_Click(object sender, EventArgs e)
{
    // Makes sure serial port is open before trying to write
    try
    {
        if(!(_serialPort.IsOpen))
        _serialPort.Open();
        _serialPort.Write("SI\r\n");
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error opening/writing to serial port :: " +
ex.Message,"Error!");
    }
}

And that is all you need to do. I have attached the Visual Studio 2005 solution.

Login to add your contents and source code to this article

Article Extensions
Contents added by Mahesh Chand on Aug 03, 2010
Here is complete code sample from MSDN.

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

public class PortChat


{
static bool _continue;
static SerialPort _serialPort;

public static void Main()


{
string name;
string message;
StringComparer stringComparer = StringComparer.OrdinalIgnoreCase;
Thread readThread = new Thread(Read);

// Create a new SerialPort object with default settings.


_serialPort = new SerialPort();

// Allow the user to set the appropriate properties.


_serialPort.PortName = SetPortName(_serialPort.PortName);
_serialPort.BaudRate = SetPortBaudRate(_serialPort.BaudRate);
_serialPort.Parity = SetPortParity(_serialPort.Parity);
_serialPort.DataBits = SetPortDataBits(_serialPort.DataBits);
_serialPort.StopBits = SetPortStopBits(_serialPort.StopBits);
_serialPort.Handshake = SetPortHandshake(_serialPort.Handshake);

// Set the read/write timeouts


_serialPort.ReadTimeout = 500;
_serialPort.WriteTimeout = 500;

_serialPort.Open();
_continue = true;
readThread.Start();

Console.Write("Name: ");
name = Console.ReadLine();

Console.WriteLine("Type QUIT to exit");

while (_continue)
{
message = Console.ReadLine();

if (stringComparer.Equals("quit", message))
{
_continue = false;
}
else
{
_serialPort.WriteLine(
String.Format("<{0}>: {1}", name, message) );
}
}

readThread.Join();
_serialPort.Close();
}

public static void Read()


{
while (_continue)
{
try
{
string message = _serialPort.ReadLine();
Console.WriteLine(message);
}
catch (TimeoutException) { }
}
}

public static string SetPortName(string defaultPortName)


{
string portName;

Console.WriteLine("Available Ports:");
foreach (string s in SerialPort.GetPortNames())
{
Console.WriteLine(" {0}", s);
}

Console.Write("COM port({0}): ", defaultPortName);


portName = Console.ReadLine();
if (portName == "")
{
portName = defaultPortName;
}
return portName;
}

public static int SetPortBaudRate(int defaultPortBaudRate)


{
string baudRate;

Console.Write("Baud Rate({0}): ", defaultPortBaudRate);


baudRate = Console.ReadLine();

if (baudRate == "")
{
baudRate = defaultPortBaudRate.ToString();
}

return int.Parse(baudRate);
}

public static Parity SetPortParity(Parity defaultPortParity)


{
string parity;

Console.WriteLine("Available Parity options:");


foreach (string s in Enum.GetNames(typeof(Parity)))
{
Console.WriteLine(" {0}", s);
}

Console.Write("Parity({0}):", defaultPortParity.ToString());
parity = Console.ReadLine();

if (parity == "")
{
parity = defaultPortParity.ToString();
}

return (Parity)Enum.Parse(typeof(Parity), parity);


}

public static int SetPortDataBits(int defaultPortDataBits)


{
string dataBits;

Console.Write("Data Bits({0}): ", defaultPortDataBits);


dataBits = Console.ReadLine();

if (dataBits == "")
{
dataBits = defaultPortDataBits.ToString();
}

return int.Parse(dataBits);
}

public static StopBits SetPortStopBits(StopBits defaultPortStopBits)


{
string stopBits;

Console.WriteLine("Available Stop Bits options:");


foreach (string s in Enum.GetNames(typeof(StopBits)))
{
Console.WriteLine(" {0}", s);
}

Console.Write("Stop Bits({0}):", defaultPortStopBits.ToString());


stopBits = Console.ReadLine();

if (stopBits == "")
{
stopBits = defaultPortStopBits.ToString();
}

return (StopBits)Enum.Parse(typeof(StopBits), stopBits);


}

public static Handshake SetPortHandshake(Handshake defaultPortHandshake)


{
string handshake;

Console.WriteLine("Available Handshake options:");


foreach (string s in Enum.GetNames(typeof(Handshake)))
{
Console.WriteLine(" {0}", s);
}

Console.Write("Handshake({0}):", defaultPortHandshake.ToString());
handshake = Console.ReadLine();

if (handshake == "")
{
handshake = defaultPortHandshake.ToString();
}

return (Handshake)Enum.Parse(typeof(Handshake), handshake);


}
}

How the MSCOMM32.OCX Works


The MSComm control provides serial communications for your application by allowing
the transmission and reception of data through a serial port. 
Syntax
MSComm
Remarks
The MSComm control provides the following two ways for handling communications: 

 Event-driven communications is a very powerful method for handling serial port


interactions. In many situations you want to be notified the moment an event
takes place, such as when a character arrives or a change occurs in the Carrier
Detect (CD) or Request To Send (RTS) lines. In such cases, use
the MSComm control's OnCommevent to trap and handle these communications
events. The OnComm event also detects and handles communications errors. For
a list of all possible events and communications errors, see
the CommEvent property. 
 You can also poll for events and errors by checking the value of
the CommEventproperty after each critical function of your program. This may
be preferable if your application is small and self-contained. For example, if you
are writing a simple phone dialer, it may not make sense to generate an event
after receiving every character, because the only characters you plan to receive
are the OK response from the modem.

Each MSComm control you use corresponds to one serial port. If you need to access more
than one serial port in your application, you must use more than one MSComm control. The
port address and interrupt address can be changed from the Windows Control Panel. 
Although the MSComm control has many important properties, there are a few that you
should be familiar with first. 

Properties Description

CommPort Sets and returns the communications port number.

Sets and returns the baud rate, parity, data bits,


Settings
and stop bits as a string.

Sets and returns the state of a communications


PortOpen
port. Also opens and closes a port.

Returns and removes characters from the receive


Input
buffer.

Output Writes a string of characters to the transmit buffer.

OnComm Event
The OnComm event is generated whenever the value of the CommEvent property changes, indicating that
either a communication event or an error occurred.
Syntax
Private Sub object_OnComm ()
The OnComm event syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.
Remarks
The CommEvent property contains the numeric code of the actual error or event that
generated the OnComm event. Note that setting
the RThreshold or SThreshold properties to 0 disables trapping for
the comEvReceive and comEvSend events, respectively.
 

CommPort Property
Sets and returns the communications port number.
Syntax
object.CommPort[ = value ]
The CommPort property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

value A integer value specifying the port number.

Remarks
You can set value to any number between 1 and 16 at design time (the default is 1).
However, the MSComm control generates error 68 (Device unavailable) if the port
does not exist when you attempt to open it with the PortOpen property.
Warning You must set the CommPort property before opening the port.
Data Type
Integer
 

Handshaking Property
Sets and returns the hardware handshaking protocol.
Syntax
object.Handshaking [ = value ]
The Handshaking property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

An integer expression specifying the handshaking


value
protocol, as described in Settings.
Settings
The settings for value are:

Setting Value Description

comNone 0 (Default) No handshaking.

comXOnXOff 1 XON/XOFF handshaking.

RTS/CTS (Request To Send/Clear To


comRTS 2
Send) handshaking.

Both Request To Send and XON/XOFF


comRTSXOnXOff 3
handshaking.

Remarks
Handshaking refers to the internal communications protocol by which data is
transferred from the hardware port to the receive buffer. When a character of data
arrives at the serial port, the communications device has to move it into the receive
buffer so that your program can read it. If there is no receive buffer and your program is
expected to read every character directly from the hardware, you will probably lose data
because the characters can arrive very quickly.
A handshaking protocol insures data is not lost due to a buffer overrun, where data
arrives at the port too quickly for the communications device to move the data into the
receive buffer.
Data Type
Integer
 

RThreshold Property
Sets and returns the number of characters to receive before the MSComm control sets theCommEvent property
to comEvReceive and generates the OnComm event.
Syntax
object.Rthreshold [ = value ]
The Rthreshold property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

An integer expression specifying the number of


value characters to receive before generating the OnComm
event.
Remarks
Setting the RThreshold property to 0 (the default) disables generating
the OnComm event when characters are received.
Setting RThreshold to 1, for example, causes the MSComm control to generate
theOnComm event every time a single character is placed in the receive buffer.
Data Type
Integer
 

Settings Property
Sets and returns the baud rate, parity, data bit, and stop bit parameters.
Syntax
object.Settings [ = value ]
The Settings property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

An string expression representing the communications


value
port settings, as described below.

Remarks
If value is not valid when the port is opened, the MSComm control generates error 380
(Invalid property value).
Value is composed of four settings and has the following format:

"BBBB,P,D,S"
Where BBBB is the baud rate, P is the parity, D is the number of data bits, and S is the
number of stop bits. The default value of value is:

"9600,N,8,1"
The following table lists the valid baud rates.
Setting

110

300

600

1200
2400

9600 (Default)

14400

19200

28800

38400

56000

128000

256000

The following table describes the valid parity values.

Setting Description

E Even

M Mark

N (Default) None

O Odd

S Space

The following table lists the valid data bit values.


Setting

8 (Default)
The following table lists the valid stop bit values.

Setting  

1 (Default)

1.5  

2  

Data Type
String

InputLen Property
Sets and returns the number of characters the Input property reads from the receive buffer.
Syntax
object.InputLen [ = value ]
The InputLen property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

An integer expression specifying the number of


value characters theInput property reads from the receive
buffer.

Remarks
The default value for the InputLen property is 0. Setting InputLen to 0 causes
theMSComm control to read the entire contents of the receive buffer when Input is
used.
If InputLen characters are not available in the receive buffer, the Input property
returns a zero-length string (""). The user can optionally check
the InBufferCount property to determine if the required number of characters are
present before using Input.
This property is useful when reading data from a machine whose output is formatted in
fixed-length blocks of data.
Data Type
Integer
 
Input Property
Returns and removes a stream of data from the receive buffer. This property is not available at design time and
is read-only at run time.
Syntax
object.Input
The Input property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

Remarks
The InputLen property determines the number of characters that are read by
the Inputproperty. Setting InputLen to 0 causes the Input property to read the entire
contents of the receive buffer.
The InputMode property determines the type of data that is retrieved with
the Inputproperty. If InputMode is set to comInputModeText then
the Input property returns text data in a Variant.
If InputMode is comInputModeBinary then the Input property returns binary data in
an array of bytes in a Variant.
Data Type
Variant
 

PortOpen Property
Sets and returns the state of the communications port (open or closed). Not available at design time.
Syntax
object.PortOpen [ = value ]
The PortOpen property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

A boolean expression specifying the state of the


value
communications port.

Settings
The settings for value are:

Setting Description
True Port is opened

False Port is closed

Remarks
Setting the PortOpen property to True opens the port. Setting it to False closes the
port and clears the receive and transmit buffers. The MSComm control automatically
closes the serial port when your application is terminated.
Make sure the CommPort property is set to a valid port number before opening the
port. If the CommPort property is set to an invalid port number when you try to open
the port, theMSComm control generates error 68 (Device unavailable).
In addition, your serial port device must support the current values in
the Settings property. If the Settings property contains communications settings that
your hardware does not support, your hardware may not work correctly.
If either the DTREnable or the RTSEnable properties is set to True before the port is
opened, the properties are set to False when the port is closed. Otherwise, the DTR and
RTS lines remain in their previous state.
Data Type
Boolean

DTREnable Property
Determines whether to enable the Data Terminal Ready (DTR) line during communications. Typically, the Data
Terminal Ready signal is sent by a computer to its modem to indicate that the computer is ready to accept
incoming transmission.
Syntax
object.DTREnable[ = value ]
The DTREnable property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

A Boolean expression specifying whether to enable the


Value Data Terminal Ready (DTR) line, as described in
Settings.

Settings
The settings for value are:

Setting Description

True Enable the Data Terminal Ready line.

False (Default) Disable the Data Terminal Ready line.


Remarks
When DTREnable is set to True, the Data Terminal Ready line is set to high (on) when
the port is opened, and low (off) when the port is closed. When DTREnable is set
to False, the Data Terminal Ready always remains low.
Note In most cases, setting the Data Terminal Ready line to low hangs up the
telephone.
Data Type
Boolean

RTSEnable Property
Determines whether to enable the Request To Send (RTS) line. Typically, the Request To Send signal that
requests permission to transmit data is sent from a computer to its attached modem.
Syntax
object.RTSEnable[ = value ]
The RTSEnable property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

An boolean expression specifying whether the Request


value To Send (RTS) line is enabled, as described in
Settings.

Settings
The settings for value are:

Setting Description

True Enables the Request To Send line.

False (Default) Disables the Request To Send line.

Remarks
When RTSEnable is set to True, the Request To Send line is set to high (on) when the
port is opened, and low (off) when the port is closed.
The Request To Send line is used in RTS/CTS hardware handshaking.
The RTSEnableproperty allows you to manually poll the Request To Send line if you
need to determine its state.
For more information on handshaking protocols, see the Handshaking property.
Data Type
Boolean

CommEvent Property
Returns the most recent communication event or error. This property is not available at design time and is read-
only at run time.
Syntax
object.CommEvent
The CommEvent property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.

Remarks
Although the OnComm event is generated whenever a communication error or event
occurs, the CommEvent property holds the numeric code for that error or event. To
determine the actual error or event that caused the OnComm event, you must
reference theCommEvent property.
The CommEvent property returns one of the following values for communication errors
or events. These constants can also be found in the Object Library for this control.
Communication errors include the following settings:

Constant Value Description

comEventBreak 1001 A Break signal was received.

Framing Error. The hardware detected


comEventFrame 1004
a framing error.

Port Overrun. A character was not read


comEventOverrun 1006 from the hardware before the next
character arrived and was lost.

Receive Buffer Overflow. There is no


comEventRxOver 1008
room in the receive buffer.

Parity Error. The hardware detected a


comEventRxParity 1009
parity error.

Transmit Buffer Full. The transmit


comEventTxFull 1010 buffer was full while trying to queue a
character.

comEventDCB 1011 Unexpected error retrieving Device


Control Block (DCB) for the port.

Communications events include the following settings:

Constant Value Description

There are fewer than Sthreshold number


comEvSend 1
of characters in the transmit buffer.

Received Rthreshold number of


characters. This event is generated
comEvReceive 2 continuously until you use the Input
property to remove the data from the
receive buffer.

comEvCTS 3 Change in Clear To Send line.

Change in Data Set Ready line. This


comEvDSR 4 event is only fired when DSR changes
from 1 to 0.

comEvCD 5 Change in Carrier Detect line.

Ring detected. Some UARTs (universal


comEvRing 6 asynchronous receiver-transmitters)
may not support this event.

End Of File (ASCII character 26)


comEvEOF 7
character received.

Data Type
Integer

Output Property
Writes a stream of data to the transmit buffer. This property is not available at design time and is write-only at
run time.
Syntax
object.Output [ = value ]
The Output property syntax has these parts:

Part Description

An object expression that evaluates to an object in the


object
Applies To list.
value A string of characters to write to the transmit buffer.

Remarks
The Output property can transmit text data or binary data. To send text data using
theOutput property, you must specify a Variant that contains a string. To send binary
data, you must pass a Variant which contains a byte array to the Output property.
Normally, if you are sending an ANSI string to an application, you can send it as text
data. If you have data that contains embedded control characters, Null characters, etc.,
then you will want to pass it as binary data.
Data Type
Variant

Serial Port atau lebih popular dengan nama RS232 adalah protocol/interface yang paling banyak
digunakan dan popular terutamanya di kalangan pelajar. Rs232 protocol mudah digunakan,
incorporated in PC(mostly old PCs), some microcontroller dan tidak memerlukan hardware yg
expensive. But today,USB lebih popular kerana mudah, plug n play, and offer higher transfer rates
compared to RS232. 

I have been using Serial Port for quite some time in a lot of projects. Contohnya, interfacing a robot
with external device such as zigbee or bluetooth module. So, i think it's good to write article about
serial port/RS232. My objective here is to show the way to write codes to access PC serial port

There are 2 ways to access PC serial port(as far as i know). 

 using mscomm32.ocx
 .NET object
I prefer the 2nd method because lebih mudah digunakan and i use C#(.NET) a lot. I have written a
script in VBA to access serial port from Microsft Excel(using mscomm32.ocx). VBA stand for Visual
Basic for Application which is exists in Excel(you probably know it if you're familiar with Excel
macro) 

.NET component - using C#

If you're familiar with C# or C++ or VB.NET, then it's better jika anda menggunakan .NET
component. I will show an example of source code written in C# in this post. First of all, you need to
'define' the component in the project file by a 'using' statement on top of the file.

using System.IO.Ports;
The above statement will allow you to access serial port component.

class SerialPortCustom
{
SerialPort SP = new SerialPort();

public SerialPortCustom()
{
SP.BaudRate = 57600;
SP.Handshake = Handshake.None;
SP.Parity = Parity.None;
SP.PortName = " ";
SP.StopBits = System.IO.Ports.StopBits.One;
SP.DataBits = 8;
}

//remaining codes are not displayed ~~~~


This is a sample of source code from my past project. I create a class name "SerialPortCustom". This
class will handle all the serial port events and function. As you can see, in the class constructor, 6
items were pre-defined. So, my baudrate works at 57600 bps without handshake signal and parity, 1
stop bit and 8 data bits. However, i left portName empty so that i can choose available port later. This
just the basic idea how to instantiate .NET serial port component. It is possible if you want to change
all the properties in the form later, but you need to write a proper code to handle it.

Next, you must have functions or methods to read data from receive buffer or to write data to transmit
buffer. Therefore, you can instantiate event handler for every data received as shown below. However,
you can use polling method if your application know the exact time of incoming data/packet. 

//instantiate event handler : raised when RX buffer is


not empty.
SP.DataReceived += new
SerialDataReceivedEventHandler(SP_DataReceived);
Every data in received buffer will raised the event. Then, it's up to you what you want to do with the
data. Just for an example, when the event raised, the method reads up all 4 bytes of the incoming data
before calling another function/method as shown below.

// This event raised if received buffer is full


public void SP_DataReceived(object sender,
SerialDataReceivedEventArgs e)
{
stream_buffer[0] = SP.ReadByte(); //read
1st byte
stream_buffer[1] = SP.ReadByte(); //read
another byte and so on
stream_buffer[2] = SP.ReadByte();
stream_buffer[3] = SP.ReadByte();
parsing_display(); //calling another
method
}
Perhaps you also wants to write something through your serial port. Therefore, you can write a
function for that purpose. The codes below is just a simple function that accepts 1 byte of data and
transmit through serial port(RS232). 

// "write" method
public void WR_byte(byte byte_data)
{
argv[0] = byte_data; // argv[] used to
hold the data
SP.Write(argv, 0, 1); // transmit 1 byte
through serial port (com port)
}
In conclusion, it is easy to use/work with serial port (RS232) using .NET framework. If you are not
familiar with C#, you can write in VB and also C++. I wrote the script in VB.NET once for my final
year project purpose. The syntax are different but the concept is just the same. Now, let's move on to
the next section. 

MSCOMM32.OCX - VBA

Selain menggunakan C#/.NET, it is possible to access serial port directly in Microsoft Excel. What you
need is just MSCOMM32.ocx and basic knowledge in VBA. However, several steps required before
you can start programming.

You need to register the file first so that your VB editor could recognize the components. Place the file
in system32 folder and then click start -> run and paste the command below. 

Regsvr32 "C:\Windows\System32\mscomm32.ocx"
After you completed the lst step, run Microsoft Excel and open VB editor. Same as C#, 2 methods shall
be implemented, either event-based or polling method. Polling method is suitable if you know exact
time of incoming data. 

First, you need to instantiate the object(class).

Private SerCom As New MSComm


Then, you need to set properties of the class such as baud rate, handshaking, and so on.

With SerCom
.CommPort = com_number
.Settings = "57600,M,8,1"
.Handshaking = comNone
.InputLen = 8
.InBufferSize = 8
.NullDiscard = True
.InputMode = comInputModeText
.RThreshold = 1
End With
Next, you can use buttons to enable/disable serial port operation.

If SerCom.PortOpen = False Then


SerCom.PortOpen = True ' turn
on serial port
Else
' error handling or any code here
End If
My previous project not required event-based method since i know exactly when the transaction will
occur. 

' a piece of code for read and write

SerCom.InputLen = 0
' Setting InputLen to 0 causes the MSComm control
to read the entire
contents of the receive buffer
chdata = Replace(SerCom.Input, vbCrLf, "")
' get a stream of data from the receive buffer
' the codes also remove carriage return and line
feed

' access write


Public Sub UART_write(ByVal str As String)
SerCom.Output = str + vbCrLf
' place any other codes here
End Sub
However, if you choose to use event-based method, you need to declare the event first.

' declare an event


Private WithEvents SerCom As MSCommLib.MSComm

' this method raised on any event that you define


in it.
Private Sub SerCom_OnComm()
If SerCom.CommEvent = 2 Then
' read recieve buffer : code goes here
ElseIf SerCom.CommEvent = x Then ' x =
Communications events/errors
' do something else
End If
End Sub

You might also like