2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题

遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题

时间:2020-11-09 06:54:59

相关推荐

遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题

遵循Modbus协议通过Usb(Ch375)通信的上位机传输问题 Delphi / Windows SDK/API

/DelphiNetwork/html/delphi_1129164355231.html

Usb芯片:Ch375

协议:Modbus

上位机开发软件:delphi

传输格式(RTU):

帧定义:

头|命令|长度|数据(高) ----数据(低)|CRC

C0C1C2 S0S1S2 T10T11 T20T21 P0P1

01 02 0C 000000 000000 0000 0000 0000 XX

第一次做这种软件,还没有在下位机上测试,先贴出部分源码,请大家帮忙改正。

还有对于从下位机取出来的数据(已从16进制转换成10进制)有几个疑问:

1。是不是就代表了真实的值,是否还需要再转换;

2。如何处理浮点型数据。

下面是部分源码:

//读数据

function ReadData(iIndex:Integer;var oBuffer:PChar;var ioLength:Integer):Boolean;

stdcall; external DllFile name 'CH375ReadData';

function TPublicFun.GetData:Integer;

var

Buff_HAdd : Byte;//帧:头地址

Buff_Cmd : Byte;//帧:命令

Buff_Len : Byte;//帧:长度

Buff_DatLC : array[1..3] of Byte;//帧:LC数据

Buff_DatLS : array[1..3] of Byte;//帧:LS数据

Buff_DatT1 : array[1..2] of Byte;//帧:T1数据

Buff_DatT2 : array[1..2] of Byte;//帧:T2数据

Buff_DatP : array[1..2] of Byte;//帧:P数据

Buff_Send : array of Byte;//用于存放各个域合成的总的串

I,BuffLen,TempLen : Integer;//传输的实际数据长度

TempStr,CSort: string;//用于存放string类型的测试传输帧

Rtl : Boolean;

PChar_Send : PChar;

begin

Result:= -1;

//测试用,假设Usb设备已打开

Usb_Opened := True;

if Usb_Opened then

begin

//设置头地址

Buff_HAdd := HeadCode;

//设置命令

Buff_Cmd := StatusCode;

//设置长度

Buff_Len := strtohex1(IntToHex(17,2),2);

TempLen:= 17;

//初始化LC,LS

for I:=1 to 3 do

begin

Buff_DatLC[I] := $00;

Buff_DatLS[I] := $00;

end;

//初始化T,P

for I:=1 to 2 do

begin

Buff_DatT1[I] := $00;

Buff_DatT2[I] := $00;

Buff_DatP[I] := $00;

end;

SetLength(Buff_Send,TempLen);

//设置总串

Buff_Send[1] := Buff_HAdd;

Buff_Send[2] := Buff_Cmd;

Buff_Send[3] := Buff_Len;

Buff_Send[4] := Buff_DatLC[1];

Buff_Send[5] := Buff_DatLC[2];

Buff_Send[6] := Buff_DatLC[3];

Buff_Send[7] := Buff_DatLS[1];

Buff_Send[8] := Buff_DatLS[2];

Buff_Send[9] := Buff_DatLS[3];

Buff_Send[10] := Buff_DatT1[1];

Buff_Send[11] := Buff_DatT1[2];

Buff_Send[12] := Buff_DatT2[1];

Buff_Send[13] := Buff_DatT2[2];

Buff_Send[14] := Buff_DatP[1];

Buff_Send[15] := Buff_DatP[2];

//CRC校验:即校验域前的几个域的集合

I := CRC(Buff_Send[1],15);

Buff_Send[16] := I div 256;

Buff_Send[17] := I mod 256;

//获得string类型的测试传输帧

TempStr := '';

for I:= 1 to TempLen do

TempStr := TempStr + inttohex(Buff_Send[i],2);

BuffLen:= TempLen * 2;

PChar_Send := PChar(TempStr);

//发送命令

//测试屏蔽

Rtl := ReadData(Usb_Index,PChar_Send,BuffLen);

if Rtl then

begin

//读取返回串

for I:= 0 to TempLen-1 do

Buff_rev[I+1] := strtohex1(copy(PChar_Send,I*2+1,2),2);

//CRC校验

if CRC_Check=1 then

begin

TempStr := '';

//校验成功,读出数据

//TempStr := TempStr + inttohex(Buff_rev[i+4],2);

for I:= 0 to 2 do

begin

Buff_DatLC[I+1] := Buff_rev[I+4];

Buff_DatLS[I+1] := Buff_rev[I+7];

end;

for I:= 0 to 1 do

begin

Buff_DatT1[I+1] := Buff_rev[I+10];

Buff_DatT2[I+1] := Buff_rev[I+12];

Buff_DatP[I+1] := Buff_rev[I+14];

end;

//数据处理

Result := 1;

//初始化接受串

for I:=1 to Maxlen do Buff_rev[I]:=0;

end;

end

else

begin

ShowMessage('数据传输出错,无法得到正确的值!','提示');

end;

end

else

begin

ShowMessage('没有发现可用的Usb设备!','提示');

end;

end;

对于传输帧,我现在有点疑惑:

我传向下位机请求和从下位机得到数据都是以上面我和下位机开发人员定义的格式传输并不象下面Modbus中的例子,不知可行否?

因为我定义的帧中要获取5个参数的值:LC由C0C1C2构成(高-低)、LS由S0S1S2构成、T1由T10T11构成、T2由T20T21构成、P由P0P1构成。

下面是Modbus RTU中一个例子:

主机请求:

地址 功能码 第一个寄存器的高位地址 第一个寄存器的低位地址 寄存器的数量的高位 寄存器的数量的低位 错误校验

01 03 00 38 00 01 XX

从机应答:

地址 功能码 字节数 数据高字节 数据低字节 错误校验

01 03 2 4124 XX

数据:16进制=4124,转换成十进制=16676

//发送命令

//测试屏蔽

Rtl := ReadData(Usb_Index,PChar_Send,BuffLen);

ReadData应该是读吧?

你的例子:

请求:

0103 00380001XX

01=>hdr

03=>cmd

00=>len

38=>crc

即无数据,后面的数据就错了

按协议,好像是这样写的

PRTUData = ^TRTUData;

TRTUData = packed record

hdr: Byte;

cmd: Byte;

len: Byte;

data: array [0..0] of Byte;

crc: Byte;

end;

data取决于len的长度

var

P: PByte;

rtuLen: Byte;

rtu: PRTUData;

begin

rtuLen := SizeOf(TRTUData) + DataLen - 1;

rtu := allocMem(rtuLen);

rtu.hdr := $01;

rtu.cmd := $02;

rtu.len := DataLen;

P := @rtu.data[0];

for I := 0 to DataLen - 1 do

beg

P^ := $XX;

inc(P);

end;

P^ := crc(xxx); // P ==> crc

WriteData(..., rtu, rtuLen)

end;

先谢谢ERR0RC0DE()

我知道了,你是先发送命令,WriteData(..., rtu, rtuLen),然后在通过ReadData(Usb_Index,PChar_Send,BuffLen);读取数据,是吧?

看不懂,^_^

顶下!

有兴趣的朋友欢迎继续讨论阿

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。