之前对于CnComm类库做过简单的分析,详见CnComm多线程串口通讯类解读CnComm是llbird开发的WINDOWS/WINCE 多线程串口通讯开源库,提供同步IO并发访问的支持,内存管理采用内存池技术,提供对于C++异常的支持。在实际的项目中,需要使用多个串口来收发消息,于是对于CnComm类做了简单的封装操作。
#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; }
#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; }