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