⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit3.pas

📁 基于MODBUSTCP协议的客户端通讯程序
💻 PAS
字号:
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Buttons, ActnList, StdCtrls, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient, ExtCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    EditSend: TRichEdit;
    EditRecv: TRichEdit;
    EditIP: TLabeledEdit;
    EditAddr: TLabeledEdit;
    EditQty: TLabeledEdit;
    Splitter1: TSplitter;
    IdTCPClient1: TIdTCPClient;
    BitBtn2: TBitBtn;
    ActionList1: TActionList;
    ActConnect: TAction;
    SpeedButton1: TSpeedButton;
    ActReadCoils: TAction;
    ActReadDiscrete: TAction;
    ActReadInputRegister: TAction;
    ActReadHoldRegister: TAction;
    ActWriteCoils: TAction;
    ActWriteHoldRegister: TAction;
    BitBtn1: TBitBtn;
    BitBtn3: TBitBtn;
    BitBtn4: TBitBtn;
    BitBtn6: TBitBtn;
    EditDeviceID: TLabeledEdit;
    BitBtn5: TBitBtn;
    procedure ActConnectExecute(Sender: TObject);
    procedure ActReadCoilsExecute(Sender: TObject);
    procedure ActReadDiscreteExecute(Sender: TObject);
    procedure ActReadHoldRegisterExecute(Sender: TObject);
    procedure ActReadInputRegisterExecute(Sender: TObject);
    procedure ActWriteHoldRegisterExecute(Sender: TObject);
    procedure ActWriteCoilsExecute(Sender: TObject);
  private
    { Private declarations }
    FID: word;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses uModBusClient;

{$R *.dfm}

procedure TForm1.ActConnectExecute(Sender: TObject);
begin
  IdTCPClient1.Host := EditiP.Text;
  if IdTCPClient1.Connected then
    IdTCPClient1.Disconnect
  else
    IdTCPClient1.Connect();
  ActConnect.Checked := IdTCPClient1.Connected;
end;

procedure TForm1.ActReadCoilsExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I, P: integer;
  B:    byte;
  FDeviceID: byte;
begin
  FillChar(Head, Sizeof(Head), 0);
  FDeviceID := StrToInt(EditDeviceID.Text);
  with Req do
  begin
    fUnitID := FDeviceID;
    fFunctionCode := mbReadCoils;
    Addr    := StrToInt(EditAddr.Text)-1;
    fReadStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    fReadQuantity := Swap(Qty);
  end;
  Head.fRecLength     := Swap(6);
  Head.fTransactionID := Swap(FID);
  Inc(FID);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], 6);
  IdTCPClient1.WriteBuffer(S[1], 12);
  SetLength(H, 24);
  BinToHex(PChar(S), PChar(H), 12);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);
    if (Rsp.fFunctionCode and $80) = 0 then
    begin
      L := 0;
      P := 0;
      while L < Qty do
      begin
        B := Rsp.fReadData[P];
        for I := 0 to 7 do
        begin
          H := Format('0%5.5d : %d', [Addr + L+1, B and $01]);
          EditRecv.Lines.Add(H);
          B := B shr 1;
          Inc(L);
          if L = Qty then
            break;
        end;
        Inc(P);
      end;
    end;
  end;
end;

procedure TForm1.ActReadDiscreteExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I, P: integer;
  B:    byte;
  FDeviceID: byte;
begin
  FillChar(Head, Sizeof(Head), 0);
  FDeviceID := StrToInt(EditDeviceID.Text);
  with Req do
  begin
    fUnitID := FDeviceID;
    fFunctionCode := mbReadDiscreteInputs;
    Addr    := StrToInt(EditAddr.Text)-1;
    fReadStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    fReadQuantity := Swap(Qty);
  end;
  Head.fRecLength     := Swap(6);
  Head.fTransactionID := Swap(FID);
  Inc(FID);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], 6);
  IdTCPClient1.WriteBuffer(S[1], 12);
  SetLength(H, 24);
  BinToHex(PChar(S), PChar(H), 12);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);

    if (Rsp.fFunctionCode and $80) = 0 then
    begin
      L := 0;
      P := 0;
      while L < Qty do
      begin
        B := Rsp.fReadData[P];
        for I := 0 to 7 do
        begin
          H := Format('1%5.5d : %d', [Addr + L+1, B and $01]);
          EditRecv.Lines.Add(H);
          B := B shr 1;
          Inc(L);
          if L = Qty then
            break;
        end;
        Inc(P);
      end;
    end;
  end;
end;

procedure TForm1.ActReadHoldRegisterExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I:    integer;
  W:    word;
  FDeviceID: byte;
begin
  FillChar(Head, Sizeof(Head), 0);
  FDeviceID := StrToInt(EditDeviceID.Text);
  with Req do
  begin
    fUnitID := FDeviceID;
    fFunctionCode := mbReadHoldingRegisters;
    Addr    := StrToInt(EditAddr.Text)-1;
    fReadStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    fReadQuantity := Swap(Qty);
  end;
  Head.fRecLength     := Swap(6);
  Head.fTransactionID := Swap(FID);
  Inc(FID);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], 6);
  IdTCPClient1.WriteBuffer(S[1], 12);
  SetLength(H, 24);
  BinToHex(PChar(S), PChar(H), 12);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);

    if (Rsp.fFunctionCode and $80) = 0 then
      for I := 0 to Rsp.fCount div 2 - 1 do
      begin
        Move(Rsp.fReadData[I * 2], W, 2);
        H := Format('4%5.5d : %d', [Addr + I+1, Swap(W)]);
        EditRecv.Lines.Add(H);
      end;
  end;
end;

procedure TForm1.ActReadInputRegisterExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I:    integer;
  W:    word;
  FDeviceID: byte;
begin
  FillChar(Head, Sizeof(Head), 0);
  FDeviceID := StrToInt(EditDeviceID.Text);
  with Req do
  begin
    fUnitID := FDeviceID;
    fFunctionCode := mbReadInputRegisters;
    Addr    := StrToInt(EditAddr.Text)-1;
    fReadStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    fReadQuantity := Swap(Qty);
  end;
  Head.fRecLength     := Swap(6);
  Head.fTransactionID := Swap(FID);
  Inc(FID);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], 6);
  IdTCPClient1.WriteBuffer(S[1], 12);
  SetLength(H, 24);
  BinToHex(PChar(S), PChar(H), 12);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);

    if (Rsp.fFunctionCode and $80) = 0 then
      for I := 0 to Rsp.fCount div 2 - 1 do
      begin
        Move(Rsp.fReadData[I * 2], W, 2);
        H := Format('3%5.5d : %d', [Addr + I+1, Swap(W)]);
        EditRecv.Lines.Add(H);
      end;
  end;
end;

procedure TForm1.ActWriteHoldRegisterExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I:    integer;
  W:    word;
begin
  FillChar(Head, Sizeof(Head), 0);
  with Req do
  begin
    fUnitID := 0;
    fFunctionCode := mbWriteMultipleRegisters;
    Addr    := StrToInt(EditAddr.Text)-1;
    fHoldStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    fRegisterQuantity := Swap(Qty);
    fCount2 := Qty * 2;
    for I := 0 to Qty - 1 do
      fOutRegisterValues[I] := Random(65536);
  end;
  L := Req.fCount2 + 7;
  Head.fRecLength := Swap(L);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], L);
  IdTCPClient1.WriteBuffer(S[1], L + 6);
  SetLength(H, (L + 6) * 2);
  BinToHex(PChar(S), PChar(H), L + 6);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);
  end;
end;

procedure TForm1.ActWriteCoilsExecute(Sender: TObject);
var
  Head: Tmb_tcp_header;
  Req:  Tmb_req_pdu;
  Rsp:  Tmb_rsp_pdu;
  Addr, Qty: word;
  S, H: string;
  L:    word;
  I:    integer;
  W:    word;
begin
  FillChar(Head, Sizeof(Head), 0);
  with Req do
  begin
    fUnitID := 0;
    fFunctionCode := mbWriteMultipleCoils;
    Addr    := StrToInt(EditAddr.Text)-1;
    fCoilsStartAddr := Swap(Addr);
    Qty     := StrToInt(EditQty.Text);
    L := Qty div 8;
    if Qty mod 8 >0 then
      L := L+1;
    fCoilQuantity := Swap(Qty);
    fCount1 := L;
    for I := 0 to L-1 do
      fOutCoilValues[I] := Random(256);
    if Qty mod 8 > 0 then  
    fOutCoilValues[L-1] := fOutCoilValues[L-1] shr ( 8 - Qty mod 8);
  end;
  L := Req.fCount1 + 7;
  Head.fRecLength := Swap(L);

  SetLength(S, 256);
  Move(Head, S[1], 6);
  Move(Req, S[7], L);
  IdTCPClient1.WriteBuffer(S[1], L + 6);
  SetLength(H, (L + 6) * 2);
  BinToHex(PChar(S), PChar(H), L + 6);
  EditSend.Lines.Add(H);

  S := IdTCPClient1.CurrentReadBuffer;
  if S > '' then
  begin
    Move(S[1], Head, 6);
    L := Swap(Head.fRecLength);
    Move(S[7], Rsp, L);
    SetLength(H, (6 + L) * 2);
    BinToHex(PChar(S), PChar(H), 6 + L);
    EditRecv.Lines.Add(H);
  end;
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -