多线程串口管理代码(2)
// CommPort.cpp: implementation of the XCommPort class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XCommPort.h"
#include <stdio.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//#define COM_BUGWRITE 1
#ifdef COM_BUGWRITE
static void ComWritePrintf(const BYTE *str,const int Len )
{
char szFileName[256];
char buf[512];
strcpy( szFileName, "c:\\WritePrintf.txt" );
FILE *fpDebug = fopen( szFileName, "a" );
memset(buf,0,Len * 3 +2);
for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
fprintf( fpDebug, "%s\n", buf );
fclose( fpDebug );
}
static void ComReadPrintf(const BYTE *str,const int Len )
{
char szFileName[256];
char buf[512];
strcpy( szFileName, "c:\\ReadPort.txt" );
FILE *fpDebug = fopen( szFileName, "a" );
memset(buf,0,Len * 3 +2);
for( int i =0; i< Len; i++) sprintf(buf+(3*i),"%02X ",str[i]);
fprintf( fpDebug, "%s\n", buf );
fclose( fpDebug );
}
#endif //BUG
XCommPort::XCommPort(): m_bThreadAlive(0),
m_dwThreadID(NULL),
m_hComm(NULL),
m_nSizeToWrite(0)
{
m_pWriteBuffer = new BYTE[200];
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
m_ovOverLapped.hEvent = NULL;
}
XCommPort::~XCommPort()
{
CloseCommPort();
SafeDeleteArray( m_pWriteBuffer );
}
//---------------------------------------------------------------------------
BOOL XCommPort::CloseCommPort()
{
while (m_bThreadAlive)
{
SetEvent( m_hShutdownEvent );
}
::CloseHandle(m_hComm);
m_hComm = NULL;
return TRUE;
}
//---------------------------------------------------------------------------
DWORD XCommPort::CommThread(LPVOID pParame)
{
XCommPort *Port = (XCommPort*)pParame;
Port->m_bThreadAlive = true;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD CommEvent = 0;
DWORD dwError = 0;
BOOL bResult = TRUE;
//.................................................
if (Port->m_hComm)
{
::PurgeComm( Port->m_hComm,
PURGE_RXCLEAR|
PURGE_TXCLEAR|
PURGE_RXABORT|
PURGE_TXABORT);
}
for(;;)
{
bResult = WaitCommEvent(Port->m_hComm,
&Event,
&Port->m_ovOverLapped);
Event = WaitForMultipleObjects(3,
Port->m_hEventArray,
false,
INFINITE);
switch( Event )
{
case 0:
{
Port->m_bThreadAlive = false;
ExitThread( 100 );
break;
}
case 1:
{
GetCommMask(Port->m_hComm,&CommEvent);
if (CommEvent & EV_RXCHAR)
Port->ReadData();
break;
}
case 2:
{
Port->WriteData();
break;
}
case WAIT_FAILED:
{
char *msg= new char[20];
sprintf(msg,"%8X\n",::GetLastError());
ATLTRACE(msg);
::Sleep(1);
break;
}
}
}
return 0;
}
//---------------------------------------------------------------------------
int XCommPort::Create(const DWORD dwThreadID,
const char *szPath,
const BYTE bComID,const BYTE bSerialNo,
const DWORD dwBaudRate,const BYTE bByteSize,
const BYTE bParity,const BYTE bStopBits,
const int nWaitTime,const short bHaveMID)
{
if( !(InitCommPort(dwThreadID, bComID,bSerialNo,dwBaudRate,
bByteSize,bParity,bStopBits)) )
{
CloseCommPort();
return SERIAL_ERROR;
}
InitSerial(dwThreadID,bComID,bSerialNo,szPath,nWaitTime,bHaveMID); //(0)
DetectComm();
//SafeDelete(pInfo);
return SERIAL_OK;
}
//---------------------------------------------------------------------------
BOOL XCommPort::DetectComm()
{
DWORD ThreadID;
m_hThread = CreateThread(NULL,0,CommThread,this,0,&ThreadID);
if ( m_hThread == NULL )
{
return FALSE;
}
SetThreadPriority( m_hThread,THREAD_PRIORITY_TIME_CRITICAL );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::InitCommPort(DWORD dwThreadID,
BYTE bComID,
BYTE bSerialNo,
DWORD dwBaudRate,
BYTE bByteSize,
BYTE bParity,
BYTE bStopBits )
{
char szSerialPortName[20];
if( m_hShutdownEvent != NULL )
ResetEvent( m_hShutdownEvent );
m_hShutdownEvent = CreateEvent( NULL, true, false, NULL );
while( m_bThreadAlive )
{
SetEvent( m_hShutdownEvent );
}
sprintf( szSerialPortName, "\\\\.\\COM%d", bComID );
m_dwThreadID = dwThreadID;
if( m_ovOverLapped.hEvent != NULL )
ResetEvent( m_ovOverLapped.hEvent );
m_ovOverLapped.hEvent = CreateEvent( NULL, true, false, NULL );
if( m_hWriteEvent != NULL )
ResetEvent( m_hWriteEvent );
m_hWriteEvent = CreateEvent( NULL, true, false, NULL );
m_hEventArray[0] = m_hShutdownEvent;
m_hEventArray[1] = m_ovOverLapped.hEvent;
m_hEventArray[2] = m_hWriteEvent;
InitializeCriticalSection( &m_csCommunicationSync );
EnterCriticalSection( &m_csCommunicationSync );
m_hComm = CreateFile( szSerialPortName,
GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL );
if( m_hComm == INVALID_HANDLE_VALUE )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
COMMTIMEOUTS CommTimeouts;
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutConstant =0;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.WriteTotalTimeoutConstant =0;
CommTimeouts.WriteTotalTimeoutMultiplier =0;
if( !SetCommTimeouts( m_hComm, &CommTimeouts ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
//if( !SetCommMask( m_hComm,
// EV_BREAK | EV_ERR | EV_RING
// | EV_RXCHAR | EV_RXFLAG | EV_CTS ) )
if( !SetCommMask( m_hComm, EV_RXCHAR ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
if( !SetupComm( m_hComm, 4096, 2048 ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
if( !GetCommState( m_hComm, &m_dcb ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
m_dcb.BaudRate =dwBaudRate;
m_dcb.ByteSize =bByteSize;
m_dcb.Parity = bParity;
m_dcb.StopBits = bStopBits;
m_dcb.fBinary = true;
m_dcb.fParity = false;
m_dcb.fInX = false;
m_dcb.fOutX = false;
m_dcb.fRtsControl = RTS_CONTROL_DISABLE; //ENABLE;
m_dcb.fDtrControl = DTR_CONTROL_DISABLE;
m_dcb.fOutxCtsFlow = FALSE;
m_dcb.fOutxDsrFlow = FALSE;
if( !SetCommState( m_hComm, &m_dcb ) )
{
LeaveCriticalSection( &m_csCommunicationSync );
return FALSE;
}
m_bSerialNo = bSerialNo;
PurgeComm( m_hComm, PURGE_RXCLEAR|PURGE_TXCLEAR
|PURGE_RXABORT|PURGE_TXABORT );
LeaveCriticalSection( &m_csCommunicationSync );
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::ReadData()
{
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD dwBytesRead = 0;
DWORD dwByteToRead = 0;
COMSTAT comstat;
EnterCriticalSection( &m_csCommunicationSync );
bResult = ClearCommError( m_hComm,&dwError,&comstat );
LeaveCriticalSection( &m_csCommunicationSync );
Sleep(27); //(0)
dwByteToRead = comstat.cbInQue;
BYTE *pBuf = new BYTE[dwByteToRead];
if ( comstat.cbInQue > 0 )
{
EnterCriticalSection( &m_csCommunicationSync );
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
bResult = ::ReadFile( m_hComm,pBuf, comstat.cbInQue,
&dwBytesRead, &m_ovOverLapped );
if ( !bResult)
{
if ( ERROR_IO_PENDING == GetLastError() )
{
::GetOverlappedResult( m_hComm, &m_ovOverLapped,&dwBytesRead,TRUE );
}
}
LeaveCriticalSection(&m_csCommunicationSync);
}
#ifdef COM_BUGWRITE
ComReadPrintf(pBuf,dwBytesRead);
#endif
ReceiveBuf(dwBytesRead,pBuf);
delete[] pBuf;
return TRUE;
}
//---------------------------------------------------------------------------
BOOL XCommPort::WriteData()
{
BOOL bResult = TRUE;
DWORD dwBytesSent = 0;
ResetEvent( m_hWriteEvent );
EnterCriticalSection( &m_csCommunicationSync );
m_ovOverLapped.Offset = 0;
m_ovOverLapped.OffsetHigh = 0;
#ifdef COM_BUGWRITE
ComWritePrintf(m_pWriteBuffer,m_nSizeToWrite);
#endif
::PurgeComm( m_hComm,
PURGE_RXCLEAR|
PURGE_TXCLEAR|
PURGE_RXABORT|
PURGE_TXABORT );
bResult = ::WriteFile( m_hComm,
m_pWriteBuffer,
m_nSizeToWrite,
&dwBytesSent,
&m_ovOverLapped );
if ( !bResult )
{
DWORD dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
::GetOverlappedResult( m_hComm,
&m_ovOverLapped,
&dwBytesSent,
TRUE );
}
WriteCompleted( false );
LeaveCriticalSection( &m_csCommunicationSync );
return TRUE;
}
//---------------------------------------------------------------------------
int XCommPort::WriteToPort(BYTE *Buf,int Length)
{
if ( !m_bThreadAlive) return -1;
EnterCriticalSection( &m_csCommunicationSync );
m_nSizeToWrite = Length;
ATLASSERT(Length < 200 );
if ( Length>= 200 )
{
MessageBox(NULL,"write length >200","提示",MB_ICONWARNING);
return 1;
}
memcpy( m_pWriteBuffer, Buf,Length );
LeaveCriticalSection( &m_csCommunicationSync );
SetEvent( m_hWriteEvent );
return 0;
}
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。