Click here to Skip to main content
15,890,506 members
Articles / Desktop Programming / MFC
Article

How to open a serial COM port in Managed C++

Rate me:
Please Sign up or sign in to vote.
4.52/5 (25 votes)
16 Apr 2002 300.9K   61   49
How to open a Serial COM port using Managed C++ and loading unmanaged DLLs

Introduction

Many days ago, I was looking for a class in managed C++ that gives me access to the COM port. I was surprised I couldn't find anything to use. There were many classes to use for sockets and files, but none for COM ports.

I tried to use System::IO::File without any success. Actually File::Open gave me an exception. So I went ahead and created a class to handle serial COM ports. Please note I am using DllImport to import the kernel32.dll 

MC++
// Header File
__gc class CSerialPort
{
public:
    CSerialPort(void);
    __nogc struct DCB
    {
        int DCBlength;
        int BaudRate;
        int fBinary;
        int fParity;
        int fOutxCtsFlow;
        int fOutxDsrFlow;
        int fDtrControl;
        int fDsrSensitivity;
        int fTXContinueOnXoff;
        int fOutX;
        int fInX;
        int fErrorChar;
        int fNull;
        int fRtsControl;
        int fAbortOnError;
        int fDummy2;
        unsigned short wReserved;
        unsigned short XonLim;
        unsigned char ByteSize;    //byte
        unsigned char Parity; // byte
        unsigned char StopBits;    //byte
        char XonChar;
        char XoffChar;
        char ErrorChar;
        char EofChar;
        char EvtChar;
        unsigned short wReserved1;
    };

    bool    Open( char *szComPort);
    void    Write(String __gc * buf);
    String  *Read();
    void    Close();

private:    
    FileStream    * m_MyFileStream;
    StreamWriter * m_MyStreamWriter;
    StreamReader * m_MyStreamReader;
    
    static long GENERIC_READ  = 0x80000000L;
    static long GENERIC_WRITE = 0x40000000L;

    static int OPEN_ALWAYS = 4;

    static int FILE_FLAG_NO_BUFFERING = 0x20000000;
    static int FILE_FLAG_OVERLAPPED   = 0x40000000;

};

namespace MyKernel
{
[DllImport("kernel32.dll")]
extern bool SetCommState(System::IntPtr hFile, CSerialPort::DCB * lpDBC);
[DllImport("kernel32.dll")]
extern int CreateFile( char * lpFileName , int dwDesiredAccess, int dwShareMode,
  IntPtr lpSecurityAttributes, int dwCreationDisposition,
  int dwFlagsAndAttributes, IntPtr hTemplateFile );

}

Also note that I am creating a new namespace to use the imported functions from kernel32.dll

This is the cpp file:

MC++
CSerialPort::CSerialPort(void)
{
}

bool CSerialPort::Open( char *szComPort)
{
    int handle;
            
    handle = MyKernel::CreateFile(
        szComPort,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_ALWAYS,
        FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED,
        NULL);

    try
    {
        IntPtr    pCom(handle);
        m_MyFileStream = new FileStream(pCom, 
                                        FileAccess::ReadWrite, 
                                        true, 1000, true);        
    }

    catch (Exception  * e ) {
        Console::WriteLine(e->ToString());
          return false;
      }

    
    DCB    * CommSettings = new DCB();
    CommSettings->DCBlength = sizeof(CommSettings);
    CommSettings->BaudRate  = 38400;
    CommSettings->ByteSize  = 8;
    CommSettings->Parity    = 0;
    CommSettings->StopBits    = 1;

    MyKernel::SetCommState(m_MyFileStream->get_Handle(), 
                           CommSettings);
    

    try
    {
        m_MyStreamReader = new StreamReader(m_MyFileStream);
    }

    catch (Exception  * e ) {
        Console::WriteLine(e->ToString());
          return false;
      }

    if ( m_MyFileStream->get_CanWrite() )
    {
        try
        {
            m_MyStreamWriter = new StreamWriter(m_MyFileStream);
        }

        catch (Exception  * e ) {
            Console::WriteLine(e->ToString());
            return false;
        }
    }

    return true;
}

void CSerialPort::Write(String __gc * buf)
{
    try
    {
        m_MyStreamWriter->Write(buf);
        m_MyStreamWriter->Flush();    
        
    }

    catch (Exception  * e ) {
        Console::WriteLine(e->ToString());    
      }
}

String  * CSerialPort::Read()
{
    String    *buf;
    
    buf = m_MyStreamReader->ReadLine();

    return (buf);
}

void CSerialPort::Close()
{
    m_MyStreamWriter->Close();
    m_MyStreamReader->Close();
    m_MyFileStream->Close();
}

To use it:

CSerialPort * pSerial = new CSerialPort;

pSerial->Open(S"COM2:");
Console::WriteLine(pSerial->Read());

We open COM port 2 and we wait to read a LINE with \r\n or \n. If you waiting for bytes you need to change m_MyStreamReader->ReadLine() to m_MyStreamReader->Read().

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Al is just another Software Engineer working in C++, ASp.NET and C#. Enjoys snowboarding in Big Bear, and wait patiently for his daughters to be old enough to write code and snowboard.

Al is a Microsoft ASP.NET MVP

Blog

Comments and Discussions

 
GeneralRe: using this class with visual c++ Pin
wadegiles6-Jul-05 5:54
wadegiles6-Jul-05 5:54 
QuestionCan also use Createfile to get handle... Pin
nutcase23-Dec-02 3:43
nutcase23-Dec-02 3:43 
AnswerRe: Can also use Createfile to get handle... Pin
Dan Neely9-May-06 3:07
Dan Neely9-May-06 3:07 
GeneralReading problems Pin
DFetterman2-Aug-02 11:55
DFetterman2-Aug-02 11:55 
GeneralRe: Reading problems Pin
wadegiles6-Jul-05 6:09
wadegiles6-Jul-05 6:09 
Generalstruct BUG in code above Pin
14-Jun-02 13:29
suss14-Jun-02 13:29 
GeneralRe: struct BUG in code above Pin
m3cardriver9-Jul-02 20:48
m3cardriver9-Jul-02 20:48 
GeneralRe: struct BUG in code above Pin
missyouvermuch30-Jul-03 21:48
sussmissyouvermuch30-Jul-03 21:48 
GeneralRe: struct BUG in code above Pin
cnall518-Sep-03 8:07
cnall518-Sep-03 8:07 
GeneralRe: struct BUG in code above Pin
Kimon R.12-Jan-05 6:24
Kimon R.12-Jan-05 6:24 
GeneralGood Article... but Pin
NormDroid24-May-02 8:19
professionalNormDroid24-May-02 8:19 
GeneralRe: Good Article... but Pin
Albert Pascual24-May-02 8:46
sitebuilderAlbert Pascual24-May-02 8:46 
GeneralRe: Good Article... but Pin
wadegiles6-Jul-05 6:07
wadegiles6-Jul-05 6:07 
GeneralDCB - Bitfield Pin
cabo20-Apr-02 5:15
cabo20-Apr-02 5:15 
GeneralRe: DCB - Bitfield Pin
Albert Pascual22-Apr-02 6:21
sitebuilderAlbert Pascual22-Apr-02 6:21 
GeneralRe: DCB - Bitfield Pin
BenDi20-May-03 2:48
BenDi20-May-03 2:48 
GeneralRe: DCB - Bitfield Pin
Albert Pascual20-May-03 5:51
sitebuilderAlbert Pascual20-May-03 5:51 
GeneralWooohoo! Pin
Nick Hodapp17-Apr-02 14:59
sitebuilderNick Hodapp17-Apr-02 14:59 
GeneralRe: Wooohoo! Pin
Nish Nishant17-Apr-02 15:40
sitebuilderNish Nishant17-Apr-02 15:40 
GeneralRe: Wooohoo! Pin
Nick Hodapp17-Apr-02 17:48
sitebuilderNick Hodapp17-Apr-02 17:48 
GeneralRe: Wooohoo! Pin
Chris Maunder17-Apr-02 17:52
cofounderChris Maunder17-Apr-02 17:52 
GeneralRe: Wooohoo! Pin
Nish Nishant17-Apr-02 18:19
sitebuilderNish Nishant17-Apr-02 18:19 

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

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