Click here to Skip to main content
Click here to Skip to main content

Serial Communication in C#

, 11 Nov 2007 CPOL
Rate this:
Please Sign up or sign in to vote.
Serail communication in .NET by connecting GSM modems.

Introduction

Whenever there is an interaction between a PC and hardware, most of the time, we are communicating either through a serial port or a parallel port. Here we will see how serial communication is done in .NET 2003 using the Microsoft Communication control (MSComm). There are of course many ways by which we can communicate serially without using the MSComm control.

Communication in PCs happens through COM ports. We choose a COM port open it. Before we open the COM port, we set the COM properties like baud rate, parity bit, handshaking, input mode, etc.

The MSComm control allows you to establish a connection to a serial port and connect to another computer or modem, issue commands, and respond to various events.

Adding the MSComm control in .NET

Note: MSCOMM32.OCX is a registered Microsoft component that comes with Visual Basic 6.0.

  • Go to Tools -> Add/Remove Items.
  • Click on the COM Components tab.
  • Click on Browse, then go to Windows - > System32 folder.
  • Choose file type as COM components, choose MSCOMM32.OCX, click on Open.
  • Click on the OK button of Customize Toolbox.

Setting MSComm properties before opening a COM port

Select and add the "Microsoft Communications Control, version 6.0" control (the Telephone control) onto your form. Set its name property to COM. Here is how we use the control:

private void InitComPort() 
{ 
   // Set the com port to be 1 
   com.CommPort = 1; 

   // Trigger the OnComm event whenever data is received 
   com.RThreshold = 1; 

   // Set the port to 9600 baud, no parity bit,
   // 8 data bits, 1 stop bit (all standard) 
   com.Settings = "9600, n, 8, 1"; 
   com.RTSEnable=true; 

   // No handshaking is used 
   com.Handshaking = MSCommLib.HandshakeConstants.comNone; 

   // Use this line instead for byte array input, best for most communications 
   com.InputMode = MSCommLib.InputModeConstants.comInputModeText; 

   // Read the entire waiting data when com.Input is used 
   com.InputLen = 0; 

   // Don't discard nulls, 0x00 is a useful byte 
   com.NullDiscard = false; 

   // Attach the event handler 
   com.OnComm += new System.EventHandler(this.OnComm); 
}

Call the InitComPort() method in form load or in the form's constructor after InitializeComponent(). Note: We can set the InputMode property to text mode or binary mode.

OnComm event

The OnComm event is used to handle the communication events. OnComm also handles communication errors.

In order to call the OnComm event of the MSComm component, we have to set the Rthreshold property to 1 and attach an event handler. We can either loop through the input buffer if input buffer count is greater than 0 and read data until some specified time is elapsed and then process the data, or you can use the OnComm events to receive output data from a hardware.

You can wait for characters to be received:

do
     Application.DoEvents();
while com.InputBufferCount >= 5

Wait for five characters to receive and then you process the read data.

Properties of MSComm

  • Break: If the Break property is set to true the transmission of characters is suspended until you set it to false. If you want, you can place a timer where you can set some delay and set the Break property to false.
  • CTS: This is the clear-to-send property usually sent from the modem to the computer to indicate that the transmission can proceed. If the CTS property returns true when polled, you can send a command.
  • Comport: You can set the COM port value between 1 to 16. If the port doesn't exist, MSComm generates device error 68.
  • InBufferCount: Refers to the number of characters waiting in the buffer that you can read; if InBufferCount > 0, you can read the data.
  • CommEvent: Returns the most recent error or event occurred; to determine the actual event or error occurred, you must reference the commEvent property.

    Communication errors:

    • comEventBreak - A break signal is received.
    • comEventFrame - Hardware detected a framing error.
    • comEventOverrun - A character was not read from the hardware before the next character arrived and was lost.
    • comEventRxOver - Received buffer overflow.
    • comEventRxParity - Hardware detected a parity error.
    • comEventTxFull - Transmit buffer full.
    • comEventDCB - Unexpected error retrieving device control block for the port.

    Communication events:

    • comEvSend: There is fewer than SThreshold number of characters in the transmitting buffer.
    • comEvReceive: Received RThreshold number of characters. This event is generated continuously until you read the data from the receiving buffer.
    • comEvCTS: Change is clear to send line.
    • comEvDSR: Change in data set ready line; this event is generated only when DSR changes from 1 to 0.
    • comEvCD: Changes in carrier detect line.
    • comEvRing: Ring detected; note: some UARTs may not support this.
    • comEvEOF: End of file character received.
  • Output: Is used to write a stream of data to the transmit buffer. You can write either in text or binary mode. If in text mode you can send a string, or byte array in case of binary mode.
  • PortOpen: Setting this property to true opens the COM port.
  • Note: make sure that a COM port is set to the valid port number.

  • RThreshold: If the RThreshold property is set to zero, OnComm events are not generated. If you want to read the response, you can poll and read. If RThreshold is not set to zero, an OnComm event is generated and the comEvent property is set to comEvReceive. You can read RThreshold number of bytes from the receiving buffer.
  • SThreshold: Setting the SThreshold property to 0 disables generating the OnComm event for data transmission. You might want to generate the comEvSend event to occur once the number of characters crosses the SThreshold value.
  • If say SThreshold is set to 1, the comEvSend event is generated when the transmitting buffer is completely empty.
  • Settings: It is used to set the baud rate, parity check, number of data bits, and stop bit.

    Syntax: object.Setting = <value>

    The calue is composed of "BBBB, P, D, S", where:

    • BBBB -> baud rate
    • P -> parity bit
    • D -> number of data bits
    • S -> number of stop bits

    The default value is "9600, N, 8, 1".

  • OutBufferCount: Returns the number of characters currently waiting in the transmitting buffer. You can also use this to clear the transmitting buffer by setting the OutBufferCount property to 0.
  • OutBufferSize: Returns the total size of the transmitting buffer; the default value is 512 bytes.
  • NullDiscard: If set to false, null characters are transferred from the port to the receiving buffer.
  • Handshaking: This property ensures that data is not lost due to buffer overrun. When the data from the hardware is received and directly read without moving into the receiving buffer, there may be chances of losing some characters because the characters may arrive too quickly. You can use this property and synchronize the communication.

    The Handshaking property can be set to the following values:

    • comNone - No handshaking.
    • comXonXoff - XON/XOFF handshaking.
    • comRTS - Request to send / Clear to send handshaking.
    • comRTSXonXoff - Both request to send and XON/XOFF handshaking.
  • InputMode: It determines how the data will be retrieved through the input property; you can read the data either as string or binary data in a byte array.

Using the code

Here we will see how you can serially communicate between two systems using GSM modems. The following things are done: Dial the GSM number from one system by clicking the Dial button. From the other system, send a command to accept the call (data). You will get a response CONNET 9600 when the connection is established between the two modems connected to the different systems. Once the data call is established, you can send data and it's received on the other end. Similarly, you can send data from another system. To send a message, type the message and click on the Send button. To disconnect, you can disconnect at any end just by closing the COM port. In the GUI, you should click on the Disconnect button.

Note: after connecting the GSM modem, dial from one system by clicking the Dial button; on the other system, you will get the response as a RING, RING. Now you can connect by specifying the command ATA\n and then send CONNECT 9600\n which will establish the connection.

Initialize the COM port by calling InitComPort():

public Form1() 
{ 
    // Initialize Form Components 
    InitializeComponent(); 
    // Initialize the COM Port control 
    InitComPort(); 
}

The OnComm event shown below receives whenever there is a response from the hardware. Note: the input mode of the COM port is set to Text so that you can process the text read. Sleep for a while until you receive the full response, then read the response using com.Input. ProcessResponseText is used to display the response in a RichTextBox.

private void OnComm(object sender, EventArgs e) 
{
    // Wait for Some mili-seconds then process 
    // The response. 
    Thread.Sleep(200); 
    if (com.InBufferCount > 0) 
    { 
        try 
        {   
            // If you want to receive data in Binary mode 
            // Remove below 2 comment lines
            // and comment lines for Process response in 
            // Text mode. 
            //byte[] b1=(byte[])com.Input; 
            //ProcessResponseBinary(b1); 
            // Process response in Text mode. 
            string response=(string)com.Input; 
            ProcessResponseText(response); 
        } 
        catch(Exception ex) 
        { 
            MessageBox.Show(ex.Message, this.Text, 
            MessageBoxButtons.OK,MessageBoxIcon.Information); 
        } 
    } 
}

The input string contains CONNECT 9600 when the connection is established from a GSM Modem. Note: while you communicate between two systems using GSM modems, say for example by using a WaveComm modem, the SIM must be enabled for making data calls. In such cases, after the connection is established, you can send data across the system.

If you receive text data as response:

private void ProcessResponseText(string input) 
{
    // Send incoming data to a Rich Text Box 
    if( input.Trim().Equals("RING")) 
    { 
        Message.Text="Ring..."; 
    } 
    else 
    if( input.Trim().Equals("CONNECT 9600")) 
    { 
        MessageBox.Show(input.Trim(), this.Text, 
        MessageBoxButtons.OK,MessageBoxIcon.Information); 
    } 
    else 
    { 
        MessageBox.Show(input.Trim(), this.Text, 
        MessageBoxButtons.OK,MessageBoxIcon.Information); 
        Message.Text=input.Trim(); 
    }

    // Append output response to RichText Box
    rtfTerminal.AppendText(input + "\n");
}

When the user clicks on the Dial button, send the AT command to dial the other modem. The command for dialing is ATD\n.

private void btn_dial_Click(object sender, System.EventArgs e) 
{ 
    if( txt_phoneno.Text.Trim().Equals("")) 
    { 
        MessageBox.Show("Please Specify Phone Number", this.Text, 
        MessageBoxButtons.OK,MessageBoxIcon.Information); 
        txt_phoneno.Focus(); 
        return; 
    } 

    if(! com.PortOpen ) 
    com.PortOpen=true; 

    // GSM Command Dial a Modem 
    // ATD<phonenumber>\n

    string gsm_command="ATD"; 
    string phone_number=txt_phoneno.Text.Trim(); 
    string command1=gsm_command + phone_number + "\n"; 
    byte[]command_to_dial=System.Text.ASCIIEncoding.Default.GetBytes (command1); 
    com.Output=command_to_dial; 
    Message.Text="Dialing..."; 
}

To disconnect, the Disconnect button needs to be clicked which will set com.PortOpen to false.

private void btn_disconnect_Click(object sender, System.EventArgs e) 
{ 
    // If com port is open then close it 
    // to disconnect connection 

    if( com.PortOpen ) 
    { 
        com.PortOpen=false; 
        MessageBox.Show("Disconnected...", this.Text, 
        MessageBoxButtons.OK,MessageBoxIcon.Information); 
        Message.Text=""; 
        rtfTerminal.Text=""; 
    } 
}

To send messages, click on the Send Button after typing some messages. If you are communicating using a GSM modem by sending commands, then you have to send a byte array. Or else you can send messages as plain text.

private void btn_sendmessage_Click(object sender, System.EventArgs e) 
{ 
    string msg=""; 
    if( txt_sendmessage.Text.Trim().Equals("")) 
    { 
        MessageBox.Show("Please Specify Command", this.Text, 
        MessageBoxButtons.OK,MessageBoxIcon.Information); 
        txt_sendmessage.Focus(); 
        return; 
    } 

    if(! com.PortOpen ) 
    com.PortOpen=true; 

    // To send text messages 
    // If you are using GSM Modem and you want to send 
    // Command then use GetByes of your message 
    // To send Byte data from com port 

    msg=txt_sendmessage.Text.Trim() + "\n"; 
    com.Output = System.Text.ASCIIEncoding.Default.GetBytes(msg); 

    // Or Else If systems are connected with Serial 
    // Cable, Output simple text directly 
    // com.Output= txt_sendmessage.Text; 

    Message.Text="Message Sent...."; 
}

Points of interest

Communicating through a serial port is a very interesting topic, that too using GSM modems. You can do a lot many things like you can programmatically send SMS, do remote communication etc.

Conclusion

It was nice playing with a serial port. This serial demo project wouldn't have been possible without the work by Noah Coad (noah@coad.net). I learnt about serial communication from his article, and worked on and modified his sample code to communicate with GSM modems.

Reference

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Ranjan.D
Web Developer
United States United States
Profile
 
Around 10 years of professional software development experience in analysis, design, development, testing and implementation of enterprise web applications for healthcare domain with good exposure to object-oriented design, software architectures, design patterns, test-driven development and agile practices.
 
In Brief
 
Analyse and create High Level , Detailed Design documents.
Use UML Modelling and create Use Cases , Class Diagram , Component Model , Deployment Diagram, Sequence Diagram in HLD.
 
Area of Working : Dedicated to Microsoft .NET Technologies
Experience with : C# , J2EE , J2ME, Windows Phone 8, Windows Store App
Proficient in: C# , XML , XHTML, XML, HTML5, Javascript, Jquery, CSS, SQL, LINQ, EF
 
Software Development
 
Database: Microsoft SQL Server, FoxPro
Development Frameworks: Microsoft .NET 1.1, 2.0, 3.5, 4.5
UI: Windows Forms, Windows Presentation Foundation, ASP.NET Web Forms and ASP.NET MVC3, MVC4
Coding: WinForm , Web Development, Windows Phone, WinRT Programming, WCF, WebAPI
 
Healthcare Domain Experience
 
CCD, CCR, QRDA, HIE, HL7 V3, Healthcare Interoperability
 
Others:
 
TTD, BDD
 
Education
 
B.E (Computer Science)
 
CodeProject Contest So Far:
 
1. Windows Azure Developer Contest - HealthReunion - A Windows Azure based healthcare product , link - http://www.codeproject.com/Articles/582535/HealthReunion-A-Windows-Azure-based-healthcare-pro
 
2. DnB Developer Contest - DNB Business Lookup and Analytics , link - http://www.codeproject.com/Articles/618344/DNB-Business-Lookup-and-Analytics
 
3. Intel Ultrabook Contest - Journey from development, code signing to publishing my App to Intel AppUp , link - http://www.codeproject.com/Articles/517482/Journey-from-development-code-signing-to-publishin
 
4. Intel App Innovation Contest 2013 - eHealthCare - http://www.codeproject.com/Articles/635815/eHealthCare
 
5. Grand Prize Winner of CodeProject HTML5 &CSS3 Article Contest 2014
 
6. Grand Prize Winner of CodeProject Android Article Contest 2014

Comments and Discussions

 
GeneralRe: Problem in data receiving in serial port communication PinmemberRanjan.D19-Aug-09 0:13 
GeneralRe: Problem in data receiving in serial port communication PinmemberMember 393560329-Jan-10 3:56 
QuestionSimple Question To Ask --- Instead Of the Index, How To Get SMS Data? PinmemberMember 450070211-Mar-09 19:09 
QuestionHow to use it in visual studio 2008 PinmembersamMaster4-Jan-09 23:33 
Hi Ranjan,
I try to use your demo application in visual studio 2008 but I can not add the MSCOMM32.OCX reference to project.
How can I do it?
AnswerRe: How to use it in visual studio 2008 PinmemberRanjan.D19-Jan-09 18:40 
AnswerRe: How to use it in visual studio 2008 PinmemberRusted18-Feb-09 23:18 
GeneralRe: How to use it in visual studio 2008 PinmembersamMaster21-Feb-09 1:38 
GeneralRe: How to use it in visual studio 2008 PinmemberMember 39356036-Sep-09 0:19 
GeneralMy vote of 1 PinmemberSyed Javed13-Dec-08 18:57 
GeneralRe: My vote of 1 PinmemberRanjan.D19-Aug-09 1:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141216.1 | Last Updated 12 Nov 2007
Article Copyright 2007 by Ranjan.D
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid