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

📄 tcomm32.cpp

📁 简单实用, 功能强大的 C++ Builder 串口控件! 本控件是免费的, 不需要注册, 有关授权及许可协议详见 license.txt 文件。 1.支持二进制数据和文本数据的收发 2.支
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/***************************************************************************\
*                                                                           *
*                  TComm32.h - 串行口通讯程序, 版本 1.3.3.5                 *
*                              Bulid: 09-05-2004                            *
*                    Copyright (C) 1997-2004, Victor Chen                   *
*                      Homepage: http://www.cppfans.com                     *
*                          Email: victor@cppfans.com                        *
*                                                                           *
\***************************************************************************/

#pragma hdrstop
#include "TComm32.h"
#include "yb_base.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------

char _TComm32_Copyright_YBCHEN[] = "\r\nTComm32.cpp Serial Port & Modem Library\r\n"
                                   "Copyright (c) Victor Chen\r\n"
                                   "http://www.cppfans.com\r\n"
                                   "Email: victor@cppfans.com\r\n";

/***************************************************************************\
*                               TCommQueue                                  *
\***************************************************************************/

TCommQueue::TCommQueue(long lSize)
 {
   _BufSize   = lSize;
   _Head      = 0;
   _Tail      = 0;
   _Buffer    = NULL;

   try
    {
      fSetBufSize(_BufSize);
    }
   catch(...)
    {
      fSetBufSize(0);
    }
 }
//---------------------------------------------------------------------------

TCommQueue::~TCommQueue()
 {
   fSetBufSize(0);
 }
//---------------------------------------------------------------------------

void TCommQueue::fSetBufSize(long n)
 {
   Clear(); //clear buffer before resize

   if(n<=0)
    {
      if(_Buffer)
       {
         free(_Buffer);
         _Buffer = NULL;
       }
    }
   else
    {
      char far *NewBuffer = (char far *)realloc(_Buffer, n);
      if(NewBuffer)
       {
         _Buffer = NewBuffer;
         _BufSize = n;
       }

      if(!NewBuffer)
       {
         throw EComm32Error(EComm32Error::COMM_NOMEMORY); //内存不够
       }
    }
 }

//---------------------------------------------------------------------------
long TCommQueue::In(const char far *c)
{
  if((_Buffer) && (c) && (fGetRemain()>0))
   {
     _Buffer[_Tail] = *c;
     _Tail = (_Tail+1)%_BufSize;
     return 1;
   }
  return 0;
}
//---------------------------------------------------------------------------

long TCommQueue::In(const char far *c, long n)
 {
   long BytesToIn = 0;           // 0 1 2 3 4 5 6 7 8 9 <- address
                                 //     ~~~             <- data
   if((_Buffer) && (n>0) && (c)) // ....H...T.......... <- pointers
    {
      long BytesAppend, BytesAhead;

      if((BytesToIn=fGetRemain())>n)
          BytesToIn=n;

      if((BytesAhead=_Tail+BytesToIn-_BufSize)<0)
          BytesAhead=0;

      BytesAppend=BytesToIn-BytesAhead;

      memcpy(_Buffer+_Tail, c            , BytesAppend);
      memcpy(_Buffer      , c+BytesAppend, BytesAhead );

      _Tail = (_Tail + BytesToIn) % _BufSize;
    }

   return BytesToIn;
 }
//---------------------------------------------------------------------------

long TCommQueue::Out(char far *c)
{
  if((_Buffer) && (c) && (fGetCount()>0))
   {
     *c = _Buffer[_Head];
     _Head = (_Head+1)%_BufSize;
     return 1;
   }
  return 0;
}
//---------------------------------------------------------------------------

long TCommQueue::Out(char far *c, long n)
 {
   long BytesToOut = 0;

   if((_Buffer) && (n>0) && (c))
    {
      long BytesTail, BytesAhead;

      if((BytesToOut=fGetCount())>n)
          BytesToOut=n;

      if((BytesAhead=_Head+BytesToOut-_BufSize)<0)
          BytesAhead=0;

      BytesTail=BytesToOut-BytesAhead;

      memcpy(c          , _Buffer+_Head, BytesTail );
      memcpy(c+BytesTail, _Buffer      , BytesAhead);

      _Head = (_Head + BytesToOut) % _BufSize;
    }

   return BytesToOut;
 }

/***************************************************************************\
*                           TCommSerialPortInfo                             *
\***************************************************************************/

__fastcall TCommSerialPortInfo::TCommSerialPortInfo()
{
  _bFromSysDrv = false;
  _PortList = new TStringList;
  Refresh();
}
//---------------------------------------------------------------------------

__fastcall TCommSerialPortInfo::~TCommSerialPortInfo()
{
  delete _PortList;
}
//---------------------------------------------------------------------------

void __fastcall TCommSerialPortInfo::Refresh(void)
{
  _PortList->Clear();
  _bFromSysDrv = false;
  ListFromSystem();

  if(_PortList->Count<=0)
   {
     for(int i=1; i<=4; i++)
       _PortList->Add(PortName(i));
     _bFromSysDrv = false;
   }
}
//---------------------------------------------------------------------------

int __fastcall TCommSerialPortInfo::PortNo(AnsiString s)
{
  if(s.SubString(1,3).UpperCase()=="COM")
   {
     int n = atoi(s.SubString(4,s.Length()).c_str());
     if(n>0)return n;
   }
  return 0;
}
//---------------------------------------------------------------------------

AnsiString __fastcall TCommSerialPortInfo::PortName(int iPortNo)
{
  AnsiString s;
  s.sprintf("COM%d",iPortNo);
  return s;
}
//---------------------------------------------------------------------------

void __fastcall TCommSerialPortInfo::ListFromSystem(void)
{
  TRegistry *reg=NULL;
  TStringList *names=NULL;
  AnsiString sPName;
  int iPortNo;

  try
   {
     try
      {
        names = new TStringList;
        reg = new TRegistry;

        reg->RootKey=HKEY_LOCAL_MACHINE;
        reg->OpenKey("HARDWARE\\DEVICEMAP\\SERIALCOMM",false);
        reg->GetValueNames(names);

        for(int i=0; i<names->Count; i++)
         {
           try
            {
              sPName = reg->ReadString(names->Strings[i]);
              iPortNo = PortNo(sPName);
              if(iPortNo>0)
               {
                 _PortList->Add(PortName(iPortNo));
               }
            }
           catch(Exception &e)
            {
              //ignore errors
            }
         }

        _PortList->CustomSort(PortListSortCompare);
        _bFromSysDrv = true;
      }
     catch(Exception &e)
      {
        //ignore errors
      }
   }
  __finally
   {
     if(reg) delete reg;
     if(names) delete names;
   }
}
//---------------------------------------------------------------------------

int __fastcall TCommSerialPortInfo::PortListSortCompare(TStringList* lpList, int Index1, int Index2)
{
  return PortNo(lpList->Strings[Index1]) - PortNo(lpList->Strings[Index2]);
}
//---------------------------------------------------------------------------

/***************************************************************************\
*                             TComm32 Threads                               *
\***************************************************************************/

void TComm32::_ReadThread(void *Param)
{
  TComm32 *Comm = (TComm32 *) Param;
  Comm->_ReadThreadRunning = 1;

  COMSTAT ComStat;
  const RecvBufSize = 2048;
  char RecvBuf[RecvBufSize];
  DWORD   dwErrorFlag, dwBytes, BytesToRead, BytesRemain;

  OVERLAPPED os;
  DWORD dwEvtMask, dwModemStatus;

  os.hEvent = CreateEvent(NULL, true, false, NULL);
  if(os.hEvent)
   {
     if(SetCommMask(Comm->Handle, EV_RXCHAR|EV_TXEMPTY|EV_CTS|EV_DSR|EV_RLSD|EV_RXFLAG|EV_RX80FULL|EV_ERR))
      {
        HANDLE StatusWaits[2] = {Comm->_hKillRead, os.hEvent};

        while(Comm->_RunReadThread)
         {
           dwEvtMask = 0;
           if(!WaitCommEvent(Comm->Handle, &dwEvtMask, &os))
            {
              if(GetLastError() == ERROR_IO_PENDING)
               {
                 if(WaitForMultipleObjects(2, StatusWaits, false, INFINITE) == WAIT_OBJECT_0)
                   break;
               }
            }
           if(!Comm->_RunReadThread)
             break;

           if(dwEvtMask & EV_RXCHAR)
            {
              ClearCommError(Comm->Handle, &dwErrorFlag, &ComStat);
              BytesRemain = ComStat.cbInQue;

              while(BytesRemain>0)
               {
                 BytesToRead = BytesRemain<RecvBufSize?BytesRemain:RecvBufSize;
                 if(ReadFile(Comm->Handle, RecvBuf, BytesToRead, &dwBytes, &Comm->_ReadOS))
                  {
                    Comm->_InQueue->In(RecvBuf, dwBytes);
                    BytesRemain-=dwBytes;
                  }
               }
            }

           if(dwEvtMask & (EV_CTS|EV_DSR|EV_RLSD))
            {
              if(GetCommModemStatus(Comm->Handle, &dwModemStatus))
               {
                 Comm->_ModemStatus = dwModemStatus;
               }
              if(dwEvtMask & EV_CTS)
               {
                 if((!Comm->FromHandle) && (Comm->_dcb.fOutxCtsFlow)  && (Comm->_ModemStatus & MS_CTS_ON))
                   dwEvtMask |= EV_TXEMPTY;
               }
              if(dwEvtMask & EV_RLSD)
               {
                 Comm->_dwDetectingRing = 0;
               }
            }

           if(dwEvtMask & EV_TXEMPTY)
            {
              if((Comm->_ModemStatus & MS_CTS_ON) || (!Comm->_dcb.fOutxCtsFlow) || (Comm->FromHandle))
               {
                 if(Comm->_InQueue->Count)
                   dwEvtMask &=~ EV_TXEMPTY;
                 SetEvent(Comm->_hSyncWrite);
               }
            }

           if(dwEvtMask & EV_ERR)
            {
              ClearCommError(Comm->Handle, &dwErrorFlag, &ComStat);
            }

           Comm->CommNotify(dwEvtMask);
         }
      }

     CloseHandle(os.hEvent);
   }

  Comm->_ReadThreadRunning = 0;
}
//---------------------------------------------------------------------------

void TComm32::_WriteThread(void *Param)
{
  TComm32 *Comm = (TComm32 *) Param;
  Comm->_WriteThreadRunning = 1;

  const SendBufSize = 256;
  char SendBuf[SendBufSize];
  DWORD BytesSent=0, BytesToSend=0;

  COMSTAT ComStat;
  DWORD dwErrorFlag, dwBytesWr;

  int iSingled;
  HANDLE MainWaits[2] = {Comm->_hKillWrite, Comm->_hSyncWrite};
  HANDLE OvlWriteWaits[2] = {Comm->_hKillWrite, Comm->_WriteOS.hEvent};

  while(Comm->_RunWriteThread)
   {
     iSingled = WaitForMultipleObjects(2, MainWaits, false, INFINITE);
     if((!Comm->_RunWriteThread) || (iSingled==WAIT_OBJECT_0))
       break;
     ResetEvent(Comm->_hSyncWrite);

     if(BytesSent<BytesToSend)
      {
        if(WriteFile(Comm->Handle, SendBuf+BytesSent, BytesToSend-BytesSent, &dwBytesWr, &Comm->_WriteOS))
         {
           BytesSent+=dwBytesWr;
         }
        else if(GetLastError()==ERROR_IO_PENDING)
         {
           iSingled = WaitForMultipleObjects(2, OvlWriteWaits, false, INFINITE);
           if((!Comm->_RunWriteThread) || (iSingled==WAIT_OBJECT_0))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -