📄 serialcomm.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 + -