improve structure of serial thread

This commit is contained in:
2023-11-19 22:33:18 +08:00
parent b375beed81
commit b274cbc6f3
6 changed files with 164 additions and 68 deletions
+12 -1
View File
@@ -62,7 +62,7 @@
<Version Value="11"/> <Version Value="11"/>
<PathDelim Value="\"/> <PathDelim Value="\"/>
<Target> <Target>
<Filename Value="CommunicationTester"/> <Filename Value="CommunicationTester-release"/>
</Target> </Target>
<SearchPaths> <SearchPaths>
<IncludeFiles Value="$(ProjOutDir)"/> <IncludeFiles Value="$(ProjOutDir)"/>
@@ -98,6 +98,9 @@
<FormatVersion Value="2"/> <FormatVersion Value="2"/>
</RunParams> </RunParams>
<RequiredPackages> <RequiredPackages>
<Item>
<PackageName Value="RunTimeTypeInfoControls"/>
</Item>
<Item> <Item>
<PackageName Value="LazControls"/> <PackageName Value="LazControls"/>
</Item> </Item>
@@ -133,6 +136,14 @@
<ResourceBaseClass Value="Frame"/> <ResourceBaseClass Value="Frame"/>
<UnitName Value="SerialPortFrameUnit"/> <UnitName Value="SerialPortFrameUnit"/>
</Unit> </Unit>
<Unit>
<Filename Value="tcpframeunit.pas"/>
<IsPartOfProject Value="True"/>
<ComponentName Value="Frame1"/>
<HasResources Value="True"/>
<ResourceBaseClass Value="Frame"/>
<UnitName Value="TCPFrameUnit"/>
</Unit>
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
+3 -3
View File
@@ -9,15 +9,15 @@ uses
athreads, athreads,
{$ENDIF} {$ENDIF}
Interfaces, // this includes the LCL widgetset Interfaces, // this includes the LCL widgetset
Forms, lazcontrols, Forms, lazcontrols, runtimetypeinfocontrols,
mainunit, mainunit,
SerialManager, SerialPortFrameUnit { you can add units after this }; SerialManager, SerialPortFrameUnit,
TCPFrameUnit { you can add units after this };
{$R *.res} {$R *.res}
begin begin
RequireDerivedFormResource := True; RequireDerivedFormResource := True;
Application.Title:='CommunicationTester';
Application.Scaled:=True; Application.Scaled:=True;
Application.Initialize; Application.Initialize;
Application.CreateForm(TMainForm, MainForm); Application.CreateForm(TMainForm, MainForm);
+2 -2
View File
@@ -22,7 +22,7 @@ object MainForm: TMainForm
Height = 580 Height = 580
Top = 10 Top = 10
Width = 940 Width = 940
ActivePage = SerialTabSheet ActivePage = TabSheet2
Anchors = [akTop, akLeft, akRight, akBottom] Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Left = 10 BorderSpacing.Left = 10
BorderSpacing.Top = 10 BorderSpacing.Top = 10
@@ -34,7 +34,7 @@ object MainForm: TMainForm
Font.Pitch = fpVariable Font.Pitch = fpVariable
Font.Quality = fqDraft Font.Quality = fqDraft
ParentFont = False ParentFont = False
TabIndex = 0 TabIndex = 1
TabOrder = 0 TabOrder = 0
object SerialTabSheet: TTabSheet object SerialTabSheet: TTabSheet
Caption = '串口' Caption = '串口'
+2 -3
View File
@@ -6,7 +6,8 @@ interface
uses uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
ComCtrls, Spin, SpinEx, Synaser, SerialManager, Types, SerialPortFrameUnit; ComCtrls, Spin, MaskEdit, SpinEx, Synaser, SerialManager, Types,
SerialPortFrameUnit, TCPFrameUnit;
type type
@@ -49,6 +50,4 @@ implementation
end. end.
+100 -5
View File
@@ -5,10 +5,13 @@ unit SerialManager;
interface interface
uses uses
Classes, Synaser; Classes, SysUtils, Synaser;
type type
TRecvDataEvent = procedure(Data: string) of object; TRecvDataEvent = procedure(Data: string) of object;
TConnectedEvent = procedure of object;
TConnectedFailedEvent = procedure of object;
TClosedEvent = procedure of object;
{ SerialThread } { SerialThread }
@@ -16,30 +19,98 @@ type
protected protected
procedure Execute; override; procedure Execute; override;
procedure ProcessRecvEvent; procedure ProcessRecvEvent;
procedure ProcessConnectedEvent;
procedure ProcessConnectedFailedEvent;
procedure ProcessOnCloseEvent;
private private
MserialPort: TBlockSerial; MserialPort: TBlockSerial;
MSerialName: string;
FOnRecvData: TRecvDataEvent; FOnRecvData: TRecvDataEvent;
FOnConnected: TConnectedEvent;
FOnClosed: TClosedEvent;
FOnConnectedFailed: TConnectedFailedEvent;
currentRecvData: string; currentRecvData: string;
public public
constructor Create(CreateSuspended: boolean; serialPort: TBlockSerial); constructor Create(CreateSuspended: boolean; serialName: string);
property OnRecvData: TRecvDataEvent read FOnRecvData write FOnRecvData; destructor Destroy; override;
procedure Close();
procedure SendString(Data: ansistring);
function SendBuffer(buffer: pointer; length: integer): integer;
procedure ConfigureSerial(baud, bits: integer; parity: char;
stop: integer; softflow, hardflow: boolean);
property OnRecvData: TRecvDataEvent read FOnRecvData write FOnRecvData;
property OnConnected: TConnectedEvent read FOnConnected write FOnConnected;
property OnConnectedFailed: TConnectedFailedEvent
read FOnConnectedFailed write FOnConnectedFailed;
property OnClosed: TClosedEvent read FOnClosed write FOnClosed;
function isConnected(): boolean;
end; end;
implementation implementation
constructor SerialThread.Create(CreateSuspended: boolean; serialPort: TBlockSerial); constructor SerialThread.Create(CreateSuspended: boolean; serialName: string);
begin begin
inherited Create(CreateSuspended); inherited Create(CreateSuspended);
FreeOnTerminate := True; FreeOnTerminate := True;
Self.MserialPort := serialPort; self.MSerialName := serialName;
Self.MserialPort := TBlockSerial.Create;
end; end;
destructor SerialThread.Destroy;
begin
inherited Destroy;
FreeAndNil(MserialPort);
end;
procedure SerialThread.Close;
begin
MserialPort.Purge();
MserialPort.CloseSocket();
Terminate();
FreeAndNil(MserialPort);
ProcessOnCloseEvent();
end;
procedure SerialThread.SendString(Data: ansistring);
begin
MserialPort.SendString(Data);
end;
function SerialThread.SendBuffer(buffer: pointer; length: integer): integer;
begin
Result := MserialPort.SendBuffer(buffer, length);
end;
procedure SerialThread.ConfigureSerial(baud, bits: integer; parity: char;
stop: integer; softflow, hardflow: boolean);
begin
MserialPort.Config(baud, bits, parity, stop,
softflow, hardflow);
end;
function SerialThread.isConnected(): boolean;
begin
Result := ((MserialPort <> nil) and MserialPort.InstanceActive);
end;
procedure SerialThread.Execute; procedure SerialThread.Execute;
begin begin
MserialPort.Connect(MSerialName);
if isConnected() then
begin
Synchronize(@ProcessConnectedEvent);
end
else
begin
Synchronize(@ProcessConnectedFailedEvent);
Exit;
end;
while not (Terminated) do while not (Terminated) do
begin begin
currentRecvData := MserialPort.RecvPacket(-1); currentRecvData := MserialPort.RecvPacket(-1);
@@ -55,4 +126,28 @@ begin
end; end;
end; end;
procedure SerialThread.ProcessConnectedEvent;
begin
if Assigned(FOnConnected) then
begin
FOnConnected();
end;
end;
procedure SerialThread.ProcessConnectedFailedEvent;
begin
if Assigned(FOnConnectedFailed) then
begin
FOnConnectedFailed();
end;
end;
procedure SerialThread.ProcessOnCloseEvent;
begin
if Assigned(FOnClosed) then
begin
FOnClosed();
end;
end;
end. end.
+45 -54
View File
@@ -12,6 +12,8 @@ type
{ TMainForm } { TMainForm }
{ SerialPortFrame }
SerialPortFrame = class(TFrame) SerialPortFrame = class(TFrame)
baudrateComboBox: TComboBox; baudrateComboBox: TComboBox;
TimerCheckBox: TCheckBox; TimerCheckBox: TCheckBox;
@@ -55,12 +57,12 @@ type
procedure TimerSpinEditChange(Sender: TObject); procedure TimerSpinEditChange(Sender: TObject);
private private
serialThr: SerialThread; serialThr: SerialThread;
serialPort: TBlockSerial; procedure OnSerialClose();
function isSerialConnected(): boolean;
procedure CloseSerial();
procedure processReceivedSerialData(Data: string); procedure processReceivedSerialData(Data: string);
procedure showWarnBox(message: string); procedure showWarnBox(message: string);
function ConfigureSerial(serial: TBlockSerial): boolean; function ConfigureSerial(serial: SerialThread): boolean;
procedure OnSerialConnected();
procedure OnSerialConnectedFailed();
public public
constructor Create(TheOwner: TComponent); override; constructor Create(TheOwner: TComponent); override;
end; end;
@@ -85,23 +87,20 @@ end;
procedure SerialPortFrame.SerialParamComboBoxEditingDone(Sender: TObject); procedure SerialPortFrame.SerialParamComboBoxEditingDone(Sender: TObject);
begin begin
if isSerialConnected() then if (serialThr <> nil) and serialThr.isConnected() then
ConfigureSerial(serialPort); ConfigureSerial(serialThr);
end; end;
procedure SerialPortFrame.closeButtonClick(Sender: TObject); procedure SerialPortFrame.closeButtonClick(Sender: TObject);
begin begin
CloseSerial(); serialThr.Close();
openButton.Enabled := True;
serialComboBox.Enabled := True;
end; end;
procedure SerialPortFrame.FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure SerialPortFrame.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin begin
CloseSerial(); serialThr.Close();
FreeAndNil(serialPort);
end; end;
@@ -109,32 +108,20 @@ end;
procedure SerialPortFrame.OpenButtonClick(Sender: TObject); procedure SerialPortFrame.OpenButtonClick(Sender: TObject);
begin begin
openButton.Enabled := False; // 防止多次点击 openButton.Enabled := False; // 防止多次点击
serialPort := TBlockSerial.Create();
serialPort.Connect(serialComboBox.Text); serialThr := SerialThread.Create(True, serialComboBox.Text);
if not ConfigureSerial(serialPort) then serialThr.OnConnected := @OnSerialConnected;
serialThr.OnConnectedFailed := @OnSerialConnectedFailed;
serialThr.OnRecvData := @processReceivedSerialData;
serialThr.OnClosed := @OnSerialClose;
if not ConfigureSerial(serialThr) then
begin begin
FreeAndNil(serialThr);
Exit; Exit;
end; end;
if isSerialConnected() then serialThr.Start;
begin
//serialPort.Config(baudrate, databit, paritybit, stopbit,
// False, False);
serialThr := SerialThread.Create(True, serialPort);
serialThr.OnRecvData := @processReceivedSerialData;
serialThr.Start;
serialComboBox.Enabled := False;
openButton.Enabled := False;
closeButton.Enabled := True;
end
else
begin
showWarnBox('串口打开失败');
openButton.Enabled := True;
closeButton.Enabled := False;
CloseSerial();
end;
end; end;
procedure SerialPortFrame.sendButtonClick(Sender: TObject); procedure SerialPortFrame.sendButtonClick(Sender: TObject);
@@ -142,16 +129,16 @@ var
hexArr: array of char; hexArr: array of char;
binBufferLen: integer; binBufferLen: integer;
begin begin
if isSerialConnected and (SendMemo.GetTextLen > 0) then if (serialThr <> nil) and serialThr.isConnected() and (SendMemo.GetTextLen > 0) then
begin begin
if SendEncodingComboBox.ItemIndex = 0 then if SendEncodingComboBox.ItemIndex = 0 then
serialPort.SendString(SendMemo.Text) serialThr.SendString(SendMemo.Text)
else else
begin begin
SetLength(hexArr, SendMemo.GetTextLen div 2); SetLength(hexArr, SendMemo.GetTextLen div 2);
binBufferLen := HexToBin(PChar(SendMemo.Text), PChar(hexArr), binBufferLen := HexToBin(PChar(SendMemo.Text), PChar(hexArr),
SendMemo.GetTextLen div 2); SendMemo.GetTextLen div 2);
serialPort.SendBuffer(PChar(hexArr), binBufferLen); serialThr.SendBuffer(PChar(hexArr), binBufferLen);
end; end;
end; end;
end; end;
@@ -181,7 +168,7 @@ begin
openButton.Enabled := True; openButton.Enabled := True;
end; end;
// 设置按钮状态 // 设置按钮状态
if isSerialConnected() then if (serialThr <> nil) and serialThr.isConnected() then
begin begin
openButton.Enabled := False; openButton.Enabled := False;
sendButton.Enabled := True; sendButton.Enabled := True;
@@ -220,21 +207,11 @@ begin
end; end;
function SerialPortFrame.isSerialConnected: boolean; procedure SerialPortFrame.OnSerialClose;
begin begin
Result := ((serialPort <> nil) and serialPort.InstanceActive); closeButton.Enabled := False;
end; openButton.Enabled := True;
serialComboBox.Enabled := True;
procedure SerialPortFrame.CloseSerial;
begin
if isSerialConnected() then
begin
closeButton.Enabled := False;
serialPort.Purge();
serialPort.CloseSocket();
serialThr.Terminate();
FreeAndNil(serialPort);
end;
end; end;
procedure SerialPortFrame.processReceivedSerialData(Data: string); procedure SerialPortFrame.processReceivedSerialData(Data: string);
@@ -275,7 +252,7 @@ begin
box.ShowModal; box.ShowModal;
end; end;
function SerialPortFrame.ConfigureSerial(serial: TBlockSerial): boolean; function SerialPortFrame.ConfigureSerial(serial: SerialThread): boolean;
var var
baudRate: integer; baudRate: integer;
databit: integer; databit: integer;
@@ -307,16 +284,30 @@ begin
//else //else
// stopbit := SB1; // stopbit := SB1;
end; end;
serialThr.ConfigureSerial(baudRate, databit, paritybit, stopbit, False, False);
Exit(True); Exit(True);
end; end;
procedure SerialPortFrame.OnSerialConnected;
begin
serialComboBox.Enabled := False;
openButton.Enabled := False;
closeButton.Enabled := True;
ConfigureSerial(serialThr);
end;
procedure SerialPortFrame.OnSerialConnectedFailed;
begin
showWarnBox('串口打开失败');
openButton.Enabled := True;
closeButton.Enabled := False;
end;
constructor SerialPortFrame.Create(TheOwner: TComponent); constructor SerialPortFrame.Create(TheOwner: TComponent);
begin begin
inherited Create(TheOwner); inherited Create(TheOwner);
serialPort := TBlockSerial.Create;
// 接收到\n即换行 // 接收到\n即换行
RecvMemo.Lines.TextLineBreakStyle := tlbsLF; RecvMemo.Lines.TextLineBreakStyle := tlbsLF;
end; end;
end. end.