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

📄 cncomm.h

📁 根据网资整理的一个串口通信类
💻 H
📖 第 1 页 / 共 2 页
字号:
	}
//DTR 电平控制
	bool SetDTR(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR :CLRDTR): false;
	}
//RTS 电平控制
	bool SetRTS(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS :CLRRTS): false;
	}
//
	bool SetBreak(bool OnOrOff)
	{
		return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK: CLRBREAK): false;
	}
//辅助线程控制 建监视线程
	bool BeginThread()
	{
		if (!IsThreadRunning())
		{
			_fRunFlag = true;
			_hThreadHandle = NULL;
			DWORD id;
			_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0,&id);
			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

//初始化
	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 != INVALID_HANDLE_VALUE);

		_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
		assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);

		_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 != INVALID_HANDLE_VALUE);
	}
//析构
	void UnInit()
	{
		if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
			CloseHandle(_ReadOverlapped.hEvent);
		if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
			CloseHandle(_WriteOverlapped.hEvent);
		if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
			CloseHandle(_WaitOverlapped.hEvent);
	}
//绑定串口
	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 &);

//base function for thread
	static DWORD WINAPI CommThreadProc(LPVOID lpPara)
	{
		return ((cnComm*)lpPara)->ThreadFunc();
	}
};
#endif //_CN_COMM_H_

⌨️ 快捷键说明

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