大家好!我编了一个RS-232的串口通讯的小程序(用WIN API 实现的),可是现在要实现实时接受数据,也就是端口有数据就接收,而不需要任何操作,我想了好久也没有写出来,现在急需要实现,小的恳请各位能帮忙解决(用WIN API 而不用控件),谢谢!
恳请各位能帮忙解决
我的原文件如下:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, MyComm;type
TCheckThread = class( TThread )
protected
procedure Execute; override;
public
bCheckThread: boolean;
end; TForm1 = class(TForm)
Memo1: TMemo;
Label1: TLabel;
ClearBtn: TButton;
WriteBtn: TButton;
CloseBtn: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ClearBtnClick(Sender: TObject);
procedure WriteBtnClick(Sender: TObject);
procedure CloseBtnClick(Sender: TObject);
private
{ Private declarations }
TestComm: TComm; //Add "uses MyComm" to use TComm
CheckThread: TCheckThread;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
begin
TestComm := TComm.Create(Self);
//9600-8-N-1, COMM2
if not TestComm.InitComm('COM2', 9600, 8, ONESTOPBIT, 0) then
begin
MessageBox(Handle, 'Error in initialing COMM2!', 'COMM error', MB_OK or MB_ICONSTOP);
TestComm.FreeComm;
end; //init check comm thread
CheckThread := TCheckThread.Create(True); //suspended
CheckThread.bCheckThread := True;
CheckThread.Priority := tpLower;
CheckThread.Resume;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
if CheckThread <> nil then
begin
//Signal the event to close the worker threads.
CheckThread.bCheckThread := False;
//Wait 1 seconds for it to exit. Shouldn't happen.
if (WaitForSingleObject(CheckThread.Handle, 1000) = WAIT_TIMEOUT) then
CheckThread.Terminate;
CheckThread.Free;
CheckThread := nil;
end; if TestComm<>Nil then TestComm.Destroy;
end;procedure TForm1.CloseBtnClick(Sender: TObject);
begin
Close;
end;procedure TForm1.ClearBtnClick(Sender: TObject);
begin
Memo1.Lines.Clear;
end;procedure TCheckThread.Execute;
var
TempByte: Byte;
begin
while bCheckThread do
begin
if (Form1.TestComm<>Nil) and (Form1.TestComm.BytesInInQue>=1) then
begin
Form1.TestComm.ReadData(@TempByte, 1);
Form1.Memo1.Lines.Add(Char(TempByte)+' '+IntToHex(TempByte, 2));
end;
end;
end;procedure TForm1.WriteBtnClick(Sender: TObject);
var
s: string;
TestBytes: array[1..10] of byte;
i: integer;
begin
s := 'ATZ'+#13#10;
TestComm.WriteData(PChar(s), Length(s)); for i:=1 to 10 do TestBytes[i] := i;
TestComm.WriteData(@TestBytes, 10);
end;end.
这是MyComm单元:
unit MyComm;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;const
//
// Modem Event Constant
//
ME_CTS = 1;
ME_DSR = 2;
ME_RING = 4;
ME_RLSD = 8;type
TComm = class( TComponent )
private
hCommFile: THandle;
public
bOpened: boolean;
CommName: string;
INQUESIZE, OUTQUESIZE: integer;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override; function InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
procedure FreeComm; function WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
function ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
function BytesInInQue: DWORD;
function BytesInOutQue: DWORD;
procedure ClearComm;
end;const
// This is the message posted to the WriteThread
// When we have something to write.
PWM_COMMWRITE = WM_USER+1;implementationconstructor TComm.Create(AOwner: TComponent);
begin
inherited Create( AOwner ); hCommFile := 0;
bOpened := False; // Default size of the Input Buffer used by this code.
INQUESIZE := 40960;
OUTQUESIZE := 8192;
end;destructor TComm.Destroy;
begin
FreeComm;
inherited Destroy;
end;function TComm.InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
var
dcb: Tdcb;
begin
//Are we already doing comm?
if hCommFile<>0 then
begin
InitComm := False;
exit;
end; hCommFile := CreateFile( PChar(ThisCommName),
GENERIC_READ or GENERIC_WRITE,
0, {not shared}
nil, {no security ??}
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0); if hCommFile=INVALID_HANDLE_VALUE then
begin
hCommFile := 0;
InitComm := False;
exit;
end; //Is this a valid comm handle?
if GetFileType(hCommFile)<>FILE_TYPE_CHAR then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; //Querying then setting the comm port configurations.
GetCommState(hCommFile, dcb); dcb.BaudRate := BaudRate;
dcb.ByteSize := DataByte; //number of bits/byte, 4-8
dcb.Parity := ParityByte; //0-4=no,odd,even,,space
dcb.StopBits := StopByte; /
if not SetCommState(hCommFile, dcb) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; if not SetupComm(hCommFile, INQUESIZE, OUTQUESIZE) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; //purge any information in the buffer
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR); InitComm := True;
bOpened := True;
CommName := ThisCommName;
end;procedure TComm.FreeComm;
begin
if hCommFile=0 then exit; //Now close the comm port handle.
PurgeComm(hCommFile, PURGE_RXABORT + PURGE_RXCLEAR
+ PURGE_TXABORT + PURGE_TXCLEAR);
CloseHandle(hCommFile);
hCommFile := 0;
bOpened := False;
end;function TComm.WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
var
nSent: DWORD;
begin
Result := WriteFile(hCommFile, pDataToWrite^, dwSizeofDataToWrite,
nSent, Nil);
end;
function TComm.ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
var
nRead: DWORD;
begin
Result := ReadFile(hCommFile, pBuffer^, BufferSize, nRead, Nil);
end;
function TComm.BytesInInQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbInQue;
end;function TComm.BytesInOutQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbOutQue;
end;procedure TComm.ClearComm;
begin
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR);
end;
end.
恳请各位能帮忙解决
我的原文件如下:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, MyComm;type
TCheckThread = class( TThread )
protected
procedure Execute; override;
public
bCheckThread: boolean;
end; TForm1 = class(TForm)
Memo1: TMemo;
Label1: TLabel;
ClearBtn: TButton;
WriteBtn: TButton;
CloseBtn: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ClearBtnClick(Sender: TObject);
procedure WriteBtnClick(Sender: TObject);
procedure CloseBtnClick(Sender: TObject);
private
{ Private declarations }
TestComm: TComm; //Add "uses MyComm" to use TComm
CheckThread: TCheckThread;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}procedure TForm1.FormCreate(Sender: TObject);
begin
TestComm := TComm.Create(Self);
//9600-8-N-1, COMM2
if not TestComm.InitComm('COM2', 9600, 8, ONESTOPBIT, 0) then
begin
MessageBox(Handle, 'Error in initialing COMM2!', 'COMM error', MB_OK or MB_ICONSTOP);
TestComm.FreeComm;
end; //init check comm thread
CheckThread := TCheckThread.Create(True); //suspended
CheckThread.bCheckThread := True;
CheckThread.Priority := tpLower;
CheckThread.Resume;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
if CheckThread <> nil then
begin
//Signal the event to close the worker threads.
CheckThread.bCheckThread := False;
//Wait 1 seconds for it to exit. Shouldn't happen.
if (WaitForSingleObject(CheckThread.Handle, 1000) = WAIT_TIMEOUT) then
CheckThread.Terminate;
CheckThread.Free;
CheckThread := nil;
end; if TestComm<>Nil then TestComm.Destroy;
end;procedure TForm1.CloseBtnClick(Sender: TObject);
begin
Close;
end;procedure TForm1.ClearBtnClick(Sender: TObject);
begin
Memo1.Lines.Clear;
end;procedure TCheckThread.Execute;
var
TempByte: Byte;
begin
while bCheckThread do
begin
if (Form1.TestComm<>Nil) and (Form1.TestComm.BytesInInQue>=1) then
begin
Form1.TestComm.ReadData(@TempByte, 1);
Form1.Memo1.Lines.Add(Char(TempByte)+' '+IntToHex(TempByte, 2));
end;
end;
end;procedure TForm1.WriteBtnClick(Sender: TObject);
var
s: string;
TestBytes: array[1..10] of byte;
i: integer;
begin
s := 'ATZ'+#13#10;
TestComm.WriteData(PChar(s), Length(s)); for i:=1 to 10 do TestBytes[i] := i;
TestComm.WriteData(@TestBytes, 10);
end;end.
这是MyComm单元:
unit MyComm;interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;const
//
// Modem Event Constant
//
ME_CTS = 1;
ME_DSR = 2;
ME_RING = 4;
ME_RLSD = 8;type
TComm = class( TComponent )
private
hCommFile: THandle;
public
bOpened: boolean;
CommName: string;
INQUESIZE, OUTQUESIZE: integer;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override; function InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
procedure FreeComm; function WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
function ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
function BytesInInQue: DWORD;
function BytesInOutQue: DWORD;
procedure ClearComm;
end;const
// This is the message posted to the WriteThread
// When we have something to write.
PWM_COMMWRITE = WM_USER+1;implementationconstructor TComm.Create(AOwner: TComponent);
begin
inherited Create( AOwner ); hCommFile := 0;
bOpened := False; // Default size of the Input Buffer used by this code.
INQUESIZE := 40960;
OUTQUESIZE := 8192;
end;destructor TComm.Destroy;
begin
FreeComm;
inherited Destroy;
end;function TComm.InitComm(ThisCommName: string; BaudRate,DataByte,StopByte,ParityByte: integer): Boolean;
var
dcb: Tdcb;
begin
//Are we already doing comm?
if hCommFile<>0 then
begin
InitComm := False;
exit;
end; hCommFile := CreateFile( PChar(ThisCommName),
GENERIC_READ or GENERIC_WRITE,
0, {not shared}
nil, {no security ??}
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
0); if hCommFile=INVALID_HANDLE_VALUE then
begin
hCommFile := 0;
InitComm := False;
exit;
end; //Is this a valid comm handle?
if GetFileType(hCommFile)<>FILE_TYPE_CHAR then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; //Querying then setting the comm port configurations.
GetCommState(hCommFile, dcb); dcb.BaudRate := BaudRate;
dcb.ByteSize := DataByte; //number of bits/byte, 4-8
dcb.Parity := ParityByte; //0-4=no,odd,even,,space
dcb.StopBits := StopByte; /
if not SetCommState(hCommFile, dcb) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; if not SetupComm(hCommFile, INQUESIZE, OUTQUESIZE) then
begin
CloseHandle(hCommFile);
hCommFile := 0;
InitComm := False;
exit;
end; //purge any information in the buffer
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR); InitComm := True;
bOpened := True;
CommName := ThisCommName;
end;procedure TComm.FreeComm;
begin
if hCommFile=0 then exit; //Now close the comm port handle.
PurgeComm(hCommFile, PURGE_RXABORT + PURGE_RXCLEAR
+ PURGE_TXABORT + PURGE_TXCLEAR);
CloseHandle(hCommFile);
hCommFile := 0;
bOpened := False;
end;function TComm.WriteData(pDataToWrite: PChar; dwSizeofDataToWrite: DWORD): Boolean;
var
nSent: DWORD;
begin
Result := WriteFile(hCommFile, pDataToWrite^, dwSizeofDataToWrite,
nSent, Nil);
end;
function TComm.ReadData(pBuffer: PChar; BufferSize: DWORD): boolean;
var
nRead: DWORD;
begin
Result := ReadFile(hCommFile, pBuffer^, BufferSize, nRead, Nil);
end;
function TComm.BytesInInQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbInQue;
end;function TComm.BytesInOutQue: DWORD;
var
stat: TCOMSTAT;
errs: DWORD;
begin
ClearCommError(hCommFile, errs, @stat);
Result := stat.cbOutQue;
end;procedure TComm.ClearComm;
begin
PurgeComm(hCommFile, PURGE_TXABORT or PURGE_RXABORT or
PURGE_TXCLEAR or PURGE_RXCLEAR);
end;
end.
此贴已发过一次,并且给了某人100分,有倒分嫌疑。