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

📄 serialcomm.cpp

📁 M16C Flash Starter Software Ver.2.0.0.46 Source Files.zip是瑞萨的M16C系列单片机的flash烧写程序。
💻 CPP
字号:
// SerialComm.cpp: CSerialComm Implementation.
//
// This software can be offered for free and used as necessary to aid 
// in your program developments.
//
// RENESAS TECHNOLOGY CORPORATION, RENESAS SOLUTIONS CORPORATION,
// and related original software developers assume no responsibility 
// for any damage or infringement of any third-party's rights, originating 
// in the use of the following software.
// Please use this software under the agreement and acceptance of these conditions. 
//
// Copyright(C)1998(2003) RENESAS TECHNOLOGY CORPORATION AND RENESAS SOLUTIONS CORPORATION
// ALL RIGHTS RESERVED
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SerialComm.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

#define	_SERIALCOMM_SELF_TIMEOUT

// Construction/Destruction.
CSerialComm::CSerialComm()
	: CIoController() ,m_dwTimeout(0), m_bThreadEndFlg(TRUE)
{
}

CSerialComm::~CSerialComm()
{
}

// Open comm port.
BOOL CSerialComm::Open(const CString& strDevice)
{
	// DTR ON.
	if (CIoController::Open(strDevice))
	{
//		::EscapeCommFunction(m_hDevice, SETDTR); // after dcb setting
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

// Send data.
DWORD CSerialComm::Write(const void* pBuffer, DWORD dwBytesToWrite)
{
	DWORD	dwBytesWritten;

	// Write data to buffer.
	if (!::WriteFile(m_hDevice, pBuffer, dwBytesToWrite, &dwBytesWritten, 0))
	{
		return 0;
	}

	// return Write length.
	return dwBytesWritten;
}

// Read data.
DWORD CSerialComm::Read(void* pBuffer, DWORD dwRequestBytes)
{
#ifdef _SERIALCOMM_SELF_TIMEOUT

	COMSTAT		stat;
	DWORD		dwErrors;
	DWORD		dwTryTime;
	DWORD		dwBytesRead = 0;
	DWORD		dwTotal = 0;		// total recieve size
	m_bIsTimeout = FALSE;

	// Get current time.
	dwTryTime = ::GetTickCount();

	

	// wait data read or timeout.
	while (TRUE)
	{


		int err = ::GetLastError();

		// Get error status(clear).
		::ClearCommError(m_hDevice, &dwErrors, &stat);

//########										// modify start		
		// data read
		if(dwRequestBytes - dwTotal > stat.cbInQue)
		{
			::ReadFile(m_hDevice, pBuffer, stat.cbInQue, &dwBytesRead, 0);
		}else{
			::ReadFile(m_hDevice, pBuffer, dwRequestBytes - dwTotal, &dwBytesRead, 0);
		}

		// total size update
		dwTotal+=dwBytesRead;
		if(dwTotal >= dwRequestBytes)
			break;

		// read buffer update
		pBuffer = (void *)((DWORD)pBuffer + dwBytesRead);
		
		// Timeout?
		if ((dwTryTime + m_dwTimeout) < ::GetTickCount() && m_dwTimeout != 0)
		{
				m_bIsTimeout = TRUE;
			return 0;
		}		
/*
		// read buffer full.
		if (dwRequestBytes <= stat.cbInQue)
		{
#if 0
			if ( dwRequestBytes > 255 )
			{
				for ( int idx = 0; idx < dwRequestBytes; idx++ )
				{
					::ReadFile(m_hDevice, ((char*)pBuffer)+idx, 1, &dwBytesRead, 0);
				}
			}
			else
			{
				::ReadFile(m_hDevice, pBuffer, dwRequestBytes, &dwBytesRead, 0);
			}
#else
			::ReadFile(m_hDevice, pBuffer, dwRequestBytes, &dwBytesRead, 0);
#endif
			break;
		}
		
		// Timeout?
		else if ((dwTryTime + m_dwTimeout) < ::GetTickCount() && m_dwTimeout != 0)
		{
			m_bIsTimeout = TRUE;
			return 0;
		}
*/
//########  modify end 
	}

	// return read data length.
	return dwBytesRead;

#else	// ifdef _SERIALCOMM_SELF_TIMEOUT

	DWORD	dwBytesRead;

	// read data.
	if (!::ReadFile(m_hDevice, pBuffer, dwRequestBytes, &dwBytesRead, 0))
	{
		return 0;
	}

	// return read data legnth.
	return dwBytesRead;

#endif	// ifdef _SERIALCOMM_SELF_TIMEOUT
}

// Set timeout.
BOOL CSerialComm::SetTimeout(DWORD dwTimeout)
{
	COMMTIMEOUTS	timeouts;

	::GetCommTimeouts(m_hDevice, &timeouts);

	// keep timout count.
	m_dwTimeout = dwTimeout;

#ifdef _SERIALCOMM_SELF_TIMEOUT
	timeouts.ReadIntervalTimeout = MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
	timeouts.ReadTotalTimeoutConstant = m_dwTimeout;
	timeouts.WriteTotalTimeoutMultiplier = 0;
	timeouts.WriteTotalTimeoutConstant = 0;

#else	// ifdef _SERIALCOMM_SELF_TIMEOUT
	timeouts.ReadIntervalTimeout = MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
	timeouts.ReadTotalTimeoutConstant = m_dwTimeout;
	timeouts.WriteTotalTimeoutMultiplier = 0;
	timeouts.WriteTotalTimeoutConstant = 0;
#endif	// ifdef _SERIALCOMM_SELF_TIMEOUT

	return ::SetCommTimeouts(m_hDevice, &timeouts);
}

// set communication status.
BOOL CSerialComm::SetState(const CIoState* pState)
{
	DCB						dcb;
	const CSerialCommState*	pSerialCommState;

	// cast pointer to comm object.
	ASSERT(IsSerialStateObject(pState));
	pSerialCommState = dynamic_cast<const CSerialCommState*>(pState);

	// get current comm status.
	if (!::GetCommState(m_hDevice, &dcb))
	{
		return FALSE;
	}

	// set new status values.
	dcb.BaudRate = pSerialCommState->m_dwBaudRate;
	dcb.ByteSize = pSerialCommState->m_byByteSize;
	dcb.Parity = pSerialCommState->m_byParity;
	dcb.StopBits = pSerialCommState->m_byStopBits;

	// set XON/XOFF OFF
	dcb.fTXContinueOnXoff = FALSE;
	dcb.fOutX = FALSE;
	dcb.fInX = FALSE;

	// change status.
	if (!::SetCommState(m_hDevice, &dcb))
	{
		return FALSE;
	}

	// DTR ON
	::EscapeCommFunction(m_hDevice, SETDTR); // modify

	return TRUE;
}

// Get comm status.
BOOL CSerialComm::GetState(CIoState* pState)
{
	DCB					dcb;
	CSerialCommState*	pSerialCommState;

	// cast pointer to comm object.
	ASSERT(IsSerialStateObject(pState));
	pSerialCommState = dynamic_cast<CSerialCommState*>(pState);

	// Get current status.
	if (!::GetCommState(m_hDevice, &dcb))
	{
		pSerialCommState->Clear();
		return FALSE;
	}

	// return status values.
	pSerialCommState->m_dwBaudRate = dcb.BaudRate;
	pSerialCommState->m_byByteSize = dcb.ByteSize;
	pSerialCommState->m_byParity = dcb.Parity;
	pSerialCommState->m_byStopBits = dcb.StopBits;

	return TRUE;
}

// inspect object pointer.
BOOL CSerialComm::IsSerialStateObject(const CIoState* pState) 
{
	return (dynamic_cast<const CSerialCommState*>(pState) != NULL);
}

// buffer clear, clear error status.
int CSerialComm::CleanUp(void* pParam)
{
	DWORD		dwErrors;
	COMSTAT		stat;

	// clear error flag.
	::ClearCommError(m_hDevice, &dwErrors, &stat);


	// clear input buffer.
	if ( !::PurgeComm(m_hDevice, PURGE_RXCLEAR) )
	{
#if defined(_DEBUG)
		int	eCode = ::GetLastError();
		CString	str;
		str.Format("buffer clear [%d]\n", eCode);
		AfxGetMainWnd()->MessageBox(str);
#endif
		}

	return 0;
}

// creat comm thread.
// if pEventProc == NULL: call CSerialComm::OnReceive().
BOOL CSerialComm::CreateRcvThread(IO_EVENT_PROC pEventProc, void* pParam, DWORD dwBytesWaitFor)
{
	DWORD	dwThreadID;
	
	// already thread exist.
	if (!m_bThreadEndFlg)
	{
		return FALSE;
	}

	EVENT_PROC_INFO* pProcInfo = new EVENT_PROC_INFO;

	// set thread param.
	pProcInfo->pEventProc = pEventProc;
	pProcInfo->pClassInstance = this;
	pProcInfo->dwBytesWaitFor = dwBytesWaitFor;
	pProcInfo->pParam = pParam;
	
	// create thread.
	m_hRcvThread = ::CreateThread(0, 0, (LPTHREAD_START_ROUTINE)CommEventThread, pProcInfo, 0, &dwThreadID);
	
	// success.
	if (m_hRcvThread != NULL)
	{
		m_bThreadEndFlg = FALSE;
		return TRUE;
	}

	// failed.
	else 
	{
		m_bThreadEndFlg = TRUE;
		delete pProcInfo;
		return FALSE;
	}
}

// delete input thread.
// The instance of thread must be deleted before deleting the instance of CSerialComm.
BOOL CSerialComm::DeleteRcvThread()
{
	// already deleted.
	ASSERT(m_bThreadEndFlg == FALSE);

	// set delete flag.
	m_bThreadEndFlg = TRUE;

	// wait tread finish.
	if (::WaitForSingleObject(m_hRcvThread, INFINITE) == WAIT_OBJECT_0)
	{
		return TRUE;
	}
	else
	{
		m_bThreadEndFlg = FALSE;
		return FALSE;
	}
}

// thread finction main loop.
void CSerialComm::CommEventThread(EVENT_PROC_INFO* pProcInfo)
{
	COMSTAT		comStat;
	DWORD		dwErrorFlags;

	// copy struct.
	CSerialComm*	pClassInstance = dynamic_cast<CSerialComm*>(pProcInfo->pClassInstance);
	IO_EVENT_PROC	pEventProc = pProcInfo->pEventProc;
	void*			pParam = pProcInfo->pParam;
	DWORD			dwBytesWaitFor = pProcInfo->dwBytesWaitFor;

	// pointer cheak.
	ASSERT(pClassInstance);

	// Since value was copied, it does not have necessity any longer.
	delete pProcInfo;

	// loop until wait delete flag set.
	while (!pClassInstance->m_bThreadEndFlg)
	{
		// get error status.
		::ClearCommError(pClassInstance->m_hDevice, &dwErrorFlags, &comStat);

		// an error occurs of read data.
		if (dwErrorFlags > 0 || dwBytesWaitFor <= comStat.cbInQue)
		{
			// call event handler.
			if (pEventProc)
			{
				pEventProc(pParam, dwErrorFlags);
			}	
			else
			{
				pClassInstance->OnReceive(pParam, dwErrorFlags);
			}
		}
	}

	// finish thread.
	ExitThread(0);
}

// default callback function. do nothing.
// must override.
void CSerialComm::OnReceive(void* pParam, DWORD dwErrFlags)
{
}

⌨️ 快捷键说明

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