//---------------------------------------------------------------------------
#pragma hdrstop
#include "TComm.h"
//---------------------------------------------------------------------------
TComm::TComm(TObject* pOwner)
{
CommOpen=false;
hCom=NULL;
HWND=NULL;
fCommReceived=NULL;
fCommSendFinished=NULL;
CommUnuseable=true;
try{
CommThread=new TCommThread(true);
if(CommThread==INVALID_HANDLE_VALUE){
ShowMessage("Can't create thread!");
CommThread=NULL;
return;
}
HWND=AllocateHWnd(MessageProc);
if(HWND==INVALID_HANDLE_VALUE){
ShowMessage("Can't create window!");
delete CommThread;
CommThread=NULL;
return;
}
memset(&osW,0,sizeof(osW));
memset(&osR,0,sizeof(osR));
osR.hEvent=CreateEvent(NULL,true,FALSE,NULL);
/*os.Internal=0;
os.InternalHigh=0;
os.Offset=0;
os.OffsetHigh=0;*/
osW.hEvent=CreateEvent(NULL,true,FALSE,NULL);
if(osR.hEvent==INVALID_HANDLE_VALUE||osW.hEvent==INVALID_HANDLE_VALUE){
delete CommThread;
CommThread=NULL;
DeallocateHWnd(HWND);
HWND=NULL;
ShowMessage("Can't create event!");
CloseHandle(osR.hEvent);
CloseHandle(osW.hEvent);
osR.hEvent=0;
osW.hEvent=0;
return;
}
CommUnuseable=false;
Owner=pOwner;
CommThread->HWND=HWND;
}
catch(Exception& e){
ShowMessage(e.Message);
if(CommThread) delete CommThread;
if(HWND) DeallocateHWnd(HWND);
return;
}
}
//---------------------------------------------------------------------------
TComm::~TComm()
{
if(CommOpen) Close();
if(CommThread){
CommThread->Resume();
CommThread->Terminate();
}
if(HWND) DeallocateHWnd(HWND);
if(osR.hEvent){
CloseHandle(osR.hEvent);
osR.hEvent=0;
}
if(osW.hEvent){
CloseHandle(osW.hEvent);
osW.hEvent=0;
}
}
//---------------------------------------------------------------------------
HANDLE TComm::Open(char* CommPort)
{
//CommPort is a string just like "com1","com2"
//if you want to open a com over 10 ,ep com10,you should write like this:
//"\\\\.\\com10"
if(!CommUnuseable&&!CommOpen){
try{
hCom=CreateFile(CommPort,GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
if(hCom!=INVALID_HANDLE_VALUE){
if(!SetCommMask(hCom,EV_RXCHAR|EV_TXEMPTY
|EV_CTS|EV_DSR|EV_RLSD|EV_RXFLAG|EV_RX80FULL|EV_ERR)){
ShowMessage("Mask setup failure!");
hCom=NULL;
return hCom;
}
if(!SetupComm(hCom,BufferSize,BufferSize)){
ShowMessage("Buffer setup failure!");
CloseHandle(hCom);
hCom=NULL;
return hCom;
}
PurgeComm( hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR|PURGE_RXCLEAR );
GetCommState(hCom,&dcb);
GetCommTimeouts(hCom,&CommTimeOuts);
osR.Offset=0;
osR.OffsetHigh=0;
osW.Offset=0;
osW.OffsetHigh=0;
CommOpen=true;
CommThread->hCom=hCom;
CommThread->HWND=HWND;
CommThread->CommOpen=true;
CommThread->Resume();
return hCom;
}
}
catch(Exception& e){
ShowMessage(e.Message);
return NULL;
}
}
return hCom;
}
HANDLE TComm::Open(int CommPort)
{
char CommName[]="\\\\.\\com00";
if(CommPort<10){
CommName[7]='0'+CommPort;
CommName[8]=0;
}
else{
CommName[7]='0'+CommPort/10;
CommName[8]='0'+CommPort%10;
}
return Open(CommName);
}
//---------------------------------------------------------------------------
bool TComm::Close(void)
{
if(CommOpen){
CommThread->CommOpen=false;
PurgeComm(hCom,PURGE_RXCLEAR);
if(CloseHandle(hCom)){
hCom=NULL;
CommOpen=false;
CommThread->Suspend();
CommThread->hCom=NULL;
return true;
}
else CommThread->CommOpen=true;
return false;
}
return true;
}
//---------------------------------------------------------------------------
bool TComm::SetCommPara(DCB* dcb)
{
if(CommOpen){
if(SetCommState(hCom,dcb)) return true;
}
return false;
}
//---------------------------------------------------------------------------
bool TComm::SetTimePara(COMMTIMEOUTS *CommTime)
{
if(CommOpen){
if(SetCommTimeouts(hCom,CommTime)) return true;
}
return false;
}
//---------------------------------------------------------------------------
bool TComm::SetComm(int BaudRate,int ByteSize,int Parity,int StopBits)
{
if(CommOpen){
//考虑到实际中可能有超过256000或者非标准的bps,删除检查
/*switch(BaudRate){
case 110:
case 300:
case 600:
case 1200:
case 2400:
case 4800:
case 9600:
case 14400:
case 19200:
case 38400:
case 57600:
case 115200:
case 128000:
case 256000:break;
default: return false;
}*/
if(ByteSize!=8&&ByteSize!=9) return false;
switch(Parity){
case 2:Parity=EVENPARITY;break;
case 0:Parity=NOPARITY;break;
case 1:Parity=ODDPARITY;break;
case MARKPARITY: break;
case SPACEPARITY:break;
default: return false;
}
switch(StopBits){
case 1:StopBits=0;break;
case 2:StopBits=2;break;
default:return false;
}
dcb.BaudRate=BaudRate;
dcb.ByteSize=ByteSize;
dcb.Parity=Parity;
dcb.StopBits=StopBits;
dcb.fOutX=0;
dcb.fInX=0;
dcb.fDtrControl =0;
dcb.fRtsControl =0;
if(SetCommState(hCom,&dcb))return true;
else{
GetCommState(hCom,&dcb);
return false;
}
}
return false;
}
//---------------------------------------------------------------------------
int TComm::SendData(void* SendData,int Length,bool Wait)
{
unsigned long sended=0,state=0;
if(CommOpen&&SendData&&Length){
if(!WriteFile(hCom,SendData,Length,&sended,&osW)&&Wait){
if(GetLastError()==ERROR_IO_PENDING){
state=WaitForSingleObject(osW.hEvent,1000);
if(state==WAIT_TIMEOUT){//超时
PurgeComm(hCom,PURGE_TXCLEAR);
}
else{
GetOverlappedResult(hCom,&osW,&sended,false);
osW.Offset+=sended;
}
}
}
}
return sended;
}
int TComm::SendData(void* SendData,int Length)
{
return this->SendData(SendData,Length,false);
}
//---------------------------------------------------------------------------
int TComm::GetReceivedCount()
{
unsigned long errorcode;
if(CommOpen){
ClearCommError(hCom,&errorcode,&CommStat);
return(CommStat.cbInQue);
}
return 0;
}
//---------------------------------------------------------------------------
int TComm::ReadComm(void* ReadBuffer,int Length)
{
unsigned long readed=0,state=0;
if(CommOpen&&ReadBuffer&&Length){
if(!ReadFile(hCom,ReadBuffer,Length,&readed,&osR)){
if(GetLastError()==ERROR_IO_PENDING){
state=WaitForSingleObject(osR.hEvent,1000);
if(state==WAIT_TIMEOUT){
PurgeComm(hCom,PURGE_RXCLEAR);
}
GetOverlappedResult(hCom,&osR,&readed,false);
}
}
}
return readed;
}
//---------------------------------------------------------------------------
int TComm::ReadCommAll(void* ReadBuffer, int BufSize)//081001 增加一个读空缓冲区的函数
//如果用户提供的缓冲区大小大于已收到的字节,该函数将读空硬件缓冲区,否则读满用户缓冲区
//在调用此函数前,不要调用GetReceivedCount函数!
{
int count;
if(BufSize<=0){
return 0;
}
count=GetReceivedCount();
if(count>BufSize){
count=BufSize;
}
if(count<=0){
return 0;
}
return ReadComm(ReadBuffer,count);
}
//------------------------------------------------------------