我从套接字中读取Delphi代码:
type
RegbusReq2=packed record
Funct:char;
Device:char;
Device1:char;
Starting:integer;
Quantity:smallint;
_CRC:Word;
stroka:char;
end;
type
crcReg=packed record
buf:array[0..2] of byte;
value:array[0..5] of byte;
end;
type
myRB=record
case byte of
0:(data:RegbusReq2);
1:(Buff:crcReg);
end;
type
outVal=packed record
cap:array[0..8] of byte;
val:array[0..3] of single;
end;
type
outValBuff=record
case byte of
0:(val:outVal);
1:(Buff:array [1..25] of byte);
end;
var
Form1: TForm1;
hCommFile:THandle;
typeCon:byte;
cs1: TClientSocket;
...
读取数据的计时器:
Procedure TForm1.Timer1Timer(Sender: TObject);
var
DataReq:myRB;
output:outValbuff;
Wr,Rd:Cardinal;
i:integer;
st:string;
begin
//çàïîëíåíèå çàïðîñà
DataReq.data.Funct:=chr(63); //êîìàíäà "?"
DataReq.data.Device:=chr(48); //íîìåð ïðèáîðà ñò
DataReq.data.Device1:=chr(49); //íîìåð ïðèáîðà ìëàäøèé
DataReq.data.Starting:=2088; //àäðåñ â äåñ ôîðì
DataReq.data.Quantity:=16; //ðàçìåð äàííûõ
DataReq.data._CRC:=CRC2(@DataReq.Buff.value,6); //ÊÑ
DataReq.data.stroka:=chr(13); //ïåðåâîä ñòðîêè
PurgeComm(hCommFile,PURGE_RXCLEAR or PURGE_TXCLEAR);
if typecon=1 then begin //COM-ïîðò
WriteFile(hCommFile,DataReq.data,SizeOf(DataReq.data),Wr,nil);
ReadFile(hCommFile,Output.buff,SizeOf(Output.Buff),Rd,nil);
end;
if typecon=2 then begin //ethernet
cs1.Active:=true;
cs1.Socket.SendBuf(DataReq.data,SizeOf(DataReq.data));
cs1.Socket.ReceiveBuf(output.buff,SizeOf(Output.Buff));
cs1.Active:=false;
end;
for i:=1 to 25 do
st:=st + '_' + inttostr(output.buff[i]);
memo1.Lines.Add(st);
edit1.Text:=FloatToStr(Round(output.val.val[0]
*exp(2*ln(10)))/(exp(2*ln(10))));
edit2.Text:=FloatToStr(Round(output.val.val[1]
*exp(2*ln(10)))/(exp(2*ln(10))));
edit3.Text:=FloatToStr(Round(output.val.val[2]
*exp(2*ln(10)))/(exp(2*ln(10))));
edit4.Text:=FloatToStr(Round(output.val.val[3]
*exp(2*ln(10)))/(exp(2*ln(10))));
end;
我关注C#代码:
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct RegBusRec
{
public char Funct;
public char Device;
public char Device1;
public int Starting;
public short Quantity;
public ushort _CRC;
public char Message;
}
...
private void timer1_Tick(object sender, EventArgs e)
{
byte[] CRCc = new byte[6];
byte[] tmp;
byte[] output = new byte[25];
RegBusRec req2 = new RegBusRec();
Crc16 crc16 = new Crc16();
req2.Funct = '?';
req2.Device = '0';
req2.Device1 = '1';
req2.Starting = 2088;
req2.Quantity = 16;
req2.Message = '\r';
tmp = BitConverter.GetBytes(req2.Starting);
CRCc[0] = tmp[0];
CRCc[1] = tmp[1];
CRCc[2] = tmp[2];
CRCc[3] = tmp[3];
tmp = BitConverter.GetBytes(req2.Quantity);
CRCc[4] = tmp[0];
CRCc[5] = tmp[1];
req2._CRC = crc16.ComputeChecksum(CRCc);
textBox6.Text += Environment.NewLine;
textBox6.Text += "CRC: " + req2._CRC;
cl.Client.Send(StructureToByteArray(req2));
cl.Client.Receive(output);
byte[] val = new byte[4];
val[0] = output[15];
val[1] = output[16];
val[2] = output[17];
val[3] = output[18];
textBox6.Text += Environment.NewLine;
textBox6.Text += "Query: ";
for (int i = 0; i < StructureToByteArray(req2).Length; i++)
{
textBox6.Text += StructureToByteArray(req2)[i] + "_";
}
textBox2.Text = BitConverter.ToSingle(val,0).ToString();
textBox6.Text += Environment.NewLine;
textBox6.Text += "Data: ";
for (int i = 0; i < output.Length; i++)
{
textBox6.Text += output[i] + "_";
}
}
...
static byte[] StructureToByteArray(object obj)
{
int len = Marshal.SizeOf(obj);
byte[] arr = new byte[len];
IntPtr ptr = Marshal.AllocHGlobal(len);
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, len);
Marshal.FreeHGlobal(ptr);
return arr;
}
CRC计算正确。但我得到的textBox2.Text数字错误 - 随机数。我怎么能正确得到这个数字?提前谢谢。
Delphi调试器的Scrrenshot:
答案 0 :(得分:2)
好吧,我想我可能已经破译了它,但我不会指望它。
您似乎在说{C#代码在textBox2
中显示意外值。查看C#代码,textBox2
显示来自val
的数据。 val
的分配方式如下:
val[0] = output[15];
val[1] = output[16];
val[2] = output[17];
val[3] = output[18];
请注意,output
是一个C#字节数组,因此使用从零开始的索引。
在您的Delphi代码中,匹配的数据结构是:
outVal=packed record
cap:array[0..8] of byte;
val:array[0..3] of single;
end;
outValBuff=record
case byte of
0:(val:outVal);
1:(Buff:array [1..25] of byte);
end;
因此,cap
消耗前9个字节,然后接下来的16个是4个单精度值。就C#字节数组而言:
cap
output[0]
至output[8]
,val[0]
output[9]
至output[12]
,val[1]
output[13]
至output[16]
,val[2]
output[17]
至output[20]
,val[3]
output[21]
至output[24]
。但您正在阅读output[15]
至output[18]
,因此将val[1]
的一半与val[2]
的一半结合起来。
简而言之,您只需要修改索引。
现在,你正在使它变得更加复杂。您可以执行以下操作来获取所有4个单值:
single[] val = new single[4];
int byteIndex = 9;
for (int i=0; i<4; i++)
{
val[i] = BitConverter.ToSingle(val, byteIndex);
byteIndex += 4;
}
而不是将字节逐字节地复制到CRCc
中,请执行以下操作:
Buffer.BlockCopy(BitConverter.GetBytes(req2.Starting), 0, CRCc, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(req2.Quantity), 0, CRCc, 4, 2);