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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章