?? 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;
return true;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnOpenClick(TObject *Sender)
{
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);
// 設置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.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); // 保存到DCB結構使設置值生效
ReadThread=new RecThread(true);//打開線程
ReadThread->Resume();//在錯誤處理程序結束后,恢復原有的運行
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::BtnCloseClick(TObject *Sender)
{
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)+"字節 ("+Date()+" "+Time()+")");
SerialPort->Memo->Lines->Add("---------------------------------------------");
}
else
{
MessageDlg("沒有發送字符!", mtWarning, TMsgDlgButtons() << mbOK, 0);
SerialPort->EdtSend->Focused();
}
}
//---------------------------------------------------------------------------
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)
{//打開文件
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 //接收方準備好,發送文件
{
bool bReady=true;
ResetEvent(hReceiveReady);
while(bReady&&lBytesWrited<iFileLength)
{
lBytesRead=FileRead(iFileHandle,FileBuf,1024);
SendData(m_hComm,FileBuf,lBytesRead,&send);
lBytesWrited=lBytesWrited+send;
ProgressBar->Position=100*lBytesWrited/iFileLength;
}
MessageDlg("發送完畢!", mtInformation, TMsgDlgButtons() << mbOK, 0);
lBytesWrited=0;
FileClose(iFileHandle);
// bReady=false;
}
} //if(bOpen)
ProgressBar->Position=0;
}
//---------------------------------------------------------------------------
void __fastcall TSerialPort::btnClearClick(TObject *Sender)
{
Memo->Clear();
}
//---------------------------------------------------------------------------
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -