之前對於CnComm類庫做過簡單的分析,詳見CnComm多線程串口通訊類解讀CnComm是llbird開發的WINDOWS/WINCE 多線程串口通訊開源庫,提供同步IO併發訪問的支持,內存管理採用內存池技術,提供對於C++異常的支持。在實際的項目中,需要使用多個串口來收發消息,於是對於CnComm類做了簡單的封裝操作。
- 實現對於CnComm串口類的封裝,提供基本的接口
- 通過串口管理類來實現對於串口的資源的管理
- 串口管理類採用單例模式實現
- 在VS2005下測試通過
1.串口管理類的實現,可增加爲多串口的管理類
#ifndef _COMM_MANAGE_H_
#define _COMM_MANAGE_H_
#include "commWrapper.h"
//串口管理類
class CommManage{
public:
static CommManage* Instance();
virtual ~CommManage();
public:
CommWrapper& commInstance(){return commInst;}
protected:
CommManage();
CommManage(const CommManage&);
CommManage& operator= (const CommManage&);
public:
CommWrapper commInst;
private:
static CommManage* _commMangeinstance;
};
#endif
#include "stdafx.h"
#include "CommManage.h"
CommManage* CommManage::_commMangeinstance = 0;
//設置串口模式
CommManage::CommManage()
{
}
CommManage::~CommManage()
{
}
CommManage* CommManage::Instance()
{
if(_commMangeinstance == 0)
{
_commMangeinstance = new CommManage();
}
return _commMangeinstance;
}
2.串口的封裝實現
#ifndef _COMM_WRAPPER_H_
#define _COMM_WRAPPER_H_
#include "CnComm.h"
//串口模塊
class CommWrapper
{
public:
CommWrapper();
virtual ~CommWrapper();
enum StringFormat{ASCII_FORMAT=0,HEX_FORMAT=1};
void initComm();
void setCommWnd(HWND hwnd);
bool openComm(DWORD port, DWORD baudrate);
void closeComm();
void sendtoDevice(CString& sendstr, int sendstrformat);
void sendasciitoDevice(CString& sendstr, CnComm& _Comm);
void sendhextoDevice(CString& sendstr, CnComm& _Comm);
char HexChar(char c);
int Str2Hex(CString str, char* data);
inline void setCommParam(DWORD port,DWORD baudrate);
inline bool iscommOpen();
inline CnComm& getCnComm();
inline DWORD getCommPort();
inline DWORD getBaudrate();
private:
CommWrapper(const CommWrapper&);
CommWrapper& operator = (const CommWrapper&);
protected:
CnComm commDevice;
DWORD devicePort;
DWORD baudRate;
CnComm::BlockBuffer rxCommBuf;
};
CnComm& CommWrapper::getCnComm(){return this->commDevice;}
DWORD CommWrapper::getCommPort(){return this->devicePort;}
DWORD CommWrapper::getBaudrate(){return this->baudRate;}
//獲取端口號和波特率
void CommWrapper::setCommParam(DWORD port,DWORD baudrate)
{
devicePort = port;
baudRate = baudrate;
}
//串口是否打開
bool CommWrapper::iscommOpen()
{
return commDevice.IsOpen();
}
#endif
#include "stdafx.h"
#include "commWrapper.h"
CommWrapper::CommWrapper()
{
initComm();
}
CommWrapper::~CommWrapper()
{
}
//初始化串口設置
void CommWrapper::initComm()
{
static int i=1;
commDevice.SetOption(commDevice.GetOption()|CnComm::EN_RX_BUFFER);
devicePort=i++;
baudRate = 9600;
rxCommBuf.SetMinBlockSize(4096);
}
//設置關聯消息的窗口句柄
void CommWrapper::setCommWnd(HWND hwnd)
{
commDevice.SetWnd(hwnd);
}
//打開串口
bool CommWrapper::openComm(DWORD port, DWORD baudrate)
{
setCommParam(port,baudrate);
if (!commDevice.IsOpen())
{
if (!commDevice.Open(devicePort,baudRate))
{
TCHAR szBuf[1024];
wsprintf(szBuf, _T("未能打開串口 COM%d ,請重新選擇串口"), devicePort);
AfxMessageBox(szBuf);
return false;
}
}
return true;
}
//關閉串口
void CommWrapper::closeComm()
{
if(commDevice.IsOpen())
{
commDevice.Close();
}
}
//發送串口消息
void CommWrapper::sendtoDevice(CString& sendstr,int sendstrformat)
{
if (sendstrformat == CommWrapper::ASCII_FORMAT)
{
sendasciitoDevice(sendstr, commDevice);
}
else if (sendstrformat == CommWrapper::HEX_FORMAT)
{
sendhextoDevice(sendstr, commDevice);
}
}
//字符串形式發送
void CommWrapper::sendasciitoDevice(CString& sendstr, CnComm& _Comm)
{
if (_Comm.IsOpen() == false)
{
return;
}
_Comm.FlushPort();
char* buffer = new char[sendstr.GetLength()*2+1];
#ifdef UNICODE
int len = wcstombs(buffer, (LPCTSTR)sendstr, sendstr.GetLength());
buffer[len]= 0;
#else
strcpy(buffer, (LPCTSTR)sendstr);
int len = sendstr.GetLength();
#endif
//! 重疊模式下或者緩衝區模式下 可以不檢查輸出返回值,並直接輸出
if (_Comm.IsOverlappedMode() || _Comm.IsTxBufferMode())
_Comm.Write(buffer);
else
{//! 阻塞非緩衝區模式 必須檢查返回值,確保數據完全發送出
for (int i = 0; i<len; i++ )
i += _Comm.Write(buffer + i, len - i);
}
delete[] buffer;
}
//16進制形式發送
void CommWrapper::sendhextoDevice(CString& sendstr, CnComm& _Comm)
{
_Comm.FlushPort();
char data[1024];
int len=Str2Hex(sendstr,data);
//! 重疊模式下或者緩衝區模式下 可以不檢查輸出返回值,並直接輸出
if (_Comm.IsOverlappedMode() || _Comm.IsTxBufferMode())
_Comm.Write(data, len);
}
//
char CommWrapper::HexChar(char c)
{
if((c>='0')&&(c<='9'))
return c-0x30;
else if((c>='A')&&(c<='F'))
return c-'A'+10;
else if((c>='a')&&(c<='f'))
return c-'a'+10;
else
return 0x10;
}
//將一個字符串作爲十六進制串轉化爲一個字節數組,字節間可用空格分隔,
//返回轉換後的字節數組長度,同時字節數組長度自動設置。
int CommWrapper::Str2Hex(CString str, char* data)
{
int t,t1;
int rlen=0;
int len=str.GetLength();
for(int i=0;i<len;)
{
char l,h=str[i];
if(h==' ')
{
i++;
continue;
}
i++;
if(i>=len)
break;
l=str[i];
t=HexChar(h);
t1=HexChar(l);
if((t==16)||(t1==16))
break;
else
t=t*16+t1;
i++;
data[rlen]=(char)t;
rlen++;
}
return rlen;
}