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

📄 modbus.pas

📁 delphi串口modbus源码
💻 PAS
字号:
unit Modbus;
{
  通讯协议 : Modbus;
}

interface

uses SysUtils;

type
 TDevModbus=class
  private
  //********************************
   Addr:integer;
   Port:integer;
   Baud:integer;
   Mode:integer;//comm para
   
   PortOpenOk:boolean;
   DebugM:boolean;

   id_RwDelayTime:integer;
   id_DataLength:integer;

   //***************************

   Procedure GetCRC(Data:array of byte;Nums:integer;var CRCH,CRCL:byte);
   Function CheckCrc(Data:array of byte;Nums:integer):Boolean;

   procedure ClearInBuff;
   procedure ClearOutBuff;
   procedure ClearInOutbuff;

   Function SendCmd(cmd:array of byte;len:integer):integer;//send cmd to pw
   Function Recv(var rev:array of byte;len:integer):integer;

  public
   Constructor create;
   destructor Destroy;override;
   Function PortOpen:integer;
   Function PortClose:integer;
   Function Read(RegAddr,RegNum:integer;var revdata:array of byte):integer;
   Function ReadByte(RegAddr:integer;High:boolean):integer;
   function ReadWord(RegAddr:integer):integer;
   Function Write(RegAddr:integer;writedata:Word):integer;
   Function WriteByte(RegAddr:integer;writedata:byte;High:boolean):integer;
   Function WriteMore(RegAddr:integer;data:array of byte;len:integer):integer;

   property PortOk:boolean read portOpenOk write PortOpenOk;

  published
    property DevAddr:integer read Addr write Addr;

    property ComPort:integer read Port write Port;// comm port
    property ComBaud:integer read Baud write Baud;//comm baud
    property ComMode:integer read Mode write Mode;//comm mode

    property DebugMode:boolean read debugM write debugM;//
    property RwDelayTime:integer read  id_RwDelayTime Write id_RwDelayTime;

end;

implementation

uses PComm;

{ TPowerMtModule }

procedure TDevModbus.GetCRC(Data:array of byte;Nums:integer;var CRCH, CRCL: byte);
var
  i,j:integer;
  CRC:integer;
begin
  CRC:=$FFFF;
  for i:=0 to Nums-1 do
  begin
    CRC:=CRC xor ord(Data[i]);
    for j:=0 to 7 do
    begin

      if (CRC mod 2=1) then
      begin
        CRC:= CRC div 2;
        CRC:=$A001 xor CRC
      end
      else
      begin
        CRC:= CRC div 2;
      end;
    end;
  end;
  CRCH := crc mod 256;
  CRCL := crc div 256;
end;

function TDevModbus.CheckCrc(Data: array of byte;
  Nums: integer): Boolean;
var i:integer;
    tmpdata:array of byte;
    CRCH,CRCL : byte;
begin
  setlength(tmpdata,Nums);
  for i:=0 to Nums-1 do
    tmpdata[i] := Data[i];
  GetCrc(tmpdata,Nums-2,CRCH,CRCL);
  if(CRCH=Data[Nums-2])and(CRCL=Data[Nums-1])then
    result := true
  else result := false;
end;

procedure TDevModbus.ClearInBuff;
begin
 if not PortOpenOk then exit;

   sio_flush(Port,0);

end;

procedure TDevModbus.ClearInOutbuff;
begin
 if not portOpenOk then exit;

  sio_flush(port,2);
end;

procedure TDevModbus.ClearOutBuff;
begin
 if not PortOpenOk then exit;

   sio_flush(Port,1);
end;

constructor TDevModbus.create;
begin
  PortOpenOk:=false;

  id_RwDelayTime:=3000;
  inherited;
end;

destructor TDevModbus.Destroy;
begin
  if portOpenOk then sio_close(Port);
  inherited;
end;

Function TDevModbus.PortClose:integer;
begin
  if portOpenOk then result:=sio_close(Port);
end;

function TDevModbus.PortOpen: integer;
var
  ret:integer;
begin
//--------------打开并设置通讯端口
   if DebugM then exit;

   if Port<1 then
   begin
     PortOpenok:=false;
     result:=-99;
     exit;
   end;

   if portOpenOk then
   begin
     result:=0;
     exit;
   end;

   PortOpenOk:=true;
   ret:= sio_open(Port);
   if ret<>SIO_OK then//打开端口出错
    begin
       if ret=sio_openfail then
       PortOpenOk:=false;

    end;

    result:=result+ret;

    ret := ret+sio_ioctl (Port,Baud,Mode);//设置端口
    if ret<>SIO_OK then
    begin
//      showmessage('SWRT端口通讯置错误: '+inttostr(ret));

      PortOpenOk:=false;
//      application.terminate;//终止程序

    end;
    portopen:=ret;

   if portOpenok then Result:=0;


end;

function TDevModbus.SendCmd(cmd: array of Byte;len:integer): integer;
begin
  if not portOpenOk then PortOpen;
  if not portOpenOk then exit;
  result:=sio_write(Port,@cmd,len);
end;

function TDevModbus.Recv(var rev: array of byte;len:integer): integer;
begin
  if not portOpenOk then PortOpen;
  if not portOpenOk then exit;
  result:=sio_read(Port,@rev,len);
end;

function TDevModbus.ReadWord(RegAddr:integer):integer;
var i,ret:integer;
    rev:array[0..1] of byte;
begin
  ret:=read(regaddr,1,rev);
  if(ret<0)then
  begin
    result:=-1;
    exit;
  end;

  result := rev[0]*256+rev[1];
end;

function TDevModbus.ReadByte(RegAddr:integer;High:boolean):integer;
var i,ret:integer;
    rev:array[0..1] of byte;
begin
  ret:=read(regaddr,1,rev);
  if(ret<0)then
  begin
    result:=-1;
    exit;
  end;
  
  if(High)then
    result := rev[0]
  else
    result := rev[1];
end;

function TDevModbus.Read(RegAddr,RegNum:integer; var revdata:array of byte):integer;
var cmd,rev:array of byte;
    i,ret,revlen:integer;
begin
  ClearInOutBuff;
  setlength(cmd,8);
  cmd[0]:=Addr;
  cmd[1]:=$03;
  cmd[2]:=RegAddr div 256;
  cmd[3]:=RegAddr mod 256;
  cmd[4]:=RegNum div 256;
  cmd[5]:=RegNum mod 256;

  getCRC(cmd,6,cmd[6],cmd[7]);

  ret:=SendCmd(cmd,length(cmd));

  sleep(200);

  revlen:=RegNum*2+5;
  setlength(rev,revlen);
  ret:=ret+Recv(rev,revlen);

  if(ret=revlen+8)then
    result := 0
  else
  begin
    result :=-1;
    exit;
  end;

  if(CheckCRC(rev,revlen))then
    result := 0
  else
  begin
    result := -1;
    exit;
  end;

  for i:=0 to RegNum*2-1 do
  begin
    revdata[i]:=rev[i+3];
  end;

end;

Function TDevModbus.Write(RegAddr:integer;writedata:word):integer;
var cmd,rev:array of byte;
    i,ret,revlen:integer;
begin
  ClearInOutBuff;
  setlength(cmd,8);
  cmd[0]:=Addr;
  cmd[1]:=$06;
  cmd[2]:=RegAddr div 256;
  cmd[3]:=RegAddr mod 256;
  cmd[4]:=writedata div 256;
  cmd[5]:=writedata mod 256;

  getCRC(cmd,6,cmd[6],cmd[7]);

  ret:=SendCmd(cmd,length(cmd));

  sleep(100);

  revlen:=8;
  setlength(rev,revlen);
  ret:=ret+Recv(rev,revlen);

  if(ret=revlen+8)then
    result := 0
  else
  begin
    result :=-1;
    exit;
  end;

  if(CheckCRC(rev,revlen))then
    result := 0
  else
    result := -1;
end;

Function TDevModbus.WriteByte(RegAddr:integer;writedata:byte;High:boolean):integer;
var cmd,rev:array of byte;
    i,ret,revlen:integer;
    bHigh,bLow:byte;
begin

  bHigh:=0;
  bLow:=0;

  //先读出整个寄存器中的数据
  setlength(rev,2);
  ret:=Read(RegAddr,1,rev);
  if(ret=0)then
  begin
    bHigh :=rev[0];
    bLow := rev[1];
  end;

  //然后写入相应的字节
  ClearInOutBuff;
  setlength(cmd,8);
  cmd[0]:=Addr;
  cmd[1]:=$06;
  cmd[2]:=RegAddr div 256;
  cmd[3]:=RegAddr mod 256;
  if(not High)then
  begin
    cmd[4]:=bHigh;
    cmd[5]:=writedata mod 256;
  end
  else
  begin
    cmd[4]:=writedata mod 256;
    cmd[5]:=bLow;
  end;

  getCRC(cmd,6,cmd[6],cmd[7]);

  ret:=SendCmd(cmd,length(cmd));

  sleep(100);

  revlen:=8;
  setlength(rev,revlen);
  ret:=ret+Recv(rev,revlen);

  if(ret=revlen+8)then
    result := 0
  else
  begin
    result :=-1;
    exit;
  end;

  if(CheckCRC(rev,revlen))then
    result := 0
  else
    result := -1;
end;

function TDevModbus.WriteMore(RegAddr: integer; data: array of byte;
  len: integer): integer;
var cmd,rev:array of byte;
    i,ret,revlen:integer;
begin
  ClearInOutBuff;
  setlength(cmd,len+8);
  cmd[0]:=Addr;
  cmd[1]:=$10;
  cmd[2]:=RegAddr div 256;
  cmd[3]:=RegAddr mod 256;

  for i:=0 to len-1 do
    cmd[i+4]:=data[i];

  getCRC(cmd,len+5,cmd[len+6],cmd[len+7]);

  ret:=SendCmd(cmd,length(cmd));

  sleep(100);

  revlen:=8;
  setlength(rev,revlen);
  ret:=ret+Recv(rev,revlen);

  if(ret=revlen+8+len)then
    result := 0
  else
  begin
    result :=-1;
    exit;
  end;

  if(CheckCRC(rev,revlen))then
    result := 0
  else
    result := -1;
end;

end.

⌨️ 快捷键说明

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