⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cncomm.h

📁 cnComm实现串口类
💻 H
📖 第 1 页 / 共 2 页
字号:
			ptr->Lock();
		}
		~InnerLock()
		{
			ptr->Unlock();
		}
	};

	//锁定资源
	void Lock()
	{
		::EnterCriticalSection(&_Mutex);
	}
	void Unlock()
	{
		::LeaveCriticalSection(&_Mutex);
	}
	//DTR 电平控制
	bool SetDTR(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) != 0 : false;
	}
	//RTS 电平控制
	bool SetRTS(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) != 0 : false;
	}
	//
	bool SetBreak(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) != 0 : false;
	}
	//辅助线程控制 建监视线程
	bool BeginThread() 
	{
		if(!IsThreadRunning()) 
		{
			_fRunFlag = true;
			_hThreadHandle = NULL;
			
			#ifdef _MT
			unsigned int id;
			_hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, CommThreadProc, this, 0, &id);
			#else
			DWORD id;
			_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0, &id); 
			#endif
			
			return (_hThreadHandle != NULL); 
		}
		return false;
	}
	//暂停监视线程
	inline bool SuspendThread()
	{
		return IsThreadRunning() ? ::SuspendThread(_hThreadHandle) != 0xFFFFFFFF : false;
	}
	//恢复监视线程
	inline bool ResumeThread()
	{
		return IsThreadRunning() ? ::ResumeThread(_hThreadHandle) != 0xFFFFFFFF : false;
	}
	//终止线程
	bool EndThread(DWORD dwWaitTime = 100)
	{
		if(IsThreadRunning()) 
		{
			_fRunFlag = false;
			::SetCommMask(_hCommHandle, 0);
			::SetEvent(_WaitOverlapped.hEvent);
			if(::WaitForSingleObject(_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0)
				if(!::TerminateThread(_hThreadHandle, 0))
					return false;
				
				::CloseHandle(_hThreadHandle);
				::ResetEvent(_WaitOverlapped.hEvent);
				
				_hThreadHandle = NULL;
				
				return true;
		}
		return false;
	}
	
protected:

	volatile DWORD _dwPort;   //串口号
	volatile HANDLE _hCommHandle;  //串口句柄
	char _szCommStr[20];  //保存COM1类似的字符串
	
	DCB _DCB;  //波特率,停止位,等   
	COMMTIMEOUTS _CO;  //超时结构   
	
	DWORD _dwIOMode;  // 0 同步  默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步
	OVERLAPPED _ReadOverlapped, _WriteOverlapped; // 重叠I/O
	
	volatile HANDLE _hThreadHandle; //辅助线程
	volatile HWND _hNotifyWnd;  // 通知窗口
	volatile DWORD _dwNotifyNum; //接受多少字节(>=_dwNotifyNum)发送通知消息
	volatile DWORD _dwMaskEvent; //监视的事件
	volatile bool _fRunFlag;  //线程运行循环标志
	bool _fAutoBeginThread;  //Open() 自动 BeginThread();
	OVERLAPPED _WaitOverlapped;  //WaitCommEvent use
	
	//初始化
	virtual void Init() 
	{
		memset(_szCommStr, 0, 20);
		memset(&_DCB, 0, sizeof(_DCB));
		_DCB.DCBlength = sizeof(_DCB);
		_hCommHandle = INVALID_HANDLE_VALUE;
		
		memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
		memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
		
		_ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
		assert(_ReadOverlapped.hEvent != NULL); 
		
		_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
		assert(_WriteOverlapped.hEvent != NULL);
		
		_hNotifyWnd = NULL;
		_dwNotifyNum = 0;
		_dwMaskEvent = DEFAULT_COM_MASK_EVENT;
		_hThreadHandle = NULL;
		
		memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
		_WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
		assert(_WaitOverlapped.hEvent != NULL); 

		::InitializeCriticalSection(&_Mutex);
	} 
	//析构
	virtual void Destroy()
	{
		if(_ReadOverlapped.hEvent != NULL)
			CloseHandle(_ReadOverlapped.hEvent);
		
		if(_WriteOverlapped.hEvent != NULL)
			CloseHandle(_WriteOverlapped.hEvent);
		
		if(_WaitOverlapped.hEvent != NULL)
			CloseHandle(_WaitOverlapped.hEvent);

		::DeleteCriticalSection(&_Mutex);
	}
	//绑定串口
	void BindCommPort(DWORD dwPort)
	{
		assert(dwPort >= 1 && dwPort <= 1024);
		
		char p[5];
		
		_dwPort = dwPort;
		strcpy(_szCommStr, "\\\\.\\COM"); 
		ltoa(_dwPort, p, 10);
		strcat(_szCommStr, p);
	}
	//打开串口
	virtual bool OpenCommPort()
	{
		if(IsOpen())
			Close();
		
		_hCommHandle = ::CreateFile(
			_szCommStr,
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | _dwIOMode, 
			NULL
			);
		
		if(_fAutoBeginThread)
		{
			if(IsOpen() && BeginThread())
				return true;
			else
			{
				Close();  //创建线程失败
				return false;
			}
		}
		return IsOpen();
	}
	//设置串口
	virtual bool SetupPort()
	{
		if(!IsOpen())
			return false;
		
		
		if(!::SetupComm(_hCommHandle, 4096, 4096))
			return false; 
		
		
		if(!::GetCommTimeouts(_hCommHandle, &_CO))
			return false;
		_CO.ReadIntervalTimeout = 0;
		_CO.ReadTotalTimeoutMultiplier = 1;
		_CO.ReadTotalTimeoutConstant = 1000;
		_CO.WriteTotalTimeoutMultiplier = 1;
		_CO.WriteTotalTimeoutConstant = 1000;
		if(!::SetCommTimeouts(_hCommHandle, &_CO))
			return false; 
		
		
		if(!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
			return false; 
		
		return true;
	} 
	
	//---------------------------------------threads callback-----------------------------------------------------
	//线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展       
	virtual void OnReceive()//EV_RXCHAR
	{
		if(::IsWindow(_hNotifyWnd))
			::PostMessage(_hNotifyWnd, ON_COM_RECEIVE, WPARAM(_dwPort), LPARAM(0));
	}
	
	virtual void OnDSR()
	{
		if(::IsWindow(_hNotifyWnd))
		{
			DWORD Status;
			if(GetCommModemStatus(_hCommHandle, &Status))
				::PostMessage(_hNotifyWnd, ON_COM_DSR, WPARAM(_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0));
		}
	}
	
	virtual void OnCTS()
	{
		if(::IsWindow(_hNotifyWnd))
		{
			DWORD Status;
			if(GetCommModemStatus(_hCommHandle, &Status))
				::PostMessage(_hNotifyWnd, ON_COM_CTS, WPARAM(_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0));
		}
	}
	
	virtual void OnBreak()
	{
		if(::IsWindow(_hNotifyWnd))
		{
			::PostMessage(_hNotifyWnd, ON_COM_BREAK , WPARAM(_dwPort), LPARAM(0));
		}
	}
	
	virtual void OnTXEmpty()
	{
		if(::IsWindow(_hNotifyWnd))
			::PostMessage(_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(_dwPort), LPARAM(0));
	}
	
	virtual void OnError()
	{
		DWORD dwError;
		::ClearCommError(_hCommHandle, &dwError, NULL);
		if(::IsWindow(_hNotifyWnd))
			::PostMessage(_hNotifyWnd, ON_COM_ERROR, WPARAM(_dwPort), LPARAM(dwError));
	}
	
	virtual void OnRing()
	{
		if(::IsWindow(_hNotifyWnd))
			::PostMessage(_hNotifyWnd, ON_COM_RING, WPARAM(_dwPort), LPARAM(0));
	}
	
	virtual void OnRLSD()
	{
		if(::IsWindow(_hNotifyWnd))
			::PostMessage(_hNotifyWnd, ON_COM_RLSD, WPARAM(_dwPort), LPARAM(0));
	}
	
	virtual DWORD ThreadFunc()
	{
		if(!::SetCommMask(_hCommHandle, _dwMaskEvent))
		{
			char szBuffer[256];
			_snprintf(szBuffer, 255, "%s(%d) : COM%d Call WINAPI SetCommMask(%x, %x) Fail, thread work invalid! GetLastError() = %d;",
				__FILE__, __LINE__, _dwPort, _hCommHandle, _dwMaskEvent, GetLastError());
			MessageBox(NULL, szBuffer, "Class cnComm", MB_OK);
			return 1;
		}
		
		COMSTAT Stat;
		DWORD dwError;
		
		for(DWORD dwLength, dwMask = 0; _fRunFlag && IsOpen(); dwMask = 0)
		{
			if(!::WaitCommEvent(_hCommHandle, &dwMask, &_WaitOverlapped))
			{
				if(::GetLastError() == ERROR_IO_PENDING)// asynchronous
					::GetOverlappedResult(_hCommHandle, &_WaitOverlapped, &dwLength, TRUE);
				else
					continue;
			}
			
			if(dwMask == 0)
				continue;
			
			switch(dwMask)
			{
			case EV_RXCHAR :
				::ClearCommError(_hCommHandle, &dwError, &Stat);
				if(Stat.cbInQue >= _dwNotifyNum)
					OnReceive();
				break;
				
			case EV_TXEMPTY :
				OnTXEmpty();
				break;
				
			case EV_CTS :
				OnCTS();
				break;
				
			case EV_DSR :
				OnDSR();
				break;
				
			case EV_RING :
				OnRing();
				break;
				
			case EV_RLSD :
				OnRLSD();
				break;
				
			case EV_BREAK:
				OnBreak();
				break;
				
			case EV_ERR :
				OnError();
				break;
				
			}//case
        }//for
		return 0;
	}
	
private:  //the function protected 
	
	cnComm(const cnComm&);
	cnComm &operator = (const cnComm&);
	CRITICAL_SECTION _Mutex;
	
	//base function for thread
	#ifdef _MT
	static UINT APIENTRY CommThreadProc(LPVOID lpPara)
	#else
	static DWORD WINAPI CommThreadProc(LPVOID lpPara)
	#endif
	{
		return ( (cnComm *)lpPara )->ThreadFunc();
	}
};

#endif //_CN_COMM_H_

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -