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

📄 comm.cpp

📁 实现RS232数据采集处理,设置RS23传输参数,显示控制终端的数据.
💻 CPP
字号:
//------------------------------------------------------------------

#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.
//

static inline void ValidCtrCheck(TComm *)
{
        new TComm(NULL);
}
//------------------------------------------------------------------
__fastcall TComm::TComm(TComponent* Owner)
        : TComponent(Owner)
{

     CommTimer= new TTimer(this);
     CommTimer->Enabled=false;
     CommTimer->Interval =10;
     CommTimer->OnTimer =ProcTimer;
     hComm = 0;        //通信端口Handle先清空
     FPortOpen =False;
     FCommPort = pnCOM1; //默认COM1
     FBaudRate = br9600;   //9600bps
     FHwHandShaking = hhNone; //不启动硬件流量控制
     FSwHandShaking = shNone; //不启动软件流量控制
     FDataBits = DB8;  //数据位数=8
     FParity = None;   //不作同位检查
     FStopBits = SB1;   //停止位数=1
     FInputLen=0;  //默认是一次指令全部读取
     FDTR=FRTS=false;

}
//------------------------------------------------------------------
namespace Comm
{
        void __fastcall PACKAGE Register()
        {
                 TComponentClass classes[1] = {__classid(TComm)};
                 RegisterComponents("System", classes, 0);
        }
}
//------------------------------------------------------------------
void TComm::OpenComm(void)
{
   HANDLE hNewCommFile;
   String  ComStr;
   char *COMNo;
     ComStr = "COM" + IntToStr(1+FCommPort);
     hNewCommFile = CreateFile(  ComStr.c_str(),
                                 GENERIC_READ | GENERIC_WRITE,
                                 0, //not shared
                                 NULL, //no security
                                 OPEN_EXISTING,
                                 0,//No Overlapped
                                 NULL //template
                                 );

     if (hNewCommFile == INVALID_HANDLE_VALUE)
        ShowMessage("Error opening serial port");
        //raise Exception.Create( "Error opening serial port" );

     if (!SetupComm( hNewCommFile, INPUTBUFFERSIZE, INPUTBUFFERSIZE ))
       {
           CloseHandle( hComm );
           ShowMessage( "Cannot setup comm buffer" );
       }
     // It is ok to continue.
     hComm = hNewCommFile;
     // 清除湲冲区
     PurgeComm( hComm, PURGE_TXABORT | PURGE_RXABORT |
                           PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
     // 通信端口配置
     _SetCommState();
     FDTR = true;
     SetDTRStatus(FDTR);
     SetRTSStatus(FRTS);
     FPortOpen=True;
     CommTimer->Enabled=true;
}

//------------------------------------------------------------------
void TComm::_SetCommState(void)
{
   DCB dcb;
   DWORD  tmpValue;
     //取得串行端口设置
   GetCommState( hComm, &dcb );
    //更改传输速率
     dcb.BaudRate = FBaudRate;
     dcb.fBinary  = 1; //必须指定为1
     dcb.Parity =  (unsigned char)FParity ;//Parity的指定
     FParityCheck=false;
     if (FParity!=0)
        FParityCheck=true;
     if (FParityCheck)
         dcb.fParity = (unsigned long)dcb_ParityCheck;          // Enable parity check
     // 设置硬件流量控制
     switch (FHwHandShaking){
      case hhNone:
           dcb.fRtsControl=0;
           break;
      case hhNoneRTSON:
          dcb.fRtsControl = RTS_CONTROL_ENABLE; //dcb_RtsControlEnable;
          break;
      case hhRTSCTS:
           dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;//dcb_RtsControlHandShake;
           dcb.fOutxCtsFlow = 1; //dcb_OutxCtsFlow;
           break;
     }
     //设置软件流量控制
     if (FSwHandShaking!=shNone)
     {
           dcb.fOutX = 1; //dcb_OutX;
           dcb.fInX  = 1; //dcb_InX;
     }
     //设置数据位数
     dcb.ByteSize = FDataBits  + 5;
     //设置停止位数
     dcb.StopBits =  FStopBits ;
     //将设置写入
     SetCommState( hComm, &dcb );

}

//---------- 组件用的定时器事件  -----------------//
void __fastcall TComm::ProcTimer(TObject *Sender)
{
   DWORD     tmpValue;
   DWORD     dwCommError;
   COMSTAT   CS;
    if (hComm==0) return;
    //若设置读取的字符数,检查并引发事件
     ClearCommError(hComm,&dwCommError,&CS);  //取得状态
     FCommError = dwCommError; //错误数值
    if (FRThreshold>0)
     if (CS.cbInQue >=(DWORD)FRThreshold)   ReceiveData();
    GetModemState();
//    EventProcess();
    Application->ProcessMessages(); //看有无其他的指令需执行,以免锁住
    //检查线路状态是否发生改变,若改变则引发事件
    tmpValue=FCommEvent;
    if (tmpValue!=0)  ModemStateChange(tmpValue);
     Application->ProcessMessages(); //看有无其他的指令需执行,以免锁住
    //若发生错误,则引发错误
    tmpValue=FCommError;
    if (tmpValue!=0)  ReceiveError(tmpValue);
     Application->ProcessMessages(); //看有无其他的指令需执行,以免锁住
}


//------------------- 线路状态检测函数 ----------------//
void __fastcall TComm::GetModemState(void)
{
 DWORD  dwModemState;
    if (hComm==0)
      ShowMessage("COM Port is not opened yet!");
     if (GetCommModemStatus(hComm, &dwModemState ))
      {
       if (dwModemState & MS_RLSD_ON)
        {
          if (!FCDHolding) FCommEvent=FCommEvent+EV_RLSD;
          FCDHolding=true;
        }
       else
       {
          if (FCDHolding)  FCommEvent=FCommEvent-EV_RLSD;
          FCDHolding=false;
       }
       if (dwModemState & MS_DSR_ON)
        {
          if (!FDSRHolding) FCommEvent=FCommEvent+EV_DSR;
          FDSRHolding=true;
        }
       else
        {
          if (FDSRHolding) FCommEvent=FCommEvent-EV_DSR;
          FDSRHolding=false;
        }
      if (dwModemState & MS_RING_ON)
       {
          if (!FRIHolding) FCommEvent=FCommEvent+EV_RING;
          FRIHolding=true;
        }
       else
        {
          if (FRIHolding) FCommEvent=FCommEvent-EV_RING;
          FRIHolding=false;
        }
      if (dwModemState & MS_CTS_ON)
        {
          if (!FCTSHolding) FCommEvent=FCommEvent+EV_CTS;
          FCTSHolding=true;
        }
       else
        {
          if (FCTSHolding) FCommEvent=FCommEvent-EV_CTS;
          FCTSHolding=false;
        }
      } // GetCommModem Loop
}

//---------------- Receive Data ---------------------//
void __fastcall TComm::ReceiveData(void)
{
  if (FOnReceiveData)  FOnReceiveData(this);
}

//----------------- Modem State Change ------------//
void __fastcall TComm::ModemStateChange(DWORD ModemEvent)
{
     if (FOnModemStateChange) FOnModemStateChange( this, ModemEvent );
}

//----------------  Receive Error ---------------//
void __fastcall TComm::ReceiveError(DWORD EvtMask)
{
       if (FOnReceiveError) FOnReceiveError( this, EvtMask );
}
//-----------------  Change Port --------------//
void __fastcall TComm::SetCommPort(TComPortNumber Port)
{
 if (Port==FCommPort) return;
 FCommPort = Port;
}

//----------------  设置速率 ----------------//
void __fastcall TComm::SetBaudRate(TBaudRate Rate)
{
     if (Rate == FBaudRate) return;
     FBaudRate = Rate;
     if (hComm != 0)  _SetCommState();
}
//----------------  硬件交握 ----------------//
THwHandShaking __fastcall TComm::GetHwHandShaking(void)
{
 return(FHwHandShaking);
}

void __fastcall TComm::SetHwHandShaking(THwHandShaking c )
{
     if (c == FHwHandShaking) return;
     FHwHandShaking = c;
     if (hComm != 0)  _SetCommState();

}
//----------------  软件交握 ----------------//
TSwHandShaking __fastcall TComm::GetSwHandShaking(void)
{
  return(FSwHandShaking);
}

void __fastcall TComm::SetSwHandShaking(TSwHandShaking c )
{
     if (c == FSwHandShaking)  return;
     FSwHandShaking = c;
     if (hComm != 0) _SetCommState();
}
//----------------  数据位数 ----------------//
void __fastcall TComm::SetDataBits(TDataBits Size  )
{
     if (Size == FDataBits) return;
     FDataBits = Size;
     if (hComm != 0) _SetCommState();
}
//----------------  奇偶校验 ----------------//
void __fastcall TComm::SetParity(TParity p  )
{
     if (p == FParity) return;
     FParity = p;
     if (hComm != 0) _SetCommState();
}
//----------------  停止位 ----------------//
void __fastcall TComm::SetStopBits(TStopBits Bits  )
{
     if (Bits == FStopBits) return;
     FStopBits = Bits;
     if (hComm != 0) _SetCommState();
}
//----------------  用来清除Buffer ----------------//
void __fastcall TComm::SetInDataCount(DWORD StrNo)
{
   if (StrNo!=0) return;
   PurgeComm(hComm, PURGE_RXCLEAR);  // 清除COM 资料
}
//----------------  接收阈值 ----------------//
void __fastcall TComm::SetRThreshold(int RTNo)
{
  FRThreshold=RTNo;
}
//----------------  开始通信端口 ----------------//
void __fastcall TComm::SetPortOpen(bool b)
{
  CommTimer->Enabled=false;
  if (b)  //若指定打开通信端口,则…
  {
   if (FPortOpen)
   {
     ShowMessage("COM Port has been opened!");
     return;
   } //FportOpen loop
   OpenComm(); //打开通信端口
   return;
  } //b loop
  CloseComm();

}
//----------------  DTR状态 ----------------//
bool __fastcall TComm::GetDTRStatus()
{
 return(FDTR);
}

void __fastcall TComm::SetDTRStatus(bool b)
{
  FDTR=b;
  if (hComm==0) return;
  if (b)
   EscapeCommFunction(hComm,SETDTR); //将DTR升至高电位
  else
   EscapeCommFunction(hComm,CLRDTR);//将DTR降至低电位
}
//----------------  RTS状态 ----------------//
bool __fastcall TComm::GetRTSStatus()
{
 return(FRTS);
}

void __fastcall TComm::SetRTSStatus(bool b)
{
  FRTS=b;
  if (hComm==0) return;
  if (b)
   EscapeCommFunction(hComm,SETRTS); //将RTS升至高电位
  else
   EscapeCommFunction(hComm,CLRRTS);//将RTS降至低电位
}
//----------------  读取数据函数 ----------------//
void __fastcall TComm::ReadProcess(void)
{
   DWORD     nBytesRead,dwCommError,i,ReadLen;
   COMSTAT  CS;
     //使用ClearCommError得知有多少的数据在缓冲区中
     //亦一并得知错误种类
     ClearCommError(hComm,&dwCommError,&CS);  //取得状态
     FCommError=dwCommError; //错误数值
     if (CS.cbInQue !=0)  //若缓冲区有数据,则读取
     {
       if (InputLen==0)  //指定读取的数据数
         ReadLen=CS.cbInQue;
       else
         ReadLen=InputLen;
       if (CS.cbInQue > sizeof(szInputBuffer))
         PurgeComm(hComm, PURGE_RXCLEAR);  // 清除COM 资料
       else
         {
           //读取数据

           if (ReadFile(hComm, szInputBuffer,ReadLen,&nBytesRead,NULL)) // 接收COM 的数据
           {
             //取出数据
             //FInputData=copy(szInputBuffer,1,ReadLen);
             FInputData=AnsiString(szInputBuffer,(unsigned int)ReadLen);
             //设置字节动态数组的长度
             FInputByteData.Length =ReadLen;
             //SetLength(FInputByteData,ReadLen);
             //将数据搬到数组中
               for (i=0 ;i<ReadLen;i++)
                FInputByteData[i]=szInputBuffer[i];
           }  //ReadFile Loop
         }//else Loop
     } //cs.binQue Loop

}
//----------------  事件检测 ----------------//
void __fastcall TComm::EventProcess(void)
{

}
//----------------  关闭通信端口函数 ----------------//
void __fastcall TComm::CloseComm(void)
{
     if (hComm == 0) return;
     // 实际关闭通信端口
     CloseHandle( hComm );
     FPortOpen = false;
     hComm = 0;
}
//----------------  硬件线路状态值读取 ----------------//
int __fastcall  TComm::ReadCommEvent(void)
{
 return(FCommEvent);
}
//----------------  错误状态值的读取 ----------------//
int __fastcall  TComm::ReadCommError(void)
{
  return(FCommError);
}
//----------------  返回收到的数据 ----------------//
String __fastcall  TComm::ReadInputData(void)
{
  if (hComm==0)
    ShowMessage("COM Port is not opened yet!");
  //决定每一次的指令要返回多少的字符(以Byte为单位)
  ReadProcess();
  return(FInputData);
}
//----------------  读取已收到的数据数量 ----------------//
int __fastcall  TComm::ReadInDataCount(void)
{
   COMSTAT CS;
   DWORD   dwCommError;
   ClearCommError(hComm,&dwCommError,&CS);  //取得状态
   return(CS.cbInQue);
}
//----------------  取得CD线路状态 ----------------//
bool __fastcall  TComm::ReadCDHolding(void)
{
   return(FCDHolding);
}
//----------------  取得DSR线路状态 ----------------//
bool __fastcall  TComm::ReadDSRHolding(void)
{
  return(FDSRHolding);
}
//----------------  取得RI线路状态 ----------------//
bool __fastcall  TComm::ReadRIHolding(void)
{
  return(FRIHolding);
}
//----------------  取得CTS线路状态 ----------------//
bool __fastcall  TComm::ReadCTSHolding(void)
{
  return(FCTSHolding);
}
//---------------  字符串指令输出  -----------------//
bool    TComm::OutputString(String DataToWrite)
{
  DWORD lrc;
  Char  *tmpChar;
  if (hComm==0)
   {
     ShowMessage("COM Port is not opened yet!");
     return(false);
   }
   // 送出数据
   tmpChar=DataToWrite.c_str();
   if (WriteFile(hComm,tmpChar,DataToWrite.Length(), &lrc, NULL))
     return(true);
   return(false);


}
//---------------  字符串字节输出 ---------------//
bool    TComm::OutputByte(const DynamicArray<byte> ByteData)
{
    DWORD  lrc,SendNum;
    int    i;
    byte   ch;
 if (hComm==0)
    {
     ShowMessage("COM Port is not opened yet!");
     return(false);
   }
      // 送出数据
  for (i=ByteData.Low;i<=ByteData.High ;i++)
    {
     ch = ByteData[i];
     WriteFile(hComm,&ch,1,&lrc,NULL);
    }
   return(true);
}
//---------------  输入字节读取 --------------//
DynamicArray<byte>  TComm::ReadInputByte(void)
{
  int i;
  if (hComm==0)
    ShowMessage("COM Port is not opened yet!");
  ReadProcess();//执行读取函数
  return(FInputByteData);//取得数据数组的最高索引值

}

⌨️ 快捷键说明

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