📄 comm.~cpp
字号:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Comm.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TSerialPort *SerialPort;
HANDLE m_hComm;
HANDLE hReceiveReady;
DCB m_dcb;
AnsiString m_ComName,m_SendBuf;
AnsiString FileName;
char filename[100];
char FileBuf[1024];
RecThread *ReadThread;
COMMTIMEOUTS m_CommTimeouts;
LPOVERLAPPED lpOverlappedWrite;
unsigned long BytesToWrite,BytesWritten; //准备发送的字符长度,实际发出的字符数
unsigned long lWriteLength;
unsigned long lBytesRead,lBytesWrited;
unsigned long send;
unsigned long iFileLength;
int iFileHandle;
bool bOpen;
//---------------------------------------------------------------------------
__fastcall TSerialPort::TSerialPort(TComponent* Owner)
: TForm(Owner)
{
m_hComm = NULL;
lpOverlappedWrite=new OVERLAPPED;
memset(lpOverlappedWrite,0,sizeof(OVERLAPPED));
lpOverlappedWrite->hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
lpOverlappedRead=new OVERLAPPED;
memset(lpOverlappedRead,0,sizeof(OVERLAPPED));
lpOverlappedRead->hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
hReceiveReady=CreateEvent(NULL,TRUE,FALSE,NULL);
EnableCmp(true,false);
}
//---------------------------------------------------------------------------
bool TSerialPort::EnableCmp(bool x,bool y)
{
CmbComName->Enabled=x;
CmbBaudRate->Enabled=x;
CmbByteSize->Enabled=x;
CmbStopBits->Enabled=x;
CmbParity->Enabled=x;
BtnOpen->Enabled=x;
BtnClose->Enabled=y;
BtnSendChar->Enabled=y;
BtnSendFile->Enabled=y;
BtnBrowse->Enabled=y;
BtnCancelSend->Enabled=y;
BtnCancelRece->Enabled=y;
return true;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnOpenClick(TObject *Sender)
{ Shape1->Brush->Color=clRed;
if(m_hComm)
{
CloseHandle(m_hComm);
m_hComm=NULL;
}
m_ComName=CmbComName->Text;
m_hComm=CreateFile(m_ComName.c_str(), //串口号
GENERIC_READ|GENERIC_WRITE, //允许读写
0, //通讯设备必须以独占方式打开
NULL, //无安全属性
OPEN_EXISTING, //通讯设备已存在
FILE_FLAG_OVERLAPPED, //异步I/O
0); //通讯设备不能用模板打开
if(m_hComm==INVALID_HANDLE_VALUE)
{
MessageDlg("端口打开出错!", mtWarning, TMsgDlgButtons() << mbOK, 0);
m_hComm=NULL;
return;
}
StatusBar->Panels->Items[0]->Text=m_ComName+"串口已打开!";
EnableCmp(false,true);
BtnCancelSend->Enabled=false;
BtnCancelRece->Enabled=false;
// 设置timeout
m_CommTimeouts.ReadIntervalTimeout = 100;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
m_CommTimeouts.ReadTotalTimeoutConstant = 0;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
m_CommTimeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(m_hComm, &m_CommTimeouts);
SetCommMask(m_hComm, EV_RXCHAR);
SetupComm(m_hComm,1024,1024);
GetCommState(m_hComm, &m_dcb); //获得DCB状态
// m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
m_dcb.BaudRate=CmbBaudRate->Text.ToInt(); //设置波特率
m_dcb.ByteSize=CmbByteSize->Text.ToInt(); //设置数据位
m_dcb.StopBits=CmbStopBits->ItemIndex; //设置停止位
m_dcb.Parity=CmbParity->ItemIndex; //设置校验位
SetCommState(m_hComm, &m_dcb); //
ReadThread=new RecThread(true);
ReadThread->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnCloseClick(TObject *Sender)
{ Shape1->Brush->Color=clGreen;
if(m_hComm!=INVALID_HANDLE_VALUE) CloseHandle(m_hComm);
m_hComm=NULL;
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
StatusBar->Panels->Items[0]->Text=m_ComName+"串口已关闭!";
EnableCmp(true,false);
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnSendCharClick(TObject *Sender)
{
m_SendBuf=EdtSend->Text;
BytesToWrite=EdtSend->Text.Length();
SendData(m_hComm,m_SendBuf.c_str(),BytesToWrite,&BytesWritten);
if (BytesWritten>0)
SerialPort->Memo->Lines->Add("已发送数据"+IntToStr(BytesWritten)+"字节");
else MessageDlg("发送字符不能为0!", mtError, TMsgDlgButtons() << mbOK, 0);
}
//---------------------------------------------------------------------------
bool SendData(HANDLE h_Comm,char *Buffer,unsigned long length,unsigned long *LengthWrited)
{
if(!h_Comm) return false;
if(!WriteFile(h_Comm, //调用成功返回非零,失败返回零
Buffer, //输出缓冲区
length, //准备发送的字符长度
LengthWrited, //实际发出的字符数
lpOverlappedWrite)) //重叠结构)
{
if(GetLastError()== ERROR_IO_PENDING)
{
DWORD RESULT;
do
{
RESULT=WaitForSingleObject(lpOverlappedWrite->hEvent,2000);
}while(RESULT!=WAIT_OBJECT_0);
GetOverlappedResult(m_hComm,lpOverlappedWrite,LengthWrited,false);
return true;
}
return false;
}
return true;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnExitClick(TObject *Sender)
{
if(!BtnClose->Enabled) Close();
else MessageDlg("退出前请关闭串口!", mtWarning, TMsgDlgButtons() << mbOK, 0);
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnBrowseClick(TObject *Sender)
{
// FILEFLAG fFileFlag;
bOpen=OpenDialog->Execute();
FileName=OpenDialog->FileName;
EdtFile->Text=FileName;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnSendFileClick(TObject *Sender)
{
FILEFLAG fFileFlag;
lBytesWrited=0;
lBytesRead=0;
if(bOpen)
{
int index=FileName.LastDelimiter("\\");
strcpy(fFileFlag.name,&FileName[index+1]); //保存文件名
iFileHandle = FileOpen(FileName, fmOpenRead);
if(iFileHandle==-1)
{
MessageDlg("打开文件出错!", mtError, TMsgDlgButtons() << mbOK, 0);
return;
}
iFileLength = FileSeek(iFileHandle,0,2); //取得文件长度(文件指针指向文件尾)
fFileFlag.length=iFileLength;
FileSeek(iFileHandle,0,0); //文件指针指向文件头
if(iFileLength<0)
{
MessageDlg("打开文件出错!", mtError, TMsgDlgButtons() << mbOK, 0);
FileClose(iFileHandle);
return;
}
strcpy(fFileFlag.flag,"FileFlag");
char *fileflag=(char*)&fFileFlag;
unsigned long fileflaglength=sizeof(FILEFLAG);
SendData(m_hComm,fileflag,fileflaglength,&fileflaglength); //发送文件握手信号
DWORD waitevent=WaitForSingleObject(hReceiveReady,20000);
if(waitevent==WAIT_TIMEOUT) //超时,对方没有响应
{
MessageDlg("对方没有响应!", mtInformation, TMsgDlgButtons() << mbOK, 0);
FileClose(iFileHandle);
return;
} // if(waitevent==WAIT_TIMEOUT)
else if(waitevent!=WAIT_OBJECT_0 ) //其他错误
{
MessageDlg("发送出错!", mtInformation, TMsgDlgButtons() << mbOK, 0);
FileClose(iFileHandle);
return;
} // else if(waitevent!=WAIT_OBJECT_0 )
else //接收方准备好,发送文件
{
// tcsReadyLock->Acquire();
bool bReady=true;
// tcsReadyLock->Release();
ResetEvent(hReceiveReady);
while(bReady&&lBytesWrited<iFileLength)
{
lBytesRead=FileRead(iFileHandle,FileBuf,1024);
SendData(m_hComm,FileBuf,lBytesRead,&send);
lBytesWrited=lBytesWrited+send;
//PbSend->Position=100*lBytesWrited/iFileLength;
}
//MessageDlg("发送完毕!", mtInformation, TMsgDlgButtons() << mbOK, 0);
lBytesWrited=0;
FileClose(iFileHandle);
//tcsReadyLock->Acquire();
bReady=false;
//tcsReadyLock->Release();
}
} //if(bOpen)
//PbSend->Position=0;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnCancelSendClick(TObject *Sender)
{
FILEFLAG FileFlag;
unsigned long SignalLength;
bReady=false;
SendData(m_hComm,"CancelS",7,&SignalLength);
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnCancelReceClick(TObject *Sender)
{
FILEFLAG FileFlag;
unsigned long SignalLength;
SendData(m_hComm,"CancelR",7,&SignalLength);
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::FormCreate(TObject *Sender)
{
Shape1->Brush->Color=clGreen;
}
//---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -