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

📄 serialport.cpp

📁 GSM通讯串口类,通过RS232串口与GSM MODEM连接,发送短信.
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	if(!::SetCommMask(m_hComm, dwEvtMask)) {
		TRACE(_T("Failed in call to SetCommMask"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::GetMask(DWORD& dwEvtMask)
{
	ASSERT(IsOpen());

	if(!::GetCommMask(m_hComm, &dwEvtMask)) {
		TRACE(_T("Failed in call to GetCommMask\n"));
		CSerialException::ThrowSerialException();
	}
}

BOOL CSerialPort::WaitEvent(DWORD& dwEvtmask, OVERLAPPED& overlapped)
{
	ASSERT(IsOpen());
	
	BOOL bResult = ::WaitCommEvent(m_hComm, &dwEvtmask, &overlapped);
	if (!bResult) {
		if (::GetLastError() != ERROR_IO_PENDING) {
			TRACE(_T("Failed in call to WaitCommEvent\n"));
			CSerialException::ThrowSerialException();
		}
	}
	return bResult;
}

void CSerialPort::GetOverlappedResult(OVERLAPPED& overlapped, DWORD& dwBytesTransfered, BOOL bWait)
{
	ASSERT(m_hComm);
	ASSERT(overlapped.hEvent != NULL);

	if (!::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransfered, bWait)) {
		if (::GetLastError() != ERROR_IO_PENDING) {
			TRACE(_T("Failed in call to GetOverlappedResult\n"));
			CSerialException::ThrowSerialException();
		}
	}
}

void CSerialPort::Escape(const DWORD& dwFunc)
{
	ASSERT(IsOpen());

	if (!::EscapeCommFunction(m_hComm, dwFunc)) {
		TRACE(_T("Failed in call to EscapeCommFunction\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::ClearDTR(void)
{
	Escape(CLRDTR);
}

void CSerialPort::ClearRTS(void)
{
	Escape(CLRRTS);
}

void CSerialPort::SetDTR(void)
{
	Escape(SETDTR);
}

void CSerialPort::SetRTS(void)
{
	Escape(SETRTS);
}

void CSerialPort::SetXOFF(void)
{
	Escape(SETXOFF);
}

void CSerialPort::SetXON(void)
{
	Escape(SETXON);
}

void CSerialPort::GetModemStatus(DWORD& dwModemStatus)
{
	ASSERT(IsOpen());

	if (!GetCommModemStatus(m_hComm, &dwModemStatus)) {
		TRACE(_T("Failed in call to GetCommModemStatus\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::SetBreak(void)
{
	ASSERT(IsOpen());

	if(!::SetCommBreak(m_hComm)) {
		TRACE(_T("Failed in call to SetCommBreak\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::ClearBreak(void)
{
	ASSERT(IsOpen());

	if(!::ClearCommBreak(m_hComm)) {
		TRACE(_T("Failed in call to ClearCommBreak"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::GetConfig(COMMCONFIG& config)
{
	ASSERT(IsOpen());

	DWORD dwSize = sizeof(COMMCONFIG);
	if (!::GetCommConfig(m_hComm, &config, &dwSize)) {
		TRACE(_T("Failed in call to GetCommConfig\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::SetConfig(COMMCONFIG& config)
{
	ASSERT(IsOpen());

	DWORD dwSize = sizeof(COMMCONFIG);
	if (!::SetCommConfig(m_hComm, &config, dwSize)) {
		TRACE(_T("Failed in call to SetCommConfig\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::GetDefaultConfig(UINT nPortNr, COMMCONFIG& config)
{
	//Validate our parameters
	ASSERT(nPortNr > 0 && nPortNr < 256);

	//Create the device name as a string
	CString strPort;
	strPort.Format(_T("COM%d"), nPortNr);

	DWORD dwSize = sizeof(COMMCONFIG);
	if (!::GetDefaultCommConfig(strPort, &config, &dwSize)) {
		TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::SetDefaultConfig(UINT nPortNr, COMMCONFIG& config)
{
	//Validate our parameters
	ASSERT(nPortNr > 0 && nPortNr < 256);

	//Create the device name as a string
	CString strPort;
	strPort.Format(_T("COM%d"), nPortNr);

	DWORD dwSize = sizeof(COMMCONFIG);
	if (!::SetDefaultCommConfig(strPort, &config, dwSize)) {
		TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::ClearError(DWORD& dwErrors)
{
	ASSERT(IsOpen());

	if(!::ClearCommError(m_hComm, &dwErrors, NULL)) {
		TRACE(_T("Failed in call to ClearCommError\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::GetStatus(COMSTAT& comstat)
{
	ASSERT(IsOpen());

	DWORD dwErrors;
	if (!::ClearCommError(m_hComm, &dwErrors, &comstat)) {
		TRACE(_T("Failed in call to ClearCommError\n"));
		CSerialException::ThrowSerialException();
	}
}

void CSerialPort::InitPort(CWnd*	pPortOwner,		// the owner (CWnd) of the port (receives message)
						   UINT		nPortNr,		// portnumber (1..255)
						   UINT		baud,			// baudrate
						   char		parity,			// parity 
						   UINT		databits,		// databits 
						   UINT		stopsbits ,		// stopbits 
						   DWORD	dwCommEvents,	// EV_CTS,EV_DSR etc
						   UINT		nBufferSize)	// number of input buffer
{
	ASSERT(pPortOwner != NULL);
	ASSERT(nPortNr > 0 && nPortNr < 256);

	if (m_bThreadAlive/*==TRUE*/) {
		do {
			::SetEvent(m_hShutdownEvent);
		} while (m_bThreadAlive);
		TRACE("Thread ended\n");
	}

	// create events
	if (m_ReadOverlapped.hEvent/*!=NULL*/)
		::ResetEvent(m_ReadOverlapped.hEvent);
	else
		m_ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	if (m_WriteOverlapped.hEvent/*!=NULL*/)
		::ResetEvent(m_WriteOverlapped.hEvent);
	else
		m_WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	if (m_BreakOverlapped.hEvent/*!= NULL*/)
		::ResetEvent(m_BreakOverlapped.hEvent);
	else
		m_BreakOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	if (m_hWriteEvent/*!= NULL*/)
		::ResetEvent(m_hWriteEvent);
	else
		m_hWriteEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
	
	if (m_hShutdownEvent/*!= NULL*/)
		::ResetEvent(m_hShutdownEvent);
	else
		m_hShutdownEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);

	// initialize the event objects
	m_hEventArray[0] = m_hShutdownEvent;	// highest priority
	m_hEventArray[1] = m_ReadOverlapped.hEvent;
	m_hEventArray[2] = m_BreakOverlapped.hEvent;
	m_hEventArray[3] = m_hWriteEvent;

	// initialize critical section
	::InitializeCriticalSection(&m_csCommunicationSync);

	// set buffersize for writing and save the owner
	m_pOwner = pPortOwner;

	if (m_lpInputBuffer/*!=NULL*/) 
		delete[] m_lpInputBuffer;
	m_lpInputBuffer = new BYTE[nBufferSize];

	m_nPortNr = nPortNr;
	m_nBufferSize = nBufferSize;
	m_dwCommEvents = dwCommEvents;

	CString strPort;
	CString strDef;

	// now it critical!
	::EnterCriticalSection(&m_csCommunicationSync);
	
	if (IsOpen()){
		::CloseHandle(m_hComm);
		m_hComm = NULL;
	}

	strPort.Format(_T("\\\\.\\COM%d"), nPortNr);
	strDef.Format(_T("baud=%d parity=%c data=%d stop=%d"), baud, parity, databits, stopsbits);

	m_hComm = ::CreateFile((LPCTSTR)strPort,			// 串口号 (COMX)
					     GENERIC_READ | GENERIC_WRITE,	// 可以同时读写
					     0,								// 以独占方式打开串口
					     NULL,							// 无安全属性
					     OPEN_EXISTING,					// 串口设备必须用OPEN_EXISTING,因为它肯定存在
					     FILE_FLAG_OVERLAPPED,			// (重叠)异步I/O操作方式
					     0);							// 对串设备,模板文件句柄必须为0(NULL)
	
	if (m_hComm == INVALID_HANDLE_VALUE) {
		::LeaveCriticalSection(&m_csCommunicationSync);
		TRACE(_T("Failed to open up the comms port\n"));
		CSerialException::ThrowSerialException();
	}
							
	// set the timeout values
	m_CommTimeouts.ReadIntervalTimeout = 100;
	m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
	m_CommTimeouts.ReadTotalTimeoutConstant = 0;
	m_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
	m_CommTimeouts.WriteTotalTimeoutConstant = 0;
	
	try {
		SetTimeouts(m_CommTimeouts);
		SetMask(dwCommEvents);
		GetState(m_dcb);
		m_dcb.fRtsControl = RTS_CONTROL_ENABLE;		// set RTS bit high!
		BuildDCB(strDef, m_dcb);
		SetState(m_dcb);
		Purge(PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
	} catch(CSerialException* pEx) {
		::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("应用程序错误"), MB_ICONSTOP);
		pEx->Delete();
	}

	::LeaveCriticalSection(&m_csCommunicationSync);

	TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", nPortNr);
}

// 开始监视工作线程
BOOL CSerialPort::StartMonitoring(void)
{
	m_Thread = AfxBeginThread(CommThread, this);
	if (!m_Thread)
		return FALSE;
	TRACE(_T("Thread started\n"));
	return TRUE;
}

// 停止监视工作线程
BOOL CSerialPort::StopMonitoring(void)
{
	ASSERT(m_Thread);

	TRACE(_T("Thread suspended\n"));
	m_Thread->SuspendThread();
	return TRUE;
}

BOOL CSerialPort::RestartMonitoring(void)
{
	ASSERT(m_Thread);

	TRACE(_T("Thread Resume\n"));
	m_Thread->ResumeThread();
	return TRUE;
}

BOOL CSerialPort::SetBreakEvent(DWORD& dwCommEvents)
{
	ASSERT(m_BreakOverlapped.hEvent != NULL);

	try {
		for(;;) {
			if (WaitEvent(dwCommEvents, m_BreakOverlapped)) {
				if (!HandleBreakEvent(dwCommEvents))
					return FALSE;
			} else {
				break;
			}
		}
	} catch(CSerialException* pEx) {
		::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("应用程序错误"), MB_ICONSTOP);
		pEx->Delete();
		return FALSE;
	}

	return TRUE;
}

BOOL CSerialPort::SetReadEvent(void)
{
	ASSERT(m_lpInputBuffer != NULL);
	ASSERT(m_ReadOverlapped.hEvent != NULL);

	DWORD dwReadByte;
	try {
		for (;;) {
			::memset((void*)m_lpInputBuffer, 0, m_nBufferSize);
			if (Read((LPVOID*)m_lpInputBuffer, m_nBufferSize, m_ReadOverlapped, &dwReadByte)) {
				if (!HandleReadedEvent(m_lpInputBuffer, dwReadByte))
					return FALSE;
				::ResetEvent(m_ReadOverlapped.hEvent);
			} else {
				break;
			}
		}
	} catch(CSerialException* pEx) {
		::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("应用程序错误"), MB_ICONSTOP);
		pEx->Delete();
		return FALSE;
	}
	
	return TRUE;
}

BOOL CSerialPort::HandleReadedEvent(LPVOID pParam, const DWORD& dwReadCount)
{
	COMMDATA CommData;
	CommData.pParam = pParam;
	CommData.dwParamCount = dwReadCount;
	//发送输入缓冲中的串口数据
	m_pOwner->SendMessage(WM_COMM_READED_DETECTED, (WPARAM)&CommData, (LPARAM)m_nPortNr);
	
	return SetReadEvent();
}

BOOL CSerialPort::HandleBreakEvent(DWORD& dwCommEvent)
{

	if (dwCommEvent & EV_CTS)
		m_pOwner->SendMessage(WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
	if (dwCommEvent & EV_BREAK)
		m_pOwner->SendMessage(WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
	if (dwCommEvent & EV_ERR)
		m_pOwner->SendMessage(WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
	if (dwCommEvent & EV_RING)
		m_pOwner->SendMessage(WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);		
	if (dwCommEvent & EV_RXFLAG)
		m_pOwner->SendMessage(WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
	if (dwCommEvent & EV_TXEMPTY)
		m_pOwner->SendMessage(WM_COMM_TXEMPTY_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);

	return SetBreakEvent(dwCommEvent);
}

BOOL CSerialPort::HandleWriteEvent(void)
{
	return ::ResetEvent(m_hWriteEvent);
}

void CSerialPort::HandleWaitTimeouts(void)
{
	m_pOwner->SendMessage(WM_COMM_TIMEOUT_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
}

⌨️ 快捷键说明

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