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

📄 comm.cpp

📁 uart串口通信的控件和demo,用API 编写
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
//  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 + -