?? asyncserialport.cpp
字號:
#include "StdAfx.h"
#include "AsyncSerialPort.h"
#include "RuntimeException.h"
CAsyncSerialPort::CAsyncSerialPort(void)
{
m_breakEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_readEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_portClosingEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
m_writeEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
::ZeroMemory(&m_readOverlapped,sizeof(m_readOverlapped));
::ZeroMemory(&m_breakOverlapped,sizeof(m_breakOverlapped));
::ZeroMemory(&m_writeOverlapped,sizeof(m_writeOverlapped));
m_readOverlapped.hEvent = m_readEvent;
m_breakOverlapped.hEvent = m_breakEvent;
m_writeOverlapped.hEvent = m_writeEvent;
ASSERT(m_breakEvent!=NULL);
ASSERT(m_readEvent!=NULL);
ASSERT(m_portClosingEvent!=NULL);
ASSERT(m_writeEvent!=NULL);
}
CAsyncSerialPort::~CAsyncSerialPort(void)
{
Close();
::CloseHandle(m_breakEvent);
::CloseHandle(m_readEvent);
::CloseHandle(m_portClosingEvent);
::CloseHandle(m_writeEvent);
}
void CAsyncSerialPort::Open(int nPort, DWORD dwBaud, Parity parity, BYTE DataBits,
StopBits stopbits, FlowControl fc, BOOL bOverlapped)
{
CSerialPort::Open(nPort,dwBaud,parity,DataBits,stopbits,fc,TRUE);
m_isWriting = FALSE;
//This config is very useful
COMMTIMEOUTS timeouts;
GetTimeouts(timeouts);
timeouts.ReadIntervalTimeout = 100;
SetTimeouts(timeouts);
//Discards all characters from the output or input buffer
Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
//Set buffer length
Setup( ReadBufferLength, WriteBufferLength);
CThread::Start();
CThread::SetPriority(THREAD_PRIORITY_HIGHEST);
for(PortObserverList::iterator iter = m_portObservers.begin(); iter != m_portObservers.end(); ++ iter )
{
(*iter)->OnPortOpen(this);
}
}
void CAsyncSerialPort::Close()
{
if(IsOpen())
{
::SetEvent(m_portClosingEvent);
CThread::Wait(5000);
CThread::Terminate();
::ResetEvent(m_portClosingEvent);
for(PortObserverList::iterator iter = m_portObservers.begin(); iter != m_portObservers.end(); ++ iter )
{
(*iter)->OnPortClose(this);
}
}
CSerialPort::Close();
}
void CAsyncSerialPort::OnRead(const byte *pData, size_t dataLength)
{
try
{
for(PortObserverList::iterator iter = m_portObservers.begin(); iter != m_portObservers.end(); ++ iter )
{
(*iter)->OnRead(this, pData, dataLength);
}
}
catch (CRuntimeException* e)
{
OnError( e->GetErrorMessage());
e->Delete();
}
}
void CAsyncSerialPort::OnWrite(const byte *pData,size_t dataLength)
{
for(PortObserverList::iterator iter = m_portObservers.begin(); iter != m_portObservers.end(); ++ iter )
{
(*iter)->OnWrite(this,pData, dataLength );
}
}
void CAsyncSerialPort::HandleBreakEvent(DWORD &dwMask)
{
DWORD dwReadBytes;
CSerialPort::GetOverlappedResult(m_breakOverlapped,dwReadBytes, FALSE);
OnBreak(dwMask);
}
void CAsyncSerialPort::OnError(LPCTSTR lpszErrorMessage)
{
for(PortObserverList::iterator iter = m_portObservers.begin(); iter != m_portObservers.end(); ++ iter )
{
(*iter)->OnError(this,lpszErrorMessage);
}
}
void CAsyncSerialPort::SetBreakEvent(DWORD &dwMask)
{
while(true)
{
if(WaitEvent(dwMask,m_breakOverlapped))
{
HandleBreakEvent(dwMask);
}
else
{
DWORD dwError = ::GetLastError();
if( ERROR_IO_PENDING == dwError)
{
break;
}
else
{
THROW_EX_CODE(dwError);
}
}
}
}
void CAsyncSerialPort::SetReadEvent(OVERLAPPED& overlapped)
{
DWORD readCount=0;
while(true)
{
if(Read(m_readBuffer, ReadBufferLength, overlapped, &readCount))
{
OnRead(m_readBuffer,readCount);
ResetEvent(m_readEvent);
}
else
{
DWORD dwError = ::GetLastError();
if( ERROR_IO_PENDING == dwError)
{
return;
}
else
{
THROW_EX_CODE(dwError);
}
}
}
}
void CAsyncSerialPort::HandleReadEvent(OVERLAPPED& overlapped)
{
DWORD dwReadCount;
GetOverlappedResult(m_readOverlapped, dwReadCount, FALSE);
OnRead(m_readBuffer, dwReadCount);
}
void CAsyncSerialPort::HandleWriteEvent(OVERLAPPED& overlapped)
{
ASSERT(m_isWriting == TRUE);
DWORD dwWriteCount;
GetOverlappedResult(m_writeOverlapped, dwWriteCount, FALSE);
OnWrite(m_writeBuffer, dwWriteCount);
m_isWriting = FALSE;
::ResetEvent(m_writeEvent);
}
void CAsyncSerialPort::OnBreak(DWORD dwMask)
{
}
//Thread worker
int CAsyncSerialPort::Run()
{
try
{
TRACE(_T("Run read thread.\n"));
//events array
HANDLE waitHandles[4]= {
m_portClosingEvent,
m_readEvent,
m_breakEvent,
m_writeEvent};
WORD dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | \
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY;
SetMask(dwStoredFlags);
DWORD dwMask;
SetBreakEvent(dwMask);
SetReadEvent(m_readOverlapped);
DWORD dwEventIndex;
while(TRUE)
{
dwEventIndex = ::WaitForMultipleObjects(4,waitHandles,false,INFINITE);
switch(dwEventIndex)
{
case WAIT_OBJECT_0:
TRACE(_T("Receive serial port close event, exit read thread.\n"));
return 0L;
case WAIT_OBJECT_0+1: //read event
{
HandleReadEvent(m_readOverlapped);
SetReadEvent(m_readOverlapped);
}
break;
case WAIT_OBJECT_0 +2: //break event
{
HandleBreakEvent(dwMask);
SetBreakEvent(dwMask);
}
break;
case WAIT_OBJECT_0 +3:
{
HandleWriteEvent(m_writeOverlapped);
}
break;
case WAIT_FAILED:
THROW_EX_CODE( ::GetLastError() );
default:
ASSERT(FALSE);
return 0L;
}
}
}
catch (CRuntimeException* e)
{
OnError(e->GetErrorMessage());
e->Delete();
}
return 0L;
}
void CAsyncSerialPort::WriteEx(const void* lpBuf, DWORD dwCount)
{
if( dwCount > WriteBufferLength)
{
THROW_EX_CODE(_T("Too much data to write"));
}
if( !IsOpen())
{
THROW_EX_CODE(_T("SerialPort is closed, write data fail"));
}
ASSERT( lpBuf != NULL );
if( m_isWriting )
{
THROW_EX_CODE(_T("Send not completed, write data fail"));
}
::CopyMemory(m_writeBuffer, lpBuf, dwCount);
m_isWriting = TRUE;
DWORD dwWriteBytes = 0;
if( CSerialPort::Write(m_writeBuffer, dwCount, m_writeOverlapped, &dwWriteBytes) )
{
OnWrite(m_writeBuffer,dwWriteBytes);
ResetEvent(m_writeEvent);
}
}
void CAsyncSerialPort::AtachObserver(ISerialPortObserver *pObserver)
{
ASSERT(pObserver!=NULL);
m_portObservers.push_back(pObserver);
}
void CAsyncSerialPort::DetchObserver(ISerialPortObserver *pObserver)
{
ASSERT(pObserver!=NULL);
m_portObservers.remove(pObserver);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -