将小型C#校验和程序转换为Java

时间:2012-09-24 00:52:43

标签: c# java checksum

我正在尝试为遥控飞机建造一个简单的地面控制站。我差不多完成了它,但是我在校验和计算方面遇到了很多麻烦。据我所知,Java和C#的数据类型不同。我试图解释这个,但我不确定我是否成功了。该程序使用CRC-16-CCITT方法。

这是我的端口:

public int crc_accumulate(int b, int crc) {
        int ch = (b ^ (crc & 0x00ff));
        ch = (ch ^ (ch << 4));
        return ((crc >> 8) ^ (ch << 8) ^ (ch << 3) ^ (ch >> 4));
}

public byte[] crc_calculate() {
        int[] pBuffer=new int[]{255,9,19,1,1,0,0,0,0,0,2,3,81,4,3};
        int crcEx=0;
        int clength=pBuffer.length;
        int[] X25_INIT_CRC=new int[]{255,255};
        byte[] crcTmp=new byte[]{(byte)255,(byte)255};
        int crcTmp2 = ((crcTmp[0] & 0xff) << 8) | (crcTmp[1] & 0xff);
        crcTmp[0]=(byte)crcTmp2;
        crcTmp[1]=(byte)(crcTmp2 >> 8);
        System.out.println("pre-calculation: 0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+";   ushort: "+crcTmp2);
        if (clength < 1) {
                System.out.println("clength < 1");
                return crcTmp;
        }
        for (int i=1; i<clength; i++) {
                crcTmp2 = crc_accumulate(pBuffer[i], crcTmp2);
        }
        crcTmp[0]=(byte)crcTmp2;
        crcTmp[1]=(byte)(crcTmp2 >> 8);
        System.out.print("crc calculation: 0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+";   ushort: "+crcTmp2);
        if (crcEx!=-1) {
                System.out.println("  extraCRC["+crcEx+"]="+extraCRC[crcEx]);
                crcTmp2=crc_accumulate(extraCRC[crcEx], crcTmp2);
                crcTmp[0]=(byte)crcTmp2;
                crcTmp[1]=(byte)(crcTmp2 >> 8);
        System.out.println("with extra CRC:  0x"+Integer.toHexString((crcTmp[0]&0xff))+" 0x"+Integer.toHexString((crcTmp[1]&0xff))+";   ushort: "+crcTmp2+"\n\n");
        }
        return crcTmp;
}

这是原始的C#文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ArdupilotMega
{
class MavlinkCRC
{
    const int X25_INIT_CRC = 0xffff;
    const int X25_VALIDATE_CRC = 0xf0b8;

    public static ushort crc_accumulate(byte b, ushort crc)
    {
        unchecked
        {
            byte ch = (byte)(b ^ (byte)(crc & 0x00ff));
            ch = (byte)(ch ^ (ch << 4));
            return (ushort)((crc >> 8) ^ (ch << 8) ^ (ch << 3) ^ (ch >> 4));
        }
    }

    public static ushort crc_calculate(byte[] pBuffer, int length)
    {
        if (length < 1)
        {
            return 0xffff;
        }
        // For a "message" of length bytes contained in the unsigned char array
        // pointed to by pBuffer, calculate the CRC
        // crcCalculate(unsigned char* pBuffer, int length, unsigned short* checkConst) < not needed

        ushort crcTmp;
        int i;

        crcTmp = X25_INIT_CRC;

        for (i = 1; i < length; i++) // skips header U
        {
            crcTmp = crc_accumulate(pBuffer[i], crcTmp);
            //Console.WriteLine(crcTmp + " " + pBuffer[i] + " " + length);
        }

        return (crcTmp);
    }

}
}

我很确定我的端口中的问题位于第1行和第5行之间。我希望得到输出0x94 0x88,但程序输出0x2D 0xF4。

如果有人能告诉我出错的地方,我将不胜感激。

感谢您的帮助, 卡梅伦

1 个答案:

答案 0 :(得分:2)

好吧,首先让我们清理C#代码:

const int X25_INIT_CRC = 0xffff;

public static ushort crc_accumulate(byte b, ushort crc)
{
    unchecked
    {
        byte ch = (byte)(b ^ (byte)(crc & 0x00ff));
        ch = (byte)(ch ^ (ch << 4));

        return (ushort)((crc >> 8) ^ (ch << 8) ^ (ch << 3) ^ (ch >> 4));
    }
}

public static ushort crc_calculate(byte[] pBuffer)
{
    ushort crcTmp = X25_INIT_CRC;

    for (int i = 1; i < pBuffer.Length; i++) // skips header U
        crcTmp = crc_accumulate(pBuffer[i], crcTmp);

    return crcTmp;
}

现在最大的问题是Java中没有未签名的数字类型,因此您必须使用下一个更大的数字类型而不是ushortbyte来解决这个问题。根据需要高位。您也可以删除unchecked,因为Java无论如何都没有溢出检查。最终结果是这样的:

public static final int X25_INIT_CRC = 0xffff;

public static int crc_accumulate(short b, int crc) {
    short ch = (short)((b ^ crc) & 0xff);
    ch = (short)((ch ^ (ch << 4)) & 0xff);

    return ((crc >> 8) ^ (ch << 8) ^ (ch << 3) ^ (ch >> 4)) & 0xffff;
}

public static int crc_calculate(short[] pBuffer) {
    int crcTmp = X25_INIT_CRC;

    for (int i = 1; i < pBuffer.length; i++) // skips header U
        crcTmp = crc_accumulate(pBuffer[i], crcTmp);

    return crcTmp;
}

对于问题中的输入({ 255, 9, 19, 1, 1, 0, 0, 0, 0, 0, 2, 3, 81, 4, 3 })原始C#,清理C#和Java都会生成0xfc7e