📄 comm.~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 + -