我知道java字节是一个8位有符号变量,要获得无符号(字节)值,我将不得不在任何地方使用0xff
进行屏蔽。
Java 文档还说,我可以使用前面提到的过程使用 int 生成无符号位。
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
但是,无论是否使用掩码,它都会返回相同的结果。
我尝试将 short 更改为 int,但没有成功。
德尔福编码
procedure TForm1.ReadHoldRegisters(var lst: TList<byte>; deviceaddr: byte;
RegisterAddress, RegisterLength: word);
begin
lst.Add(deviceaddr);
lst.Add(6);
lst.Add(RegisterAddress div 256);
lst.Add(RegisterAddress mod 256);
lst.Add(RegisterLength div 256);
lst.Add(RegisterLength mod 256);
Add_CRC16(lst);
end;
procedure TForm1.Add_CRC16(var Data: TList<byte>);
var
CRC16Lo, CRC16Hi, CL, CH, SaveHi, SaveLo: byte;
Flag: Integer;
b: byte;
begin
CRC16Lo := $FF;
CRC16Hi := $FF;
CL := $1;
CH := $A0;
for b in Data do
begin
CRC16Lo := CRC16Lo Xor b;
For Flag := 0 To 7 Do
Begin
SaveHi := CRC16Hi;
SaveLo := CRC16Lo;
CRC16Hi := CRC16Hi Div 2;
CRC16Lo := CRC16Lo Div 2;
If ((SaveHi And $1) = $1) Then
begin
CRC16Lo := CRC16Lo Or $80;
end;
If ((SaveLo And $1) = $1) Then
Begin
CRC16Hi := CRC16Hi Xor CH;
CRC16Lo := CRC16Lo Xor CL;
End;
End;
end;
Data.Add(CRC16Lo);
Data.Add(CRC16Hi);
end;
爪哇代码
public void ReadHoldRegisters(List<Short> lst, byte deviceaddr, char RegisterAddress, char RegisterLength)
{
lst.add((short) (deviceaddr & 0xff));
lst.add((short) ((byte) 6 & 0xff));
lst.add((short) ((RegisterAddress / 256 & 0xff)));
lst.add((RegisterAddress%256));
lst.add((RegisterLength/256));
lst.add(((RegisterLength%256)));
Add_CRC16(lst);
}
private void Add_CRC16(List<Short> Data)
{
//Cyclic Redundancy Check 16
short SaveLo, SaveHi;
int flag;
short CRC16Lo = ((short) 0xFF & 0xff);
short CRC16Hi = ((short) 0xFF & 0xff);
short CL = (short) 0x1 & 0xff;
short CH = (short) (0xA0) & 0xff;
short andop = ((short) 0x80 & 0xff);
short andop2 = (short) 0x1 & 0xff;
// início do for in
for (Short b : Data)
{
CRC16Lo ^= b & 0xff;
for(flag=0;flag<7;flag++)
{
SaveHi = (short) ((CRC16Hi) & 0xff);
SaveLo = (short) ((CRC16Lo) & 0xff);
CRC16Hi = (short) ((CRC16Hi/2) & 0xff);
CRC16Lo = (short) ((CRC16Lo/2) & 0xff);
if((SaveHi & andop2) == andop2 )
CRC16Lo |= andop & 0xff;
if(((SaveLo) & (andop2)) == (andop2))
{
CRC16Hi ^= CH & 0xff;
CRC16Lo ^= CL & 0xff;
}
}
}
Data.add((short) (CRC16Lo & 0xff));
Data.add((short) (CRC16Hi & 0xff));
}
在这种情况下要显示的正确结果是"01 06 00 01 00 0A 58 0D"
有什么想法吗?有什么帮助吗?
最明显的区别在这里:
for(flag=0;flag<7;flag++)
此循环的运行次数比德尔福版本少一次。你是说:
for(flag=0;flag<8;flag++)
最重要的是,Java代码是不必要的复杂。它可以大大简化。该程序给出与德尔菲代码相同的输出:
import java.util.*;
public class test
{
public static void ReadHoldRegisters(List<Integer> lst, int deviceaddr, int RegisterAddress, int RegisterLength)
{
lst.add(deviceaddr & 0xff);
lst.add(6);
lst.add((RegisterAddress >> 8) & 0xff);
lst.add(RegisterAddress & 0xff);
lst.add((RegisterLength >> 8) & 0xff);
lst.add(RegisterLength & 0xff);
Add_CRC16(lst);
}
private static void Add_CRC16(List<Integer> Data)
{
int SaveLo, SaveHi;
int CRC16Lo = 0xFF;
int CRC16Hi = 0xff;
int CL = 0x1;
int CH = 0xA0;
for (int b : Data)
{
CRC16Lo ^= b;
for (int flag=0; flag<8; flag++)
{
SaveHi = CRC16Hi;
SaveLo = CRC16Lo;
CRC16Hi = CRC16Hi/2;
CRC16Lo = CRC16Lo/2;
if((SaveHi & 0x01) == 0x01)
CRC16Lo |= 0x80;
if((SaveLo & 0x01) == 0x01)
{
CRC16Hi ^= CH;
CRC16Lo ^= CL;
}
}
}
Data.add(CRC16Lo & 0xff);
Data.add(CRC16Hi & 0xff);
}
public static void main(String[] args)
{
List<Integer> lst = new ArrayList<Integer>();
ReadHoldRegisters(lst, 1, 1, 10);
for (int value: lst)
{
System.out.print(String.format("%02x", value));
System.out.print(" ");
}
}
}