posts - 45,  comments - 232,  trackbacks - 0

   源代码请从这里下载:http://www.cppblog.com/Files/dyj057/Midapexsoft.IO.SerialPort.rar,请使用VS2005打开.
       我写的CAsyncSerialPort类是一个MFC的类,怎么才能使它在托管代码中使用呢?方法有两个:

l         把类的功能封装成DLL中的API,然后通过平台调用实现。这个方法我以前写过,就不说了,适合在.NET 1.0 1.1中使用。

l         使用C++/CLICAsyncSerialPort转换成一个托管类,然后供C#等代码使用,这个方法适合在.NET 2.0中使用,下面介绍这个方法。

下面写出步骤:

第一步:在VS2005中,使用C#创建一个包含串口通讯的接口,生成DLL组件。

第二步:创建一个C++/CLI的组件工程,一定要生成DLL的工程,不能是exe然后引入上面创建的接口DLL,实现一个SerialPortX类。

通过上面的方法,就把基于MFCCAsyncSerialPort转化成了实现了ISerialPort接口的托管类SerialPortX。这个对于许多以前C++写的代码转到.NET 2.0中使用,都有借鉴意义。我还使用这个方法,把一个OPC ServerMFC实现,转换到了.NET 2.0,很好用的。^:^

最后,我使用SerialPortXVS2005中写了一个串口通讯工具。

界面效果如下:

关键代码如下:

using System;

using System.IO.Ports;

 

namespace Midapexsoft.IO.Ports

{

       /// <summary>

       /// Interface of serial port

       /// </summary>

    public interface ISerialPort : IDisposable, Midapexsoft.IO.ITerminal

       {

              #region Property

 

        string PortName

              {

                     get;

                     set;

              }

 

              Parity Parity

              {

                     get;

                     set;

        }

 

        int DataBits

              {

                     get;

                     set;

              }

 

              StopBits StopBits

              {

                     get;

                     set;

              }

 

              StandardBaudRate BaudRate

              {

                     get;

                     set;

              }

 

              Handshake HandShake

              {

                     get;

                     set;

              }

 

              #endregion

       }

 

 

    /// <summary>

    /// Standard baud rate setting

    /// </summary>

    public enum StandardBaudRate

    {

        R110 = 110,

        R300 = 300,

        R600 = 600,

        R1200 = 1200,

        R2400 = 2400,

        R4800 = 4800,

        R9600 = 9600,

        R14400 = 14400,

        R19200 = 19200,

        R38400 = 38400,

        R57600 = 57600,

        R76800 = 76800,

        R115200 = 115200

    };

}

 

//SerialPortX.h

#pragma once

#include "AsyncSerialPort.h"

#include "RuntimeException.h"

#include "SerialPortX.h"

#include "RuntimeException.h"

 

using namespace System;

using namespace System::Collections;

 

class CSerialPortObserver;

 

namespace Midapexsoft

{

namespace IO

{

namespace Port

{

       public ref class SerialPortX: public IStartable, public ISerialPort

       {

       public:

              SerialPortX(void);

              ~SerialPortX(void);

 

              virtual void Stop();

             

              virtual void SerialPortX::Start();

 

              virtual void Write(array<byte> ^ data);

 

              virtual event BytesEventHandler^ OnWriteData

              {

                     void add(BytesEventHandler^ value)

                     {

                            writeDataHandler += value;

                     }

                     void remove(BytesEventHandler^ value)

                     {

                            writeDataHandler -= value;

                     }

                     void raise(Object^ sender, BytesEventArgs^ args)

                     {

                            if(writeDataHandler!=nullptr)

                            {

                                   //writeDataHandler->BeginInvoke(sender, args,nullptr,nullptr);

                                   writeDataHandler(sender,args);

                            }

                     }

              }

 

              virtual event BytesEventHandler^ OnReadData

              {

                     void add(BytesEventHandler^ value)

                     {

                            readDataHandler += value;

                     }

                     void remove(BytesEventHandler^ value)

                     {

                            readDataHandler -= value;

                     }

                     void raise(Object^ sender, BytesEventArgs^ args)

                     {

                            if(readDataHandler!=nullptr)

                            {

                                   //readDataHandler->BeginInvoke(sender, args,nullptr,nullptr);

                                   readDataHandler(sender,args);

                            }

                     }

              }

 

              virtual event MessageEventHandler^ OnError

              {

                     void add(MessageEventHandler^ value)

                     {

                            errorHandler += value;

                     }

                     void remove(MessageEventHandler^ value)

                     {

                            errorHandler -= value;

                     }

                     void raise(Object^ sender, MessageEventArgs^ args)

                     {

                            if(errorHandler!=nullptr)

                            {

                                   //errorHandler->BeginInvoke(sender, args,nullptr,nullptr);

                                   errorHandler(sender,args);

                            }

                     }

              }

 

              property String^ PortName

              {

                     virtual String^ get() { return name;}

                     virtual void set(String^ newName)

                     {

                            //Get port number

                            int portNumberIndex = newName->IndexOf("COM");

 

                            if(portNumberIndex!=0)

                            {

                                   throw gcnew Exception("Bad Port Name");

                            }

 

                            String^ portNumberS = newName->Substring(3);

                            portNumber = Convert::ToByte(portNumberS);

                            name= newName;

 

                     }

              }

 

              property Parity PortParity

              {

                     virtual Parity get() { return parity;}

                     virtual void set(Parity parity)

                     {

                            try

                            {

                                   if(IsOpen)

                                   {

 

                                          Hashtable^ parityTable = gcnew Hashtable();

                                          parityTable->Add(L"None", 2);

                                          parityTable->Add(L"Odd",3);

                                          parityTable->Add(L"Even",gcnew int(0) );

                                          parityTable->Add(L"Mark",1);

                                          parityTable->Add(L"Space",4);

 

                                          int parityMothord = (int) parityTable[parity.ToString()];

 

                                          port->SetParity((CSerialPort::Parity)parityMothord);

                                   }

 

                                   this->parity = parity;

                            }

                            catch (CRuntimeException* e)

                            {

                                   String^ info = gcnew String((LPCTSTR)e->GetErrorMessage());

                                   throw gcnew Exception( info );

                                   e->Delete();

                            }

                           

                     }

              }

 

              property byte DataBytes

              {

                     virtual byte get() { return dataBytes;}

                     virtual void set(byte dataBytes)

                     {

                            if(IsOpen)

                            {

                                   port->SetDataBytes(dataBytes);

                            }

 

                            this->dataBytes = dataBytes;

                     }

              }

 

              property bool IsOpen

              {

                     virtual bool get() { return port->IsOpen() != 0;}

              }

 

              property StopBits PortStopBits

              {

                     virtual StopBits get() { return stopBits; }

                     virtual void set(StopBits stopBits)

                     {

                            try

                            {

                                   if(IsOpen)

                                   {

                                          port->SetStopBits((CSerialPort::StopBits)(int)stopBits);                                              

                                   }

 

                                   this->stopBits = stopBits;

                            }

                            catch (CRuntimeException* e)

                            {

                                   String^ info = gcnew String((LPCTSTR)e->GetErrorMessage());

                                   throw gcnew Exception( info );

                                   e->Delete();

                            }

                           

                     }

              }

 

              property StandardBaudRate BaudRate

              {

                     virtual StandardBaudRate get() { return this->baudRate; }

                     virtual void set(StandardBaudRate newBaudRate)

                     {

                            try

                            {

                                   if(IsOpen)

                                   {

                                          int baud = (int)newBaudRate;

                                          port->SetBaud(baud);

                                   }

 

                                   this->baudRate = newBaudRate;

                            }

                            catch (CRuntimeException* e)

                            {

                                   String^ info = gcnew String((LPCTSTR)e->GetErrorMessage());

                                   throw gcnew Exception( info );

                                   e->Delete();

                            }

                     }

              }

 

              property Handshake PortHandShake

              {

                     virtual Handshake get() { return this->handshake;}

                     virtual void set( Handshake newHandShake)

                     {

                            try

                            {

                                   if(IsOpen)

                                   {

                                          Hashtable ^ handshakeTable = gcnew Hashtable();

                                          handshakeTable->Add("None",gcnew int(0));

                                          handshakeTable->Add("XonXoff",5);

                                          handshakeTable->Add("CtsRts",1);

                                          handshakeTable->Add("DsrDtr",4);

 

                                          //Handshake

                                          int handshake = (int)handshakeTable[ newHandShake.ToString() ];

                                          port->SetFlowControl((CSerialPort::FlowControl)handshake);

 

                                   }

                                   this->handshake = newHandShake;

                            }

                            catch (CRuntimeException* e)

                            {

                                   String^ info = gcnew String((LPCTSTR)e->GetErrorMessage());

                                   throw gcnew Exception( info );

                                   e->Delete();

                            }

                     }

              }

              property bool CanStart

              {

                     virtual bool get() { return canStart;}

                     virtual void set(bool canStart) { this->canStart = canStart; }

              }

 

              property bool IsRun

              {

                     virtual bool get() { return isRun;}

              }

 

              virtual event EventHandler<StartableArgs^>^ OnStartableStatueChange

              {

                     void add(EventHandler<StartableArgs^>^ value)

                     {

                            statusChangeHandler+= value;

                     }

                     void remove(EventHandler<StartableArgs^>^ value)

                     {

                            statusChangeHandler -= value;

                     }

                     void raise(Object^ sender, StartableArgs^ args)

                     {

                            if(statusChangeHandler!=nullptr)

                            {

                                   statusChangeHandler->BeginInvoke(sender,args,nullptr,nullptr);

                            }

                     }

              }

 

       internal:

 

              void OnPortWriteData(array<Byte>^ data)

              {

                     OnWriteData(this, gcnew BytesEventArgs(data));

              }

              void OnPortReceiveData(array<Byte>^ data)

              {

                     OnReadData(this, gcnew BytesEventArgs(data));

              }

 

              void ReportError(String^ errorMessage)

              {

                     OnError(this, gcnew MessageEventArgs(errorMessage));

              }

 

              void SetRunStatus(bool isRun)

              {

                     this->isRun = isRun;

                     OnStartableStatueChange(this, gcnew StartableArgs(this));

              }

 

       private:

              CAsyncSerialPort* port;

              CSerialPortObserver* observer;

 

       private:

              String^ name;

              Parity parity;

              byte dataBytes;

              StandardBaudRate baudRate;

              Handshake handshake;

              StopBits stopBits;

              byte portNumber;

              bool canStart;

              bool isRun;

 

              BytesEventHandler^ writeDataHandler;

              BytesEventHandler^ readDataHandler;

              MessageEventHandler^ errorHandler;

 

               EventHandler<StartableArgs^>^ statusChangeHandler;

 

       };

}

 

}

}

 

posted on 2007-08-24 09:28 天下无双 阅读(2231) 评论(1)  编辑 收藏 引用 所属分类: C/C++

FeedBack:
# re: 串口编程(2)--在托管代码中使用异步串口类(使用C++/CLI实现转换)
2007-08-30 17:54 | C++面试题
文章好长,看的好累。呵呵  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



常用链接

留言簿(15)

随笔分类

随笔档案

相册

我的其它领域Blog

搜索

  •  

积分与排名

  • 积分 - 203929
  • 排名 - 129

最新评论

阅读排行榜

评论排行榜