Files
CommunicationTester/serialportframeunit.pas
T

314 lines
8.0 KiB
ObjectPascal

unit SerialPortFrameUnit;
{$mode ObjFPC}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls,
ComCtrls, Spin, SpinEx, Synaser, SerialManager, Types;
type
{ TMainForm }
{ SerialPortFrame }
SerialPortFrame = class(TFrame)
baudrateComboBox: TComboBox;
TimerCheckBox: TCheckBox;
closeButton: TButton;
MSLabel: TLabel;
RecvGroupBox: TGroupBox;
SendEncodingComboBox: TComboBox;
RecvEncodingComboBox: TComboBox;
RecvEncodingLabel: TLabel;
SerialSendGroupBox: TGroupBox;
SendEncodingLabel: TLabel;
SerialGroupBox: TGroupBox;
RecvMemo: TMemo;
openButton: TButton;
databitComboBox: TComboBox;
databitLabel: TLabel;
SendMemo: TMemo;
sendButton: TButton;
ClearButton: TButton;
SerialSendTimer: TTimer;
TimerSpinEdit: TSpinEdit;
stopbitComboBox: TComboBox;
baudrateLabel: TLabel;
paritybitComboBox: TComboBox;
serialComboBox: TComboBox;
stopbitLabel: TLabel;
paritybitLabel: TLabel;
serialLabel: TLabel;
SerialListTimer: TTimer;
procedure SerialParamComboBoxEditingDone(Sender: TObject);
procedure ClearButtonClick(Sender: TObject);
procedure closeButtonClick(Sender: TObject);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure OpenButtonClick(Sender: TObject);
procedure sendButtonClick(Sender: TObject);
procedure SerialListTimerTimer(Sender: TObject);
procedure SerialSendTimerTimer(Sender: TObject);
procedure TimerCheckBoxChange(Sender: TObject);
procedure TimerSpinEditChange(Sender: TObject);
private
serialThr: SerialThread;
procedure OnSerialClose();
procedure processReceivedSerialData(Data: string);
procedure showWarnBox(message: string);
function ConfigureSerial(serial: SerialThread): boolean;
procedure OnSerialConnected();
procedure OnSerialConnectedFailed();
public
constructor Create(TheOwner: TComponent); override;
end;
var
MainForm: SerialPortFrame;
implementation
{$R *.lfm}
{ SerialPortFrame }
procedure SerialPortFrame.ClearButtonClick(Sender: TObject);
begin
RecvMemo.Clear();
end;
procedure SerialPortFrame.SerialParamComboBoxEditingDone(Sender: TObject);
begin
if (serialThr <> nil) and serialThr.isConnected() then
ConfigureSerial(serialThr);
end;
procedure SerialPortFrame.closeButtonClick(Sender: TObject);
begin
serialThr.Close();
end;
procedure SerialPortFrame.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
serialThr.Close();
end;
procedure SerialPortFrame.OpenButtonClick(Sender: TObject);
begin
openButton.Enabled := False; // 防止多次点击
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;
serialThr.Start;
end;
procedure SerialPortFrame.sendButtonClick(Sender: TObject);
var
hexArr: array of char;
binBufferLen: integer;
begin
if (serialThr <> nil) and serialThr.isConnected() and (SendMemo.GetTextLen > 0) then
begin
if SendEncodingComboBox.ItemIndex = 0 then
serialThr.SendString(SendMemo.Text)
else
begin
SetLength(hexArr, SendMemo.GetTextLen div 2);
binBufferLen := HexToBin(PChar(SendMemo.Text), PChar(hexArr),
SendMemo.GetTextLen div 2);
serialThr.SendBuffer(PChar(hexArr), binBufferLen);
end;
end;
end;
procedure SerialPortFrame.SerialListTimerTimer(Sender: TObject);
var
serialList: string;
begin
// 刷新串口列表
serialList := GetSerialPortNames;
if (serialList.IsEmpty) then
begin
// 只在当前Combox非空时Clear,防止闪烁
if not (serialComboBox.Items.CommaText.IsEmpty) then
begin
serialComboBox.Items.Clear;
end;
openButton.Enabled := False;
end
else
begin
if not (serialComboBox.Items.CommaText.Equals(serialList)) then
begin
serialComboBox.Items.CommaText := serialList;
serialComboBox.ItemIndex := 0;
end;
openButton.Enabled := True;
end;
// 设置按钮状态
if (serialThr <> nil) and serialThr.isConnected() then
begin
openButton.Enabled := False;
sendButton.Enabled := True;
closeButton.Enabled := True;
end
else
begin
sendButton.Enabled := False;
closeButton.Enabled := False;
end;
end;
procedure SerialPortFrame.SerialSendTimerTimer(Sender: TObject);
begin
sendButtonClick(Sender);
end;
procedure SerialPortFrame.TimerCheckBoxChange(Sender: TObject);
begin
if (Sender is TCheckBox) then
begin
if (Sender as TCheckBox).Checked then
begin
SerialSendTimer.Enabled := True;
end
else
begin
SerialSendTimer.Enabled := False;
end;
end;
end;
procedure SerialPortFrame.TimerSpinEditChange(Sender: TObject);
begin
SerialSendTimer.Interval := TimerSpinEdit.Value;
end;
procedure SerialPortFrame.OnSerialClose;
begin
closeButton.Enabled := False;
openButton.Enabled := True;
serialComboBox.Enabled := True;
end;
procedure SerialPortFrame.processReceivedSerialData(Data: string);
var
hexArr: array of char;
hexResult: string;
i: integer;
begin
RecvMemo.SelStart := Length(RecvMemo.Text);
if RecvEncodingComboBox.ItemIndex = 0 then
begin
{ TODO -omycai : 将各类换行符换成LineBreak }
RecvMemo.SelText := Data;
end
else
begin
hexResult := '';
if RecvMemo.GetTextLen() > 0 then
hexResult += ':';
SetLength(hexArr, Data.Length * 2);
BinToHex(Pointer(Data), PChar(hexArr), Data.Length);
for i := 0 to High(hexArr) div 2 do
begin
hexResult := hexResult + hexArr[i * 2] + hexArr[i * 2 + 1];
if i * 2 + 1 < High(hexArr) - 1 then
hexResult := hexResult + ':';
end;
RecvMemo.SelText := ansistring(hexResult);
end;
end;
procedure SerialPortFrame.showWarnBox(message: string);
var
box: TForm;
begin
box := CreateMessageDialog(message, mtWarning, [mbClose]);
box.Position := poOwnerFormCenter;
box.ShowModal;
end;
function SerialPortFrame.ConfigureSerial(serial: SerialThread): boolean;
var
baudRate: integer;
databit: integer;
paritybit: char;
stopbit: integer;
begin
if TryStrToInt(baudrateComboBox.Text, baudRate) then
baudrate := StrToInt(baudrateComboBox.Text)
else
begin
showWarnBox('波特率参数错误');
Exit(False);
end;
databit := StrToInt(databitComboBox.Text);
case (paritybitComboBox.Text) of
'无': paritybit := 'N';
'奇校验': paritybit := 'O';
'偶校验': paritybit := 'E';
else
paritybit := 'N';
end;
case (stopbitComboBox.Text) of
'1': stopbit := SB1;
'1.5': stopbit := SB1andHalf;
'2': stopbit := SB2;
//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);
// 接收到\n即换行
RecvMemo.Lines.TextLineBreakStyle := tlbsLF;
end;
end.