📄 comm.cpp
字号:
//---------------------------------------------------------------------------
// Victor Chen
// victorch@163.net
#include <vcl.h>
#pragma hdrstop
#include "Comm.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------
// ValidCtrCheck is used to assure that the components created do not have
// any pure virtual functions.
//
//////////// begin internal objects define ///////////////////////////////
DWORD CommEventList[]={EV_BREAK,
EV_CTS,
EV_DSR,
EV_ERR,
EV_RING,
EV_RLSD,
EV_RXCHAR,
EV_RXFLAG,
EV_TXEMPTY};
DWORD CommBaudRates[] =
{
CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,
CBR_4800,CBR_9600,CBR_14400,CBR_19200,
CBR_38400,CBR_56000,CBR_57600,CBR_115200,
CBR_128000,CBR_256000
} ;
BYTE CommParity[]={ NOPARITY, EVENPARITY, ODDPARITY, MARKPARITY, SPACEPARITY } ;
BYTE CommStopBits[]={ ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITS } ;
BYTE CommDataBits[]={ 4, 5, 6, 7, 8 } ;
void RaiseCommError(String Msg, int ErrCode)
{
throw Exception(Msg + Format(sMsgExtention, ARRAYOFCONST(((int)ErrCode))));
}
__fastcall TCommEventThread::TCommEventThread(HANDLE Handle,TCommEventTypes MonitorEvents,DWORD SuspendTime):TThread(true)
{
int i ;
DWORD AttrWord ;
FreeOnTerminate = True;
FCommHandle = Handle;
FSuspendTime = SuspendTime;
AttrWord=0;
for (i=0;i<9;i++)
{
if (MonitorEvents.Contains(TCommEventType(i))) AttrWord=AttrWord+CommEventList[i];
}
SetCommMask(FCommHandle, AttrWord);
}
void __fastcall TCommEventThread::Execute(void)
{
OVERLAPPED os ;
bool WaitEventResult;
memset( &os, 0, sizeof( OVERLAPPED ) ) ;
os.hEvent = CreateEvent( NULL,TRUE,FALSE,NULL ) ;
while (!Terminated)
{
WaitEventResult=WaitCommEvent( FCommHandle, &FEventMask, &os );
if (GetLastError() == ERROR_IO_PENDING)
WaitEventResult=(WaitForSingleObject(os.hEvent,INFINITE)==WAIT_OBJECT_0);
if (WaitEventResult>0)
{
Synchronize(DoOnSignal);
ResetEvent(os.hEvent) ;
}
}
CloseHandle(os.hEvent) ;
PurgeComm(FCommHandle, PurgeReadWrite);
}
void __fastcall TCommEventThread::DoOnSignal(void)
{
if (FOnSignal) FOnSignal(this, FEventMask);
}
__fastcall TCommEventChars::TCommEventChars(TThreadComm *Owner): TPersistent()
{
FOwner = Owner;
FXOnChar = 17;
FXOffChar = 19;
FErrorChar = 0;
FEofChar = 0;
FEvtChar = 0;
}
void __fastcall TCommEventChars::SetEventChar(int Index, char Value)
{
// if (!FOwner->Connected)
switch (Index)
{
case 1: FXOnChar = Value; break;
case 2: FXOffChar = Value; break;
case 3: FErrorChar = Value; break;
case 4: FEofChar = Value; break;
case 5: FEvtChar = Value; break;
}
if (FOwner!=NULL)
FOwner->UpdateDataControlBlock();
}
void __fastcall TCommEventChars::Assign(TPersistent *Source)
{
TCommEventChars *TempControl ;
TempControl = dynamic_cast<TCommEventChars *>(Source) ;
if (TempControl != NULL)
{
FXOnChar = TempControl->FXOnChar;
FXOffChar = TempControl->FXOffChar;
FErrorChar = TempControl->FErrorChar;
FEofChar = TempControl->FEofChar;
FEvtChar = TempControl->FEvtChar;
}
else TPersistent::Assign(Source);
}
//////////// end internal objects define ///////////////////////////////
static inline void ValidCtrCheck(TThreadComm *)
{
new TThreadComm(NULL);
}
//---------------------------------------------------------------------------
__fastcall TThreadComm::TThreadComm(TComponent* Owner)
: TComponent(Owner)
{
FHandle = INVALID_HANDLE_VALUE;
FDeviceName = "Com2";
FReadTimeout = 1000;
FWriteTimeout = 1000;
FReadBufSize = 4096;
FWriteBufSize = 2048;
FSuspendTime = 5 ;
FMonitorEvents <<evBreak<<evCts<<evDsr<<evError<<evRing ;
FMonitorEvents <<evRlsd<<evRxChar<<evRxFlag<<evTxEmpty;
FBaudRate = br9600;
FParity = paNone;
FStopBits = sb10;
FDataBits = da8;
FConnected = false ;
WRITE_OS.Offset = 0 ;
WRITE_OS.OffsetHigh = 0 ;
WRITE_OS.hEvent = CreateEvent( NULL,TRUE,FALSE,NULL ) ;
READ_OS.Offset = 0 ;
READ_OS.OffsetHigh = 0 ;
READ_OS.hEvent = CreateEvent( NULL,TRUE,FALSE,NULL ) ;
// FOptions = [];
//*xukaiming 2005.4.2日更改--------------------------------------start ----------//
//FFlowControl = fcDefault;
//*xukaiming 2005.4.2日更改--------------------------------------end ----------//
FEventChars = new TCommEventChars(this);
FEvent = new TSimpleEvent();
FCriticalSection = new TCriticalSection();
}
__fastcall TThreadComm::~TThreadComm(void)
{
Close();
FEventChars->Free();
FEvent->Free();
FCriticalSection->Free();
CloseHandle(WRITE_OS.hEvent) ;
CloseHandle(READ_OS.hEvent) ;
}
void __fastcall TThreadComm::Lock()
{
FCriticalSection->Enter();
}
void __fastcall TThreadComm::Unlock()
{
FCriticalSection->Leave();
}
bool __fastcall TThreadComm::Enabled()
{
return (FConnected);
}
void __fastcall TThreadComm::CheckOpen()
{
if (Enabled()) RaiseCommError(sPortAlreadyOpen, -1);
}
void __fastcall TThreadComm::CreateHandle()
{
if ((FHandle = CreateFile(FDeviceName.c_str(),
GENERIC_READ | GENERIC_WRITE, 0, NULL,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL))==(HANDLE)-1)
{
FConnected = false ;
}
else
{
FConnected = true ;
if (GetFileType(FHandle) != FILE_TYPE_CHAR)
{
DestroyHandle();
} else
{
SetCommMask(FHandle, 511);
}
}
}
void __fastcall TThreadComm::DestroyHandle()
{
CloseHandle(FHandle);
FConnected = false ;
FHandle = INVALID_HANDLE_VALUE;
}
void _fastcall TThreadComm::Open()
{
int Error_Code =0 ;
String ErrorString ;
Lock();
if (!Enabled())
{
CreateHandle();
if (Enabled())
{
UpdateCommTimeouts();
UpdateDataControlBlock();
if (!SetupComm(FHandle, FReadBufSize, FWriteBufSize))
{
Error_Code = GetLastError() ;
ErrorString = sSetupCommErr ;
}
FEventThread = new TCommEventThread(FHandle,FMonitorEvents,FSuspendTime) ;
FEventThread->OnSignal = HandleCommEvent;
FEventThread->Resume() ;
if (FEventThread==NULL)
DestroyHandle() ;
}
else
{
Error_Code = -1 ;
ErrorString = sPortAlreadyOpen ;
}
}
Unlock();
if (Error_Code!=0) RaiseCommError(ErrorString, Error_Code);
}
void __fastcall TThreadComm::Close()
{
if (Enabled())
{
Lock();
try
{
FEventThread->OnSignal = NULL ;
TerminateThread((void*)FEventThread->Handle,0);
//delete FEventThread ; //xukaiming 2005.3.25
DestroyHandle();
}
__finally
{
Unlock();
}
// catch (...) { Unlock(); }
//Unlock();
}
}
int __fastcall TThreadComm::Write(char Buf[], DWORD Count)
{
BOOL fWriteStat ;
DWORD dwBytesWritten ;
DWORD dwErrorFlags;
DWORD dwError;
DWORD dwBytesSent=0;
COMSTAT ComStat;
if (!Enabled()) return -1;
Lock();
try
{
fWriteStat = WriteFile(FHandle, Buf, Count,
&dwBytesWritten, &WRITE_OS ) ;
if (!fWriteStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(FHandle,&WRITE_OS, &dwBytesWritten, FALSE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesSent += dwBytesWritten;
continue;
}
else
{
ClearCommError(FHandle, &dwErrorFlags, &ComStat ) ;
break;
}
}
dwBytesSent += dwBytesWritten;
}
else
{
ClearCommError(FHandle, &dwErrorFlags, &ComStat ) ;
}
}
else dwBytesSent += dwBytesWritten;
}
catch(...) { Unlock(); }
Unlock();
return dwBytesSent ;
}
int __fastcall TThreadComm::Read(char Buf[], DWORD Count)
{
BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength ;
DWORD dwBytesReceive=0;
DWORD dwError;
if (!Enabled()) return -1;
Lock();
try
{
ClearCommError( FHandle, &dwErrorFlags, &ComStat ) ;
dwLength = Count ;
if (dwLength > 0)
{
fReadStat = ReadFile( FHandle, Buf,
dwLength, &dwLength, &READ_OS ) ;
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(FHandle,
&READ_OS , &dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
{
dwBytesReceive += dwLength;
continue;
}
else
{
ClearCommError(FHandle, &dwErrorFlags, &ComStat ) ;
}
break;
}
dwBytesReceive += dwLength;
}
}
else dwBytesReceive += dwLength;
}
else
{
ClearCommError(FHandle, &dwErrorFlags, &ComStat ) ;
}
}
catch(...) { Unlock(); }
Unlock();
return dwBytesReceive ;
}
int __fastcall TThreadComm::InQueCount()
{
COMSTAT ComStat;
DWORD Errors;
int Result ;
if (Enabled())
{
ClearCommError(FHandle, &Errors, &ComStat);
Result = ComStat.cbInQue;
} else Result = -1;
return Result ;
}
int __fastcall TThreadComm::OutQueCount()
{
COMSTAT ComStat;
DWORD Errors;
int Result ;
if (Enabled())
{
ClearCommError(FHandle, &Errors, &ComStat);
Result = ComStat.cbOutQue;
} else Result = -1;
return Result ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -