1

私はRC飛行機用の簡単な地上管制局を建設しようとしています。ほぼ完了しましたが、チェックサムの計算に多くの問題があります。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行目の間にあると確信しています。0x940x88の出力を期待していますが、代わりにプログラムは0x2D0xF4を出力します。

どこが間違っているのか誰かに教えてもらえれば幸いです。

キャメロン、助けてくれてありがとう

4

1 に答える 1

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に符号なし数値型がないことです。そのため、andの代わりに次に大きい数値型を使用し、必要に応じて上位ビットをマスクすることで、この問題を回避するushort必要byteがあります。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ます。

于 2012-09-24T02:08:08.093 に答える