|
|
2008-11-14 09:50
| 只看楼主
树型|
收藏|
小
中
大
1#
Delphi编写的Modbus通讯类
最近有很多仪表和现场设备要组成Modbus RTU网络,自己使用Delphi编写了Modbus的通讯类,可直接使用,大家多多支持啊。 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.
|