之前对于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;
}