?? serialport.cpp
字號:
// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "SerialPort.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// CSerialException Construction/Destruction
//////////////////////////////////////////////////////////////////////
void CSerialException::ThrowSerialException(DWORD dwError/* = 0 */)
{
if (dwError == 0)
dwError = ::GetLastError();
CSerialException* pException = new CSerialException(dwError);
TRACE(_T("Warning: throwing CSerialException for error %d\n"), dwError);
THROW(pException);
}
BOOL CSerialException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError, PUINT pnHelpContext)
{
ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
if (pnHelpContext != NULL)
*pnHelpContext = 0;
LPTSTR lpBuffer;
BOOL bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, m_dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
(LPTSTR) &lpBuffer, 0, NULL);
if (bRet == FALSE)
*pstrError = '\0';
else
{
lstrcpyn(pstrError, lpBuffer, nMaxError);
bRet = TRUE;
LocalFree(lpBuffer);
}
return bRet;
}
CString CSerialException::GetErrorMessage()
{
CString rVal;
LPTSTR pstrError = rVal.GetBuffer(4096);
GetErrorMessage(pstrError, 4096, NULL);
rVal.ReleaseBuffer();
return rVal;
}
CSerialException::CSerialException(DWORD dwError)
{
m_dwError = dwError;
}
CSerialException::~CSerialException()
{
}
IMPLEMENT_DYNAMIC(CSerialException, CException)
#ifdef _DEBUG
void CSerialException::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << "m_dwError = " << m_dwError;
}
#endif
//////////////////////////////////////////////////////////////////////
// CSerialPort Construction/Destruction
//////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNAMIC(CSerialPort, CObject)
const UINT CSerialPort::WM_COMM_BREAK_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_BREAK_DETECTED"));
const UINT CSerialPort::WM_COMM_CTS_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_CTS_DETECTED"));
const UINT CSerialPort::WM_COMM_DSR_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_DSR_DETECTED"));
const UINT CSerialPort::WM_COMM_ERR_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_ERR_DETECTED"));
const UINT CSerialPort::WM_COMM_RXFLAG_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_RXFLAG_DETECTED"));
const UINT CSerialPort::WM_COMM_RING_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_RING_DETECTED"));
const UINT CSerialPort::WM_COMM_RLSD_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_RLSD_DETECTED"));
const UINT CSerialPort::WM_COMM_TXEMPTY_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_TXEMPTY_DETECTED"));
const UINT CSerialPort::WM_COMM_READED_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_READED_DETECTED"));
const UINT CSerialPort::WM_COMM_TIMEOUT_DETECTED = ::RegisterWindowMessage(_T("CSerialPort::WM_COMM_TIMEOUT_DETECTED"));
CSerialPort::CSerialPort()
{
m_hComm = INVALID_HANDLE_VALUE;
m_ReadOverlapped.Offset = 0;
m_ReadOverlapped.OffsetHigh = 0;
m_BreakOverlapped.Offset = 0;
m_BreakOverlapped.OffsetHigh = 0;
m_WriteOverlapped.Offset = 0;
m_WriteOverlapped.OffsetHigh = 0;
m_hShutdownEvent = NULL;
m_hWriteEvent = NULL;
m_BreakOverlapped.hEvent = NULL;
m_ReadOverlapped.hEvent = NULL;
m_WriteOverlapped.hEvent = NULL;
SetWaitTimeouts();
m_Thread = NULL;
m_lpInputBuffer = NULL;
m_nBufferSize = 0;
m_bThreadAlive = FALSE;
m_pOwner = NULL;
}
CSerialPort::~CSerialPort()
{
while(m_bThreadAlive/*==TRUE*/)
::SetEvent(m_hShutdownEvent);
if (IsOpen())
::CloseHandle(m_hComm);
// Close Handles
if(m_hShutdownEvent/*!=NULL*/)
CloseHandle(m_hShutdownEvent);
if(m_BreakOverlapped.hEvent/*!=NULL*/)
::CloseHandle(m_BreakOverlapped.hEvent);
if (m_ReadOverlapped.hEvent/*!=NULL*/)
::CloseHandle(m_ReadOverlapped.hEvent);
if (m_WriteOverlapped.hEvent/*!=NULL*/)
::CloseHandle(m_WriteOverlapped.hEvent);
if(m_hWriteEvent/*!=NULL*/)
CloseHandle(m_hWriteEvent);
TRACE("Thread ended\n");
if (m_lpInputBuffer/*!=NULL*/)
delete[] m_lpInputBuffer;
}
#ifdef _DEBUG
void CSerialPort::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
dc << _T("m_hComm = ") << m_hComm << _T("\n");
}
#endif
UINT CSerialPort::CommThread(LPVOID pParam)
{
CSerialPort* port = (CSerialPort*)pParam;
ASSERT(port != NULL);
ASSERT_KINDOF(CSerialPort, port);
port->m_bThreadAlive = TRUE;
try {
if (port->IsOpen())
port->Purge(PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
} catch(CSerialException* pEx) {
::MessageBox(port->m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("應(yīng)用程序錯誤"), MB_ICONSTOP);
pEx->Delete();
port->ClosePort();
pEx->Delete();
}
DWORD dwCommEvents = 0;
DWORD Event = 0;
DWORD dwByteRead = 0;
if (!(port->SetBreakEvent(dwCommEvents) && port->SetReadEvent()))
port->ClosePort();
for (;;) {
Event = ::WaitForMultipleObjects(4, port->m_hEventArray, FALSE, port->m_dwTimeoutMilliseconds);
switch (Event) {
case 0/*WAIT_OBJECT_0*/:
port->HandleShutdownEvent();
AfxEndThread(100);
break;
case 1/*WAIT_OBJECT_0+1*/:
try {
port->GetOverlappedResult(port->m_ReadOverlapped, dwByteRead, TRUE);
if (!port->HandleReadedEvent((LPVOID)(port->m_lpInputBuffer), dwByteRead))
port->ClosePort();
} catch(CSerialException* pEx) {
::MessageBox(port->m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("應(yīng)用程序錯誤"), MB_ICONSTOP);
pEx->Delete();
port->ClosePort();
}
break;
case 2/*WAIT_OBJECT_0+2*/:
if (!port->HandleBreakEvent(dwCommEvents))
port->ClosePort();
break;
case 3/*WAIT_OBJECT_0+3*/:
if (!port->HandleWriteEvent())
port->ClosePort();
break;
case WAIT_TIMEOUT:
port->HandleWaitTimeouts();
break;
}
} // end for
return 0;
}
void CSerialPort::Setup(const DWORD& dwInQueue, const DWORD& dwOutQueue)
{
ASSERT(IsOpen());
if (!::SetupComm(m_hComm, dwInQueue, dwOutQueue)) {
TRACE(_T("Failed in call to SetupComm\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::SetState(DCB& dcb)
{
ASSERT(IsOpen());
if (!::SetCommState(m_hComm, &dcb)) {
TRACE(_T("Failed in call to SetCommState\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetState(DCB& dcb)
{
ASSERT(IsOpen());
if (!::GetCommState(m_hComm, &dcb)) {
TRACE(_T("Failed in call to GetCommState\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetProperties(COMMPROP& commprop)
{
ASSERT(IsOpen());
if (!::GetCommProperties(m_hComm, &commprop)) {
TRACE(_T("Failed in call to GetCommProperties\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::BuildDCB(const CString& strDef, DCB& dcb)
{
ASSERT(IsOpen());
if (!::BuildCommDCB((LPCTSTR)strDef, &dcb)) {
TRACE(_T("Failed in call to BuildCommDCB"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::BuildDCBAndTimeouts(const CString& strDef, DCB& dcb, COMMTIMEOUTS commtimeouts)
{
ASSERT(IsOpen());
if (!::BuildCommDCBAndTimeouts((LPCTSTR)strDef, &dcb, &commtimeouts)) {
TRACE(_T("Failed in call to BuildCommDCAndTimeouts\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::TransmitChar(const char& cChar)
{
ASSERT(IsOpen());
if (!::TransmitCommChar(m_hComm, cChar)) {
TRACE(_T("Failed in call to SetCommTimeouts\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetTimeouts(COMMTIMEOUTS& commtimeouts)
{
ASSERT(IsOpen());
if (!::GetCommTimeouts(m_hComm, &commtimeouts)) {
TRACE(_T("Failed in call to GetCommTimeouts\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::SetTimeouts(COMMTIMEOUTS& commtimeouts)
{
ASSERT(IsOpen());
if (!::SetCommTimeouts(m_hComm, &commtimeouts)) {
TRACE(_T("Failed in call to SetCommTimeouts\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::Set0Timeout(void)
{
COMMTIMEOUTS Timeouts;
ZeroMemory(&Timeouts, sizeof(COMMTIMEOUTS));
Timeouts.ReadIntervalTimeout = MAXDWORD;
SetTimeouts(Timeouts);
}
void CSerialPort::Set0WriteTimeout(void)
{
COMMTIMEOUTS Timeouts;
GetTimeouts(Timeouts);
Timeouts.WriteTotalTimeoutMultiplier = 0;
Timeouts.WriteTotalTimeoutConstant = 0;
SetTimeouts(Timeouts);
}
void CSerialPort::Set0ReadTimeout(void)
{
COMMTIMEOUTS Timeouts;
GetTimeouts(Timeouts);
Timeouts.ReadIntervalTimeout = MAXDWORD;
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 0;
SetTimeouts(Timeouts);
}
BOOL CSerialPort::Read(LPVOID lpBuffer, const DWORD& dwNumberOfBytesToRead, OVERLAPPED& overlapped, LPDWORD lpNumberOfBytesRead)
{
ASSERT(IsOpen());
ASSERT(overlapped.hEvent != NULL);
DWORD dwReadCount = 0;
BOOL bResult = ::ReadFile(m_hComm, lpBuffer, dwNumberOfBytesToRead, &dwReadCount, &overlapped);
if (!bResult) {
if (::GetLastError() != ERROR_IO_PENDING) {
TRACE(_T("Failed in call to ReadFile\n"));
CSerialException::ThrowSerialException();
}
} else
if (lpNumberOfBytesRead/*!=NULL*/)
*lpNumberOfBytesRead = dwReadCount;
return bResult;
}
BOOL CSerialPort::Write(LPCVOID lpBuffer, const DWORD& dwNumberOfBytesToWrite, OVERLAPPED& overlapped, LPDWORD lpNumberOfBytesWrite)
{
ASSERT(IsOpen());
ASSERT(overlapped.hEvent != NULL);
DWORD dwWriteCount = 0;
BOOL bResult = ::WriteFile(m_hComm, lpBuffer, dwNumberOfBytesToWrite, &dwWriteCount, &overlapped);
if (!bResult) {
if (::GetLastError() != ERROR_IO_PENDING) {
TRACE(_T("Failed in call to WriteFile\n"));
CSerialException::ThrowSerialException();
} else
if(lpNumberOfBytesWrite/*!=NULL*/)
*lpNumberOfBytesWrite = dwWriteCount;
}
return bResult;
}
void CSerialPort::Flush(void)
{
ASSERT(IsOpen());
if(!::FlushFileBuffers(m_hComm)) {
TRACE(_T("Failed in call to FlushFileBuffers"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::Purge(const DWORD& dwFlags)
{
ASSERT(IsOpen());
if(!::PurgeComm(m_hComm, dwFlags)) {
TRACE(_T("Failed in call to PurgeComm"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::TerminateOutstandingWrites(void)
{
Purge(PURGE_TXABORT);
}
void CSerialPort::TerminateOutstandingReads(void)
{
Purge(PURGE_RXABORT);
}
void CSerialPort::ClearWriteBuffer(void)
{
Purge(PURGE_TXCLEAR);
}
void CSerialPort::ClearReadBuffer(void)
{
Purge(PURGE_RXCLEAR);
}
void CSerialPort::SetMask(const DWORD& dwEvtMask)
{
ASSERT(IsOpen());
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -