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

📄 serialcomm.cpp

📁 云台控制的工具
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//=======================================================================================
// ComPort.cpp : 实现文件
//
//=======================================================================================

#include "stdafx.h"
#include "serialcomm.h"


//***************************************************************************************
// CSerialComm
//***************************************************************************************

CSerialComm::CSerialComm()
{
	m_pfnOnReceiveData = NULL;
	m_pfnOnComBreak =NULL;
	m_pPort = NULL;
	m_pReadThread = NULL;
	::ZeroMemory( &m_WriteOverlapped, sizeof(m_WriteOverlapped) );
	m_hWriteEvent = NULL;
}

CSerialComm::~CSerialComm()
{
	if(m_pPort)
	{
		if(m_pPort->IsOpen())
			Close(); 
	}

	delete m_pPort; 
	m_pPort = NULL;
}


//---------------------------------------------------------------------------------------
//	比 CSerialPort 多了一个 ReceiveMode 的参数,表示读取方式
//---------------------------------------------------------------------------------------

void CSerialComm::Open(int nPort, ReceiveMode mode, DWORD dwBaud, Parity parity, BYTE DataBits, 
					   StopBits stopbits, FlowControl fc)
{   
	//	1.新建串口
	m_pPort = new CSerialPort();

	//	2.判断收发模式
	if( mode == ManualReceiveByQuery )
		m_IsOverlapped  = FALSE;
	else
		m_IsOverlapped  = TRUE;
	m_RecvMode = mode;

	//	3.打开串口
	m_pPort->Open(nPort, dwBaud, parity, DataBits, stopbits, fc, m_IsOverlapped );
	m_pPort->Setup(4096, 4096);
	m_pPort->Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	//	--- 重点
	COMMTIMEOUTS timeouts;
	m_pPort->GetTimeouts(timeouts);
	timeouts.ReadIntervalTimeout = 100;
	m_pPort->SetTimeouts(timeouts);

	m_CurPortNum = nPort;
	//	创建关闭事件
	m_hCloseEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	ASSERT(m_hCloseEvent); 

	//-------------------------------------------------------------------------
	//	4.创建线程类
	//-------------------------------------------------------------------------
	m_pReadThread = new CSerialReadThread();
	m_pReadThread->BandSerialPort(this); 
	m_pReadThread->Create();
	m_pReadThread->Resume(); 

	if( IsOverlapped() )
	{	//	对于支持重叠操作的方式创建重叠事件
		m_hWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
	}
}

void CSerialComm::Close()
{
	//	1.串口,没有创建或打开
	if( m_pPort == NULL )
		return;
	if( !m_pPort->IsOpen() )
		return;

	//	2.事件
	::SetEvent( m_hCloseEvent );// 通知关闭系统
// ???
//	Sleep(1000);
	//	3.结束读线程
	TRY
	{
		m_pReadThread->Terminate();
		delete m_pReadThread;
		m_pReadThread = NULL;
	}
	CATCH(CSerialException, pEx)
	{
		TRACE(pEx->GetErrorMessage());
		pEx->Delete();
	}
	END_CATCH

	//	4.结束关闭线程
	::CloseHandle(m_hCloseEvent); 
	m_pPort->Close();

	//	5.结束写事件
	if( m_hWriteEvent )
	{
		::CloseHandle( m_hWriteEvent );
		m_hWriteEvent = NULL;
	}

	//	6.释放串口对象
	delete m_pPort;
	m_pPort = NULL;
}

void CSerialComm::OnReceiveData(void* pBuf, DWORD InBufferCount)
{
	if( m_pfnOnReceiveData )
		m_pfnOnReceiveData( m_pSender, pBuf, InBufferCount ); 
}

void CSerialComm::SetReceiveFunc(PFNOnReceiveData pfnOnReceiveData, LPVOID pSender)
{
	m_pfnOnReceiveData = pfnOnReceiveData;
	m_pSender = pSender;
}

void CSerialComm::OnComBreak(DWORD dwMask)
{
	if( m_pfnOnComBreak )
	{
		COMSTAT stat;
		m_pPort->GetStatus( stat );
		m_pfnOnComBreak( m_pPort, dwMask, stat );
	}
}

void CSerialComm::SetBreakHandleFunc(PFNOnComBreak pfnOnComBreak)
{
	m_pfnOnComBreak = pfnOnComBreak;
}


//---------------------------------------------------------------------------------------
//	
//---------------------------------------------------------------------------------------

ReceiveMode CSerialComm::GetReceiveMode()
{
	return m_RecvMode;
}

DWORD CSerialComm::GetInBufferCount()
{
	if(this->IsOverlapped())
	{
		TRACE( _T("this methord is only used for ManualQuery mode!") );
		return 0;
	}

	COMSTAT stat;
	ZeroMemory(&stat, sizeof(stat));
	this->m_pPort->GetStatus(stat);
	return stat.cbInQue; 
}


DWORD CSerialComm::GetInput(void* pBuf,DWORD Count,DWORD dwMilliseconds)
{   
	//	不允许在自动模式下工作
	if( GetReceiveMode() == AutoReceiveByBreak ||
		GetReceiveMode() == AutoReceiveBySignal )
	{
		TRACE( _T("Can't use GetInput methord in AutoQuery mode!") );
		return 0;
	}

	if( IsOverlapped() )
	{
		ASSERT(m_pReadThread); 
		DWORD dwBytes = m_pReadThread->ReadInput(pBuf,Count,dwMilliseconds);  
		m_pPort->TerminateOutstandingReads();  
		return dwBytes;
	}
	else
	{
		return m_pPort->Read(pBuf,Count);
	}
}

DWORD CSerialComm::Output(void* pBuf,DWORD Count)
{   
	DWORD dwWriteBytes = 0;
	if( IsOverlapped() )
	{	//	异步模式
		m_pPort->Write(pBuf, Count, m_WriteOverlapped);
		if( WaitForSingleObject(m_WriteOverlapped.hEvent,INFINITE) == WAIT_OBJECT_0 )
		{
			m_pPort->GetOverlappedResult(m_WriteOverlapped, dwWriteBytes, FALSE);
		}
	}
	else
	{
		dwWriteBytes = m_pPort->Write(pBuf,Count);
	}

	return dwWriteBytes;
}

CSerialPort* CSerialComm::GetSerialPort() 
{ 
	ASSERT(m_pPort);
	return m_pPort;
}

HANDLE CSerialComm::GetCloseHandle()
{ 
	ASSERT(this->m_hCloseEvent);
	return this->m_hCloseEvent;
}


//***************************************************************************************
//	CSerialReadThread
//***************************************************************************************

CSerialReadThread::CSerialReadThread()
{
	m_hThread = NULL;
	m_pPortComm = NULL;
	m_IsClose = FALSE;
	ZeroMemory(&m_BreakOverlapped, sizeof(m_BreakOverlapped));
	ZeroMemory(&m_ReadOverlapped, sizeof(m_ReadOverlapped));

	memset(m_InputBuffer, 0, 2048);
}

CSerialReadThread::~CSerialReadThread()
{
	m_hThread = NULL;
}


BOOL CSerialReadThread::SetReadEvent(OVERLAPPED& overlapped)
{
	CSerialPort* pPort = m_pPortComm->GetSerialPort();
	if( pPort == NULL )
		return FALSE;

BeginSet:
	if( pPort->Read(m_InputBuffer, 2048, overlapped, &m_InBufferCount) )
	{	//	读取完成后调用 HandleData 处理
		if( !HandleData() )
			return FALSE;
		::ResetEvent( m_ReadOverlapped.hEvent );
		goto BeginSet;
	}

    DWORD error = GetLastError();
	if( error == ERROR_IO_PENDING )
		return TRUE;
	else
		return FALSE;
}


BOOL CSerialReadThread::HandleData() //处理读取数据
{
	if( m_InBufferCount > 0 )
	{
		m_pBuffer = new BYTE[m_InBufferCount];
		for( int i = 0; i< (int)m_InBufferCount; i ++ )
		{	//	拷贝
			m_pBuffer[i] = m_InputBuffer[i];
		}
		//	处理完后立即删掉
		m_pPortComm->OnReceiveData( m_pBuffer, m_InBufferCount );
		delete[] m_pBuffer;
	}

	return TRUE;
}

BOOL CSerialReadThread::HandleReadEvent(OVERLAPPED& overlapped)
{
	CSerialPort* pPort = m_pPortComm->GetSerialPort();
	if( pPort == NULL )
		return FALSE;

	if( pPort->GetOverlappedResult(overlapped, m_InBufferCount, FALSE) )
	{	//	转到了 CSerialReadThread::HandleData(),然后到了 CSerialComm::ReceiveData
		return HandleData();
	}

	DWORD dwError = ::GetLastError();
	if( dwError == ERROR_INVALID_HANDLE )
		return FALSE;
	else
		return TRUE;
}

BOOL CSerialReadThread::SetBreakEvent(DWORD& dwMask )
{
	CSerialPort* pPort = m_pPortComm->GetSerialPort();
	if( pPort == NULL )
		return FALSE;

SetBegin:
	if( pPort->WaitEvent(dwMask, m_BreakOverlapped) )
	{
		if( !HandleBreakEvent(dwMask) )
			return FALSE;
		goto SetBegin;
	}

	DWORD error = GetLastError();
	if( error == ERROR_IO_PENDING )
		return TRUE;
	else
		return FALSE;
}

BOOL CSerialReadThread::HandleBreakEvent(DWORD dwMask)
{
	DWORD dwReadBytes;
	CSerialPort* pPort = m_pPortComm->GetSerialPort();

⌨️ 快捷键说明

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