📄 tcomm32.cpp
字号:
break;
if(GetOverlappedResult(Comm->Handle, &Comm->_WriteOS, &dwBytesWr, false))
BytesSent+=dwBytesWr;
}
Sleep(0);
}
else if(Comm->_OutQueue->Count)
{
BytesSent = 0;
BytesToSend = Comm->_OutQueue->Out(SendBuf, SendBufSize);
SetEvent(Comm->_hSyncWrite);
}
}
Comm->_WriteThreadRunning = 0;
}
//---------------------------------------------------------------------------
void TComm32::_TimerThread(void *Param)
{
TComm32 *Comm = (TComm32 *) Param;
Comm->_TimerThreadRunning = 1;
while(Comm->_RunTimerThread)
{
if(WaitForSingleObject(Comm->_hKillTimer, Comm->_TimerInterval) == WAIT_OBJECT_0)
break;
Comm->fmsgCommTimer();
}
Comm->_TimerThreadRunning = 0;
}
/***************************************************************************\
* TComm32 *
\***************************************************************************/
const char TComm32::Fmt_COMn[] = "\\\\.\\COM%d";
const char TComm32::Fmt_InitModem[] = "ATE0&K%dS0=%d\r";
const char TComm32::Str_ResetModem[] = "ATZ\r";
//---------------------------------------------------------------------------
__fastcall TComm32::TComm32()
{
_Opened = false;
_bFromHandle = false;
_DisableWrite = false;
_bDTR = true; //After activate, DTR is true.
_bRTS = true; //After activate, RTS is true.
lpCommNotify = NULL;
lpAfterOpen = NULL;
lpBeforeClose = NULL;
_PortNo = 2; //"COM2"
_HwInSize = 1200;
_HwOutSize = 1200;
_AutoAns = 0; //disable auto answer
sprintf(_PortName, Fmt_COMn, _PortNo);
//---- DCB settings ----//
memset(&_dcb, 0, sizeof(DCB)); //Clear DCB
_dcb.DCBlength = sizeof(DCB); //DWORD: sizeof(DCB)
_dcb.BaudRate = CBR_115200; //DWORD: current baud rate
_dcb.Parity = NOPARITY; //BYTE : 0-4=no,odd,even,mark,space
_dcb.ByteSize = 8; //BYTE : number of bits/byte, 4-8
_dcb.StopBits = ONESTOPBIT; //BYTE : 0,1,2 = 1, 1.5, 2
_dcb.fBinary = true; //DWORD: binary mode, no EOF check
_dcb.fParity = false; //DWORD: enable parity checking
_dcb.fOutxCtsFlow = false; //DWORD: CTS output flow control
_dcb.fOutxDsrFlow = false; //DWORD: DSR output flow control
_dcb.fDtrControl = DTR_CONTROL_ENABLE; //DWORD: DTR flow control type
_dcb.fDsrSensitivity = false; //DWORD: DSR sensitivity
_dcb.fTXContinueOnXoff = false; //DWORD: XOFF continues Tx
_dcb.fOutX = false; //DWORD: XON/XOFF out flow control
_dcb.fInX = false; //DWORD: XON/XOFF in flow control
_dcb.fErrorChar = false; //DWORD: enable error replacement
_dcb.fNull = false; //DWORD: enable null stripping
_dcb.fRtsControl = RTS_CONTROL_ENABLE; //DWORD: RTS flow control
_dcb.fAbortOnError = false; //WORD : abort reads/writes on error
_dcb.XonLim = 2048; //0xffff; //WORD : transmit XON threshold
_dcb.XoffLim = 512; //0xffff; //WORD : transmit XOFF threshold
_dcb.XonChar = 0x11; //char : Tx and Rx XON character
_dcb.XoffChar = 0x13; //char : Tx and Rx XOFF character
_dcb.ErrorChar = 0; //char : error replacement character
_dcb.EofChar = 0; //char : end of input character
_dcb.EvtChar = 0; //char : received event character
//---- Variables ----//
_TimerInterval = 200; //200 ms
_ModemStatus = 0; //MS_CTS_ON | MS_DSR_ON | MS_RING_ON | MS_RLSD_ON
_DetectRingTime = 15; //15*200 = 3000 ms
_dwDetectingRing = 0;
_Handle = INVALID_HANDLE_VALUE;
_ReadThreadId = -1;
_RunReadThread = 0;
_ReadThreadRunning = 0;
_WriteThreadId = -1;
_RunWriteThread = 0;
_WriteThreadRunning = 0;
_TimerThreadId = -1;
_RunTimerThread = 0;
_TimerThreadRunning = 0;
_hKillRead = 0;
_hKillWrite = 0;
_hSyncWrite = 0;
_hKillTimer = 0;
memset(&_ReadOS, 0, sizeof(OVERLAPPED));
memset(&_WriteOS, 0, sizeof(OVERLAPPED));
_InQueue = new TCommQueue;
_OutQueue = new TCommQueue;
}
//---------------------------------------------------------------------------
__fastcall TComm32::~TComm32()
{
try
{
Close();
}
catch(Exception &e)
{
//ignore errors
}
delete _OutQueue;
delete _InQueue;
}
//---------------------------------------------------------------------------
void __fastcall TComm32::Open(void)
{
if(!_Opened)
{
EComm32Error::TErrorCode ecErrCode = EComm32Error::COMM_NOERROR;
_dwDetectingRing = 0;
if((!ecErrCode) && (!_InQueue->Valid))
{
ecErrCode = EComm32Error::COMM_INITRDBUF; //不能初始化读缓存
}
if((!ecErrCode) && (!_OutQueue->Valid))
{
ecErrCode = EComm32Error::COMM_INITWRBUF; //不能初始化写缓存
}
if((!ecErrCode) && (!_bFromHandle)) //如果已知句柄,不需要打开端口
{
_Handle=CreateFile(_PortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
if(_Handle==INVALID_HANDLE_VALUE)
{
ecErrCode = EComm32Error::COMM_OPENPORT; //不能打开端口
}
}
if((!ecErrCode) && (!SetCommMask(_Handle, EV_RXFLAG)))
{
ecErrCode = EComm32Error::COMM_SETMASK; //不能设置端口事件MASK
}
if((!ecErrCode) && (!_bFromHandle)) //如果已知句柄,不需要设置缓存
{
if(!SetupComm(_Handle, _HwInSize, _HwOutSize))
{
ecErrCode = EComm32Error::COMM_BUFSIZE; //不能设置端口缓存
}
}
if(!ecErrCode)
{
if(!_bFromHandle)
{
//设置预先设定的 DTR 和 RTS 值
if(_dcb.fDtrControl != DTR_CONTROL_HANDSHAKE)
{
_dcb.fDtrControl = _bDTR?DTR_CONTROL_ENABLE:DTR_CONTROL_DISABLE;
}
if((_dcb.fRtsControl != RTS_CONTROL_HANDSHAKE) && (_dcb.fRtsControl != RTS_CONTROL_TOGGLE))
{
_dcb.fRtsControl = _bRTS?RTS_CONTROL_ENABLE:RTS_CONTROL_DISABLE;
}
DCB dcb = _dcb; //设定串口参数
if(!SetCommState(_Handle, &dcb))
{
ecErrCode = EComm32Error::COMM_SETSTATE; //不能设置端口参数
}
}
else //如果已知句柄,不需要设置参数
{
DCB dcb;
if(GetCommState(_Handle, &dcb))
{
dcb.fAbortOnError = false;
if(!SetCommState(_Handle, &dcb))
{
ecErrCode = EComm32Error::COMM_SETSTATE; //不能设置端口参数
}
}
else
{
ecErrCode = EComm32Error::COMM_GETSTATE; //不能得到端口参数
}
}
}
if(!ecErrCode)
{
memset(&_ReadOS, 0, sizeof(OVERLAPPED));
_ReadOS.hEvent = CreateEvent(NULL,true,false,NULL);
_hKillRead = CreateEvent(NULL,true,false,NULL);
_hKillTimer = CreateEvent(NULL,true,false,NULL);
if((!_hKillRead) || (!_ReadOS.hEvent) || (!_hKillTimer))
{
ecErrCode = EComm32Error::COMM_CRRDEVENT; //不能创建端口异步读事件
}
}
if(!ecErrCode)
{
memset(&_WriteOS, 0, sizeof(OVERLAPPED));
_WriteOS.hEvent = CreateEvent(NULL, true, false, NULL);
_hSyncWrite = CreateEvent(NULL, true, false, NULL);
_hKillWrite = CreateEvent(NULL, true, false, NULL);
if((!_hKillWrite) || (!_hSyncWrite) || (!_WriteOS.hEvent))
{
ecErrCode = EComm32Error::COMM_CRWREVENT; //不能创建端口异步写事件
}
}
if(!ecErrCode)
{
_RunReadThread = 1;
if((_ReadThreadId=_beginthread(_ReadThread, 4096, this))==-1)
{
_RunReadThread = 0;
ecErrCode = EComm32Error::COMM_CRRDTHREAD; //不能创建端口读线程
}
}
if(!ecErrCode)
{
_RunTimerThread = 1;
if((_TimerThreadId=_beginthread(_TimerThread, 4096, this))==-1)
{
_RunTimerThread = 0;
ecErrCode = EComm32Error::COMM_CRRDTHREAD; //不能创建端口读线程
}
}
if(!ecErrCode)
{
_RunWriteThread = 1;
if((_WriteThreadId=_beginthread(_WriteThread, 4096, this))==-1)
{
_RunWriteThread = 0;
ecErrCode = EComm32Error::COMM_CRWRTHREAD; //不能创建端口写线程
}
}
if(!ecErrCode)
{
SetThreadPriority((HANDLE)_ReadThreadId,THREAD_PRIORITY_HIGHEST);
//SetThreadPriority((HANDLE)_WriteThreadId,THREAD_PRIORITY_HIGHEST);
_Opened = true;
_DisableWrite = false;
DWORD dwMs; //MS_CTS_ON | MS_DSR_ON | MS_RING_ON | MS_RLSD_ON
if(GetCommModemStatus(_Handle, &dwMs)) //Get modem status after port opened
_ModemStatus = dwMs;
_bDTR = _dcb.fDtrControl != DTR_CONTROL_DISABLE;
_bRTS = _dcb.fRtsControl != RTS_CONTROL_DISABLE;
CommNotify(EV_CTS|EV_DSR|EV_RLSD);
CommAfterOpen();
}
else
{
Close();
throw EComm32Error(ecErrCode);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TComm32::Close(void)
{
EComm32Error::TErrorCode ecErrCode = EComm32Error::COMM_NOERROR;
int i;
if(_Opened)
{
CommBeforeClose();
}
_RunReadThread = 0;
_RunWriteThread = 0;
_RunTimerThread = 0;
if(_Handle!=INVALID_HANDLE_VALUE)
{
SetCommMask(_Handle, EV_RXFLAG); //terminate the WaitCommEvent() func.
}
if(_hKillRead )SetEvent(_hKillRead );
if(_hKillWrite)SetEvent(_hKillWrite);
if(_hKillTimer)SetEvent(_hKillTimer);
//-- read & write thread --
for(i=0; (_ReadThreadRunning||_WriteThreadRunning||_TimerThreadRunning) && (i<100); i++)
{
Sleep(5);
}
if(_ReadThreadRunning||_TimerThreadRunning)
{
ecErrCode = EComm32Error::COMM_CLOSERDT; //不能关闭端口读线程
}
if(_WriteThreadRunning)
{
ecErrCode = EComm32Error::COMM_CLOSEWRT; //不能关闭端口写线程
}
_ReadThreadId=-1;
_WriteThreadId=-1;
//-- read event
if(_ReadOS.hEvent)
{
CloseHandle(_ReadOS.hEvent);
memset(&_ReadOS, 0, sizeof(OVERLAPPED));
}
if(_hKillRead)
{
CloseHandle(_hKillRead);
_hKillRead = NULL;
}
if(_hKillTimer)
{
CloseHandle(_hKillTimer);
_hKillTimer = NULL;
}
//-- write sync --
if(_hSyncWrite)
{
CloseHandle(_hSyncWrite);
_hSyncWrite = NULL;
}
if(_WriteOS.hEvent)
{
CloseHandle(_WriteOS.hEvent);
memset(&_WriteOS, 0, sizeof(OVERLAPPED));
}
if(_hKillWrite)
{
CloseHandle(_hKillWrite);
_hKillWrite = NULL;
}
//-- close handle --
if((_Handle!=INVALID_HANDLE_VALUE) && (!_bFromHandle)) //如果已知句柄,不需要关闭端口
{
CloseHandle(_Handle);
_Handle=INVALID_HANDLE_VALUE;
}
//-- Restore status before opened
_bDTR = _dcb.fDtrControl != DTR_CONTROL_DISABLE;
_bRTS = _dcb.fRtsControl != RTS_CONTROL_DISABLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -