Delphi 10 で ApdComPort を使う (2019/02/10)

※ 2019/02/10 ApdDataPacket1.EndCond : ecStringにチェックを追記。IntToBin, IntToBunRev を変更。
※ 2019/02/06 三菱 FX3S との通信サンプルを追加
※ 2017/05/18 TApdDataPacket、TApdSLController、TApdStatusLight コンポーネント、ログファイルのスクリーンショットを追加
※ 2017/05/21 日本語マニュアルがありました。TurboPower Async Professional リファレンス・ガイド 第2章

これまでは CPortLIB を使っていたのですが、GetIt からインストールできる ApdComPort を使ってみました。
ウェルカムページ で、「GetIt でアドオンを取得」 をクリックすると、GetIt パッケージマネージャ が開きます。



インストールすると、ツールパレットに APRO カテゴリが追加されます。
TApdComPort は、その中にあります。



データの受信は、ApdComPort1TriggerAvail(CP: TObject; Count: Word); イベントを使います。

終端文字が ETX、CRLF のように固定の場合は、TApdDataPacket コンポーネントを追加し、
ComPort プロパティを ApdComPort にします。
終端文字が CRLF の場合は、EndString を #13#10 (^M^J) に、StartCond を scAnyData に設定。
ApdDataPacket1.EndCond プロパティの ecString にチェックを付けておくと、(2019/02/10追加)
ApdDataPacket1StringPacket(Sender: TObject; Data: AnsiString); イベントで文字列として取得されます。

通信状態のランプは、TApdStatusLight コンポーネントを必要数追加、TApdSLController コンポーネントを1個追加し、
ApdSLController に ApdStatusLigh を登録。ApdSLController の ComPort プロパティに ApdComPort を設定します。
ApdSLController1.Monitoring := True; にすると、動くようになります。

COM ポート番号が有効であるかを確認するには、uses 節に、AdSelCom を追加し、IsPortAvailable() を使います。
ex: for i := 1 to 32 do if IsPortAvailable(i) then ComboBox1.Items.Add ( 'COM ' + IntToStr (i));

単体で、ログファイルの作成、追加ができます。
ASCII 表記

HEX 表記


// GetIt からアドオンを取得
// AsyncPro for VCL 1.3

var buf : string;

// 送信
procedure TForm2.Button1Click(Sender: TObject);
begin
  ApdComPort1.ComNumber := 5; // COM5
  ApdComPort1.Baud := 2400;
  ApdComPort1.StopBits := 1;
  ApdComPort1.DataBits := 8;
  ApdComPort1.Parity := TParity.pNone;
  try
    ApdComPort1.Open := True;
    buf := '';
    // 送信
    ApdComPort1.Output := 'ABCDEFGHIJKLMNOPQRS';
    ApdComPort1.PutString('1234678901324567890');
  except
    ShowMessage('ERROR');
  end;
end;

// 受信
//----------------------------------------------------------
// GetChar
//----------------------------------------------------------
procedure TForm2.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
  i: Word;
begin
  for i := 1 to Count do
    buf := buf + string(ApdComPort1.GetChar);
  Edit1.Text := buf;
end;

//----------------------------------------------------------
// Byte
//----------------------------------------------------------
procedure TForm2.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
  i: Word;
  B: array [0..1024] of Byte;
begin
  ApdComPort1.GetBlock(B, Count);
  for i := 0 to Count -1 do
    buf := buf + Char(B[i], 2);
  Edit1.Text := buf;
end;

//----------------------------------------------------------
// TBytes
//----------------------------------------------------------
procedure TForm2.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
var
  B: TBytes;
begin
  SetLength(B, Count);
  ZeroMemory(B, Count);
  ApdComPort1.GetBlock(B[0], Count);
  buf := buf + TEncoding.ANSI.GetString(B);
  Edit1.Text := buf;
end;

・2019/02/06 FX3S との通信を追加

unit TX3SRS232ComTestUnit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,AdSelCom, Vcl.StdCtrls, OoMisc, AdPort,
  Vcl.ComCtrls;

type
  TForm4 = class(TForm)
    ApdComPort1: TApdComPort;
    ComboBox1: TComboBox;
    UpDown1: TUpDown;
    Edit1: TEdit;
    Edit2: TEdit;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure ApdComPort1TriggerAvail(CP: TObject; Count: Word);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    rcvBuf : string;
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm}

function IntToBin(x : Integer; bits : integer) : String;
var
  i, k : integer;
begin
  result := '';
  k := x;
  for i := 0 to bits -1 do begin
    result := IntToStr(k and 1) + result;
    k := k shr 1;
  end;
end;

function IntToBinRev(x : Integer; bits : integer) : String;
var
  i, k : Integer;
begin
  result := '';
  k := x;
  for i := 0 to bits - 1 do begin
    result := result + IntToStr(k and 1);
    k := k shr 1;
  end;
end;

procedure TForm4.ApdComPort1TriggerAvail(CP: TObject; Count: Word);
// 文字列受信
var
  i: Word;
begin
  for i := 1 to Count do
    rcvBuf := rcvBuf + string(ApdComPort1.GetChar);
  Edit2.Text := rcvBuf;
end;

procedure TForm4.Button1Click(Sender: TObject);
// COM ポートオープン
var
  s : string;
begin
  with ApdComPort1 do begin
    if not Open then begin
      s := '';
      with ComboBox1 do begin
        if ItemIndex >= 0 then begin
          s := Items[ItemIndex].Substring(4);
        end;
      end;
      if s <> '' then begin
        with ApdComPort1 do begin
          ComNumber := s.ToInteger;
          Baud := 19200;
          StopBits := 1;
          DataBits := 8;
          Parity := TParity.pNone;
          try
            Open := True;
          except
            ShowMessage('ERROR');
          end;
        end;
      end;
    end;
  end;
end;

procedure TForm4.Button2Click(Sender: TObject);
// WAV-5F2 255CH 再生テスト用
// Y0~Y4 = D0 ~ D4、Y5 = STB に使用
const
  STX = #$02; // テキスト開始
  ETX = #$03; // テキスト終了
  EOT = #$04; // テキスト終結
  ENQ = #$05; // 問合せ
  ACK = #$06; // 肯定応答
  CR  = #$0D; // キャリッジリターン
  LF  = #$0A; // 改行
  CL  = #$0C; // クリア
  NAK = #$15; // 否定応答
var
  s, cmd, head, term : string;
begin
  // 左から若い順の2進文字列に
  s := IntToBinRev(UpDown1.Position, 8).Substring(0, 5);
 with ApdComPort1 do begin
    if Open then begin
      try
        rcvBuf := '';
        head := ENQ +'00FFBW0';
        term := CR + LF;
        cmd := 'Y0000'; // 5桁で指示:Y0000から
        cmd := cmd + '06';    // 6個書き込み
        cmd := cmd + s + '0';
        PutString(head + cmd + term);
        // STB (Y5) ON
        PutString(head + 'Y0005011' + term);
        Sleep(50);
        // STB (Y5) OFF
        PutString(head + 'Y0005010' + term);

        cmd := 'Y0000'; // 5桁で指示:Y0000から
        cmd := cmd + '06';    // 6個書き込み
        cmd := cmd + '000000';
        PutString(head + cmd + term);
      except

      end;
    end;
  end;
end;

procedure TForm4.FormCreate(Sender: TObject);
// 使用可能な COM ポートを列挙
var
  i : integer;
begin
  Edit2.Text := '';
  with ComboBox1 do begin
    for i := 0 to 32 do begin
      if IsPortAvailable(i) then
        Items.Add('COM ' + i.ToString);
    end;
    if Items.Count > 0 then
      ItemIndex := 0;
  end;
end;

end.