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

📄 serial.cpp

📁 VC网络程序设计实例导航配套代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Serial.cpp: implementation of the CSerial class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Serial.h"


// ---------------------------CSerial类---------------------------------//


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::CSerial
// 功能描述     : 构造函数,用来初始化整个实例对象
// 参数         : BOOL bNeedThread			// 指定是否需要创建辅助线程
// 返回值       : None
//
///////////////////////////////////////////////////////////////////////
CSerial::CSerial(BOOL bNeedThread)
{
	m_hCom = INVALID_HANDLE_VALUE;
	m_bExit = FALSE;
	m_hThread = NULL;
	m_dwMaskEvent = DEFAULT_COM_MASK_EVENT; 
	m_dwNotifyNum = 0;
	m_dcb.DCBlength = sizeof(DCB);
	m_hNotifyWnd = NULL;

	// 初始化重叠结构
	memset(&m_ReadOl, 0, sizeof(m_ReadOl));
	memset(&m_WriteOl, 0, sizeof(m_WriteOl));
	memset(&m_WaitOl, 0, sizeof(m_WaitOl));
	m_ReadOl.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	m_WriteOl.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	m_WaitOl.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	m_bNeedThread = bNeedThread ;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::~CSerial
// 功能描述     : 析构函数,用来销毁整个实例对象
// 返回值       : None
//
///////////////////////////////////////////////////////////////////////
CSerial::~CSerial()
{
	// 关闭串口
	Close();
	// 释放事件对象
	::CloseHandle(m_ReadOl.hEvent);
	::CloseHandle(m_WriteOl.hEvent);
	::CloseHandle(m_WaitOl.hEvent);
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::Open
// 功能描述     : 打开端口
// 参数         : DWORD dwPort			要打开的COM端口
// 参数         : DWORD dwBaudRate		要设置的波特率
// 返回值       : BOOL					是否成功
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::Open(DWORD dwPort, DWORD dwBaudRate)
{
	if(dwPort<1 || dwPort>1024)
	{
		return FALSE;
	}

	// 打开串口
	if(!OpenCommPort(dwPort))
	{
		return FALSE;
	}

	// 采用默认设置
	// 设置输入输出缓冲区大小
	if(!::SetupComm(m_hCom, 4096, 4096))
	{
		return FALSE;
	}
	// 设置超时
	COMMTIMEOUTS co;
	if(!::GetCommTimeouts(m_hCom, &co))
		return FALSE;

	co.ReadIntervalTimeout = 0;
	co.ReadTotalTimeoutMultiplier = 1;
	co.ReadTotalTimeoutConstant = 1000;
	co.WriteTotalTimeoutMultiplier = 1;
	co.WriteTotalTimeoutConstant = 1000;
	if(!::SetCommTimeouts(m_hCom, &co))
		return FALSE;
	// 清空输入输出缓冲区
	if(!::PurgeComm(m_hCom, 
		PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR))
		return FALSE;


	return SetState(dwBaudRate);
}



///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::Purge
// 功能描述     : 清空输入输出缓冲区
// 参数         : DWORD dwFlags				 清空属性
// 返回值       : BOOL						 是否成功
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::Purge(DWORD dwFlags)
{
	if(!IsOpen())
		return FALSE;

	return ::PurgeComm(m_hCom, dwFlags);
}



///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::OpenCommPort	
// 功能描述     : 打开指定端口
// 参数         : DWORD dwPort		要打开的端口
// 返回值       : BOOL				是否成功		
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::OpenCommPort(DWORD dwPort)
{
	if(m_hCom != INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	strcpy(m_szComm, "\\\\.\\COM");
	char sz[5];
	ltoa(dwPort, sz, 10);

	strcat(m_szComm, sz);


	m_hCom = ::CreateFile(m_szComm, GENERIC_READ | GENERIC_WRITE, 
						0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if(m_hCom == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	
	if(m_bNeedThread)
	{
		DWORD dwId;
		m_bExit = FALSE;
		m_hThread = ::CreateThread(NULL, 0, SerialThreadProc, this, 0, &dwId);
		if(m_hThread == NULL)
		{
			::CloseHandle(m_hCom);
			m_hCom = INVALID_HANDLE_VALUE; // 
			return FALSE;
		}
	}

	// here to 
	return TRUE;
}



///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::Close
// 功能描述     : 关闭打开的端口
// 返回值       : void 
//
///////////////////////////////////////////////////////////////////////
void CSerial::Close()
{
	if(!IsOpen())
		return;

	if(m_bNeedThread)
	{
		// wait thread to exit
		m_bExit = TRUE;
		::SetEvent(m_WaitOl.hEvent);
		DWORD dwExitCode;
		int n = 0;
		do
		{
			::Sleep(10);
			if(n++ > 5)
				break;
		}while(!::GetExitCodeThread(m_hThread, &dwExitCode));
		
		::CloseHandle(m_hThread);
		m_hThread = NULL;
	}

	::CloseHandle(m_hCom);
	m_hCom = INVALID_HANDLE_VALUE;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetState
// 功能描述     : 设置状态
// 参数         : DWORD dwBaudRate			指定波特率
// 参数         : DWORD dwByteSize          指定字节长度
// 参数         : DWORD dwPatity			指定校验位
// 参数         : DWORD dwStopBits          指定停止位
// 返回值       : BOOL						是否成功
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::SetState(DWORD dwBaudRate, 
					   DWORD dwByteSize, DWORD dwPatity, DWORD dwStopBits)
{
	if(IsOpen())
	{
		if(!::GetCommState(m_hCom, &m_dcb))
		{
			return FALSE;
		}
		m_dcb.BaudRate = dwBaudRate;
		m_dcb.ByteSize = (UCHAR)dwByteSize;
		m_dcb.StopBits = (UCHAR)dwStopBits;
		m_dcb.Parity = (UCHAR)dwPatity;
		if(dwPatity != NOPARITY)
			m_dcb.fParity = TRUE;

		return ::SetCommState(m_hCom, &m_dcb);
	}
	return FALSE;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::ThreadProc
// 功能描述     : 线程函数
// 返回值       : DWORD       线程退出代码
//
///////////////////////////////////////////////////////////////////////
DWORD CSerial::ThreadProc()
{
	if(!::SetCommMask(m_hCom, m_dwMaskEvent))
	{
		::MessageBox(m_hNotifyWnd, " SetCommMask failed", "", 0);
		return -1;
	}

	DWORD dwError, dwMask, dwTrans;
	COMSTAT Stat;


	while(!m_bExit)
	{
		dwMask = 0;
		if(!::WaitCommEvent(m_hCom, &dwMask, &m_WaitOl))
		{
			if(::GetLastError() == ERROR_IO_PENDING)
			{
				::GetOverlappedResult(m_hCom, &m_WaitOl, &dwTrans, TRUE);
			}
			else
				continue;
		}

		switch(dwMask)
		{
			case EV_RXCHAR:
				{
					// 有数据进来,  获取数据大小
					::ClearCommError(m_hCom, &dwError, &Stat);
					if(Stat.cbInQue >= m_dwNotifyNum)
					{
						OnReceive();
					}
				}
				break;
			
			case EV_TXEMPTY:		// 输出缓冲区中的最后一个字符被发送了
				OnTXEmpty();
				break;
			case EV_CTS:			// clear-to-send信号改变
				OnCTS();
				break;

			case EV_DSR:			// data-set-ready信号改变
				OnDSR();
				break;

			case EV_RING:		
				OnRing();
				break;

			case EV_RLSD:		
				OnRLSD();
				break;

			case EV_BREAK:
				OnBreak();
				break;

			case EV_ERR:
				OnError();
				break;
			default:
				continue;
		}
	}
	return 0;
}
	

///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SerialThreadProc
// 功能描述     : 
// 参数         : LPVOID lpParam
// 返回值       : DWORD WINAPI 
//
///////////////////////////////////////////////////////////////////////
DWORD WINAPI CSerial::SerialThreadProc(LPVOID lpParam)
{
	CSerial *pThis = (CSerial *)lpParam;
	return pThis->ThreadProc();
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::ReadData
// 功能描述     : 读取指定长度的数据
// 参数         : LPVOID Buffer					数据缓冲区
// 参数         : DWORD dwReadLen				要读取的长度
// 参数         : DWORD dwWaitTime				要等待时间
// 返回值       : BOOL							是否成功
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::ReadData(LPVOID Buffer, DWORD dwReadLen, DWORD dwWaitTime)
{
	if(!IsOpen())
		return FALSE;

	COMSTAT Stat;
	DWORD dwError;
	BOOL bError = FALSE;  // 

	DWORD dwRead = 0;
	while(TRUE)
	{
		// 检查是否有错误发生
		if(::ClearCommError(m_hCom, &dwError, &Stat))
		{
			if(dwError > 0)
			{
				 bError = TRUE;  
			}
			
			// 查看输入缓冲区中的数据长度
			if(Stat.cbInQue >= dwReadLen)
			{
				// 读取输入缓冲区中的数据
				dwRead = Read(Buffer, dwReadLen, dwWaitTime);
				break;
			}
			else
			{
				::Sleep(10);
			 	dwWaitTime -= 10;
			}
		}
		else
		{
			return FALSE;
		}

		if(dwWaitTime <= 0)
			return FALSE;
	}


	if(dwRead == dwReadLen && !bError)
		return TRUE;
	else
		return FALSE; 
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::Read
// 功能描述     : 读取缓冲区中的数据
// 参数         : LPVOID Buffer
// 参数         : DWORD dwBufferLen
// 参数         : DWORD dwWaitTime
// 返回值       : DWORD 
//
///////////////////////////////////////////////////////////////////////
DWORD CSerial::Read(LPVOID Buffer, DWORD dwBufferLen, DWORD dwWaitTime)
{
	if(!IsOpen())
		return 0;


	COMSTAT Stat;
	DWORD dwError;
	// 有错误发生!
	if(::ClearCommError(m_hCom, &dwError, &Stat) && dwError > 0)
	{
		// 清除缓冲区,清除所有抛出的读操作
		::PurgeComm(m_hCom, PURGE_RXABORT|PURGE_RXCLEAR);
		return 0;
	}

	if(!Stat.cbInQue)
	{
		return 0;
	}

	DWORD dwReadLen = 0;
	if(dwBufferLen > Stat.cbInQue)
		dwBufferLen = Stat.cbInQue;

	if(!::ReadFile(m_hCom, Buffer, dwBufferLen, &dwReadLen, &m_ReadOl))
	{
		if(::GetLastError() == ERROR_IO_PENDING)
		{
			// 等待操作完成
			::WaitForSingleObject(m_ReadOl.hEvent, dwWaitTime);
			// 获取操作结果
			if(!::GetOverlappedResult(m_hCom, &m_ReadOl, &dwReadLen, FALSE))
			{
				if(::GetLastError() != ERROR_IO_INCOMPLETE)
				{
					dwReadLen  = 0;
				}
			}
		}
		else
		{
			dwReadLen  = 0;
		}
	}
	return dwReadLen;
}



///////////////////////////////////////////////////////////////////////
//
// 函数名       : *CSerial::ReadString
// 功能描述     : 读取字符串
// 参数         : TCHAR *szBuffer
// 参数         : DWORD dwBufferLen
// 参数         : DWORD dwWaitTime
// 返回值       : TCHAR 
//
///////////////////////////////////////////////////////////////////////
TCHAR *CSerial::ReadString(TCHAR *szBuffer, DWORD dwBufferLen, DWORD dwWaitTime)
{
	DWORD dwRead = Read(szBuffer, dwBufferLen - 1, dwWaitTime);
	szBuffer[dwRead] = '\0';
	return szBuffer;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::Write
// 功能描述     : 写入指定长度的数据
// 参数         : LPVOID Buffer			数据缓冲区
// 参数         : DWORD dwBufferLen		缓冲区长度
// 返回值       : DWORD					实际写入的数量
//
///////////////////////////////////////////////////////////////////////
DWORD CSerial::Write(LPVOID Buffer, DWORD dwBufferLen)
{
	if(!IsOpen())
		return 0;


	COMSTAT Stat;
	DWORD dwError;
	// 有错误发生!
	if(::ClearCommError(m_hCom, &dwError, &Stat) && dwError > 0)
	{
		// 清除缓冲区,清除所有抛出的读操作
		::PurgeComm(m_hCom, PURGE_RXABORT|PURGE_RXCLEAR);
		return 0;
	}

	DWORD dwWrite = 0;
	if(!::WriteFile(m_hCom, Buffer, dwBufferLen, &dwWrite, &m_WriteOl))
	{
		if( ::GetLastError() == ERROR_IO_PENDING)
		{
			::GetOverlappedResult(m_hCom, &m_WriteOl, &dwWrite, TRUE);
		}
	}
	return dwWrite;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::WriteString
// 功能描述     : 写入字符串
// 参数         : LPTSTR szBuffer
// 返回值       : DWORD 
//
///////////////////////////////////////////////////////////////////////
DWORD CSerial::WriteString(LPTSTR szBuffer)
{
	return Write(szBuffer, strlen(szBuffer));
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetBufferSize
// 功能描述     : 设置缓冲区大小
// 参数         : DWORD dwInputSize
// 参数         : DWORD dwOutputSize
// 返回值       : BOOL 
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)
{
	return IsOpen() ? ::SetupComm(m_hCom, dwInputSize, dwOutputSize) : FALSE;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetWnd
// 功能描述     : 设置窗口句柄
// 参数         : HWND hWnd
// 返回值       : void 
//
///////////////////////////////////////////////////////////////////////
void CSerial::SetWnd(HWND hWnd)
{
	m_hNotifyWnd = hWnd;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetNotifyNum
// 功能描述     : 设置通知数量
// 参数         : DWORD dwNum
// 返回值       : void 
//
///////////////////////////////////////////////////////////////////////
void CSerial::SetNotifyNum(DWORD dwNum)
{
	m_dwNotifyNum = dwNum;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetTimeouts
// 功能描述     : 设置超时
// 参数         : LPCOMMTIMEOUTS lpCO
// 返回值       : BOOL 
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::SetTimeouts(LPCOMMTIMEOUTS lpCO)
{
	return IsOpen() ? ::SetCommTimeouts(m_hCom, lpCO) : FALSE;
}


///////////////////////////////////////////////////////////////////////
//
// 函数名       : CSerial::SetDTR
// 功能描述     : 
// 参数         : BOOL OnOrOff
// 返回值       : BOOL 
//
///////////////////////////////////////////////////////////////////////
BOOL CSerial::SetDTR(BOOL OnOrOff)
{
	return IsOpen() ? ::EscapeCommFunction(m_hCom, OnOrOff ? SETDTR:CLRDTR): FALSE;
}


⌨️ 快捷键说明

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