⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcomm32.cpp

📁 简单实用, 功能强大的 C++ Builder 串口控件! 本控件是免费的, 不需要注册, 有关授权及许可协议详见 license.txt 文件。 1.支持二进制数据和文本数据的收发 2.支
💻 CPP
📖 第 1 页 / 共 3 页
字号:
             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 + -