CnComm多线程串口通讯类的封装实现

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

3.CnComm多线程的串口类实现

CnComm串口通讯库v1.5 源码下载


发布了21 篇原创文章 · 获赞 49 · 访问量 13万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章