下面是我的程序,请各位帮忙看看,谢谢!
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls,comctrls, ExtCtrls, Buttons;
const
WM_COMMNOTIFY=WM_USER+365;
type
TRecvThread=Class(TThread)
public
procedure Execute;override;
end;
TMainForm = class(TForm)
Panel1: TPanel;
Label4: TLabel;
edtSend: TEdit;
SendBt: TButton;
CloseBt: TButton;
CancleBt: TButton;
stbSend: TStatusBar;
mmoSend: TMemo;
OpenBt: TButton;
GroupBox1: TGroupBox;
CmbSendComm: TComboBox;
Label2: TLabel;
Label3: TLabel;
cmbSendBaudRate: TComboBox;
Label5: TLabel;
cmbSendStopBits: TComboBox;
Label6: TLabel;
cmbSendParity: TComboBox;
RecvBt: TButton;
CheckBox1: TCheckBox;
procedure FormCreate(Sender: TObject);
procedure OpenBtClick(Sender: TObject);
procedure SendBtClick(Sender: TObject);
procedure RecvBtClick(Sender: TObject);
private
procedure CommInitialize(comm:string;BaudRate:integer;StopBits:byte;Parity:byte);
procedure WMCOMMNOTIFY(var Message:TMessage);Message WM_COMMNOTIFY; //数据接收信息处理函数
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
Post_Event:Thandle; //创建事件同步对象的句柄
hSend:THandle; //发送串口的句柄
Read_os:Toverlapped; //重叠结构的变量
Receive:boolean; //开关变量,代表是否接受
implementation
{$R *.dfm}
PROCEdure tmainform.CommInitialize(comm:string;BaudRate:integer;StopBits:byte;Parity:byte);
var
dcb:TDCB;
Error:boolean;
CommTimeOut:TCOMMTIMEOUTS;
begin
hSend:=createfile(Pchar(comm),GENERIC_WRITE or GENERIC_READ ,0,NIL,OPEN_EXISTING,
FILE_FLAG_OVERLAPPED ,0); //打开串口 OR GENERIC_READ or FILE_ATTRIBUTE_NORMAL
IF hSend=INVALID_HANDLE_VALUE then
raise Exception.Create('打开'+comm+'端口错误!');
commtimeout.ReadIntervalTimeout:=MAXDWORD;
COMmtimeout.ReadTotalTimeoutMultiplier:=0;
commtimeout.ReadTotalTimeoutConstant:=1000;
commtimeout.WriteTotalTimeoutMultiplier:=2;
commtimeout.WriteTotalTimeoutConstant:=1000;
setcommtimeouts(hSend,commtimeout); //设置超时
SetupComm(hSend,4096,4096); //设置输入和输出缓冲区大小
//设置串口的波特率、字符位数、奇偶校验、停止位
GetCommState(hSend,dcb);
dcb.BaudRate:=BaudRate;
dcb.ByteSize:=8;
dcb.StopBits:=StopBits;
dcb.Parity:=Parity;
Error:=SetCommState(hSend,dcb);
if (not Error) then
raise Exception.Create('设置'+comm+'错误!');
Error:=SetCommMask(hSend,EV_RXCHAR);
IF not Error then
raise exception.Create('SetCommMask错误!');
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
cmbsendcomm.ItemIndex:=0;
cmbsendbaudrate.ItemIndex:=0;
cmbsendstopbits.ItemIndex:=1;
cmbsendparity.ItemIndex:=0;
end;
procedure TMainForm.OpenBtClick(Sender: TObject);
var
recvThread:TRecvThread;
begin
CommInitialize('com2',9600,ONESTOPBIT,NOPARITY);
STBsend.Panels[0].Text:='串口已打开...';
end;
procedure TMainForm.SendBtClick(Sender: TObject);
var
dwNumberOfBytesWritten,dwNumberOfBytesToWrite,ErrorFlag,dwWhereToStartWriting
WORD;
pDataToWrite
Char;
write_os:Toverlapped;
begin
dwWhereToStartWriting:=0;
dwNumberOfBytesWritten:=0;
//设置将要向串口写的数据长度
dwNumberOfBytesToWrite:=edtSend.GetTextLen;
if (dwNumberOfBytesToWrite=0) then
raise exception.Create('发送缓冲区为空!');
//将mmoSend中的文本传到pDateToWrite缓冲区
pDataToWrite:=pchar(trim(edtSend.Text));
fillchar(write_os,sizeof(write_os),0);
//位重叠创建事件
write_os.hEvent:=createevent(nil,true,true,nil);
//设置直到最后一个字符被发送
setCommMask(hSend,EV_TxEMPTY);
Repeat
//发送数据
if not WriteFile(hSend,pdataToWrite[dwWhereToStartWriting],dwNumberOfBytesToWrite,dwNumberOfBytesWritten,
@write_os) then
begin
errorFlag:=GetLastError;
if ErrorFlag<>0 then
begin
if ErrorFlag=ERROR_IO_PENDING THEN
begin
WaitForSingleObject(Write_os.hEvent,INFINITE);
GetOverlappedResult(hSend,write_os,dwNumberOfBytesWritten,False);
end
else raise exception.Create('发送数据失败!');
end;
end;
//减去已发生的数据长度
dec(dwNumberOfBytesToWrite,dwNumberOfBytesWritten);
//记录已发送的数据长度
inc(dwWhereToStartWriting,dwNumberOfBytesWritten);
until(dwNumberOfBytesToWrite<=0);
mmoSend.Lines.Add('已发送:'+inttostr(dwWhereToStartWriting)+'个字节的数据');
end;
procedure TMainForm.RecvBtClick(Sender: TObject);
var
recvThread:TRecvThread;
begin
FillChar(Read_os,Sizeof(Read_os),0);
Read_os.Offset:=0;
Read_os.OffsetHigh:=0;
//创建Ovrelapped事件
Read_os.hEvent:=createEvent(nil,true,false,nil);
if read_os.hEvent=null then
begin
closehandle(hSend);
raise exception.Create('Create Event Error');
end;
Post_event:=createevent(nil,true,true,nil);
if post_event=null then
begin
closehandle(hSend);
closehandle(read_os.hEvent);
raise exception.Create('Create Event Error');
end;
//建立通信监视线程
recvThread:=TRecvThread.Create(false);
//发送DTR信号
EscapeCommFunction(hSend,SETDTR);
stbSend.Panels[1].Text:='正在接收数据...';
stbSend.Refresh;
end;
procedure TrecvThread.Execute; //接收串口述句的线程执行体
var
dwEvtMask,dwTranser
WORD;
wait,Ok:boolean;
Os:Toverlapped;
begin
FreeOnTerminate:=true;
Receive:=true;
FillChar(os,Sizeof(os),0);
os.hEvent:=createevent(nil,true,false,nil);
if os.hEvent=null then
begin
MessageBox(0,'os.Event Create Error!','Notice',MB_OK);
exit;
end;
if (not setcommMask(hSend,EV_RXCHAR)) THEN
BEGIN
messagebox(0,'setcommMask Error','Notice',MB_OK);
END;
while(receive) do
begin
dwEvtMask:=0;
//等待事件发生
if not waitcommevent(hSend,dwEvtMask,@os) then
begin
if ERROR_IO_PENDING=GetLastError then
GetOverLappedResult(hSend,Os,dwTranser,True);
end;
if ((dwEvtMask and EV_RXCHAR)=EV_RXCHAR) THEN
begin
waitforsingleobject(post_event,INFINITE);
ResetEvent(post_event);
ok:=postmessage(mainform.Handle,WM_COMMNOTIFY,hSend,0);
if (not ok) then
begin
messagebox(0,'PostMessage Error','Notice',MB_OK);
exit;
end;
end;
end;
closehandle(os.hEvent);
end;
procedure tmainform.WMCOMMNOTIFY(var message:tmessage);
var
CommState:ComStat;
dwNumberOfBytesRead
WORD;
ErrorFlag
WORD;
InputBuffer:array[0..100] of char;
begin
if not clearcommerror(hSend,ErrorFlag,@Commstate) then
begin
messagebox(0,'clearcommerror','Notice',MB_OK);
purgecomm(hSend,Purge_Rxabort or Purge_Rxclear);
exit;
end;
if (commstate.cbInQue>0) then
begin
fillchar(inputbuffer,commstate.cbInQue,#0);
if not readfile(hSend,InputBuffer,Commstate.cbInQue,dwNumberOfBytesRead,@read_os) then
begin
ErrorFlag:=GetLastError;
if (ErrorFlag<>0) and (ErrorFlag<>ERROR_IO_PENDING) THEN
begin
receive:=false;
raise exception.Create('读串口数据出错!');
end
else begin
waitforsingleobject(hSend,INFINITE);
GETOVERlappedresult(hSend,read_os,dwnumberofbytesread,false);
end;
end;
if dwnumberofbytesread>0 then
begin
read_os.Offset:=read_os.Offset+dwNumberofbytesread;
inputbuffer[dwnumberofbytesread]:=#0;;
mmosend.Lines.Add('接收到:'+inttostr(dwnumberofbytesread)+'个字节的数据');
mmosend.Lines.Add(strpas(inputbuffer));
end;
end;
setevent(post_event);
end;
end.