1

c# を使用して16-CRC [DNP]を実装しようとしてgenerator polynomialいます。

ここに画像の説明を入力

16-crc の標準的な解決策を見つけました : [ソース]

public class Crc16
{
    const ushort polynomial = 0xA001;
    ushort[] table = new ushort[256];

    public ushort ComputeChecksum ( byte[] bytes )
    {
        ushort crc = 0;
        for ( int i = 0; i < bytes.Length; ++i )
        {
            byte index = ( byte ) ( crc ^ bytes[i] );
            crc = ( ushort ) ( ( crc >> 8 ) ^ table[index] );
        }
        return crc;
    }

    public byte[] ComputeChecksumBytes ( byte[] bytes )
    {
        ushort crc = ComputeChecksum ( bytes );
        return BitConverter.GetBytes ( crc );
    }

    public Crc16 ()
    {
        ushort value;
        ushort temp;
        for ( ushort i = 0; i < table.Length; ++i )
        {
            value = 0;
            temp = i;
            for ( byte j = 0; j < 8; ++j )
            {
                if ( ( ( value ^ temp ) & 0x0001 ) != 0 )
                {
                    value = ( ushort ) ( ( value >> 1 ) ^ polynomial );
                }
                else
                {
                    value >>= 1;
                }
                temp >>= 1;
            }
            table[i] = value;
        }
    }
}

ここで、多項式を変換すると1 0011 1101 0110 0111=>が得られ(3D65)h、私の質問は、特定の多項式に対して上記のソリューションを機能させるために何を変更する必要があるかです。

Edit: また、2 つのことを考慮する必要があります。

1) 初期値は 0 &
2) 最終 CRC を補完する必要があります。

4

3 に答える 3

3

これは実際に私にとって非常に役に立ちました。ただし、私は SanVEE が行ったソリューションを使用しませんでした。Mark Adler が説明したように、元の投稿のコードを実際に変更したところ、うまく機能しました。少なくとも、これまでのところ、結果はここにある DNP3 チェックサム計算機と一致します: http://www.lammertbies.nl/comm/info/crc-calculation.html

SanVEE の回答として投稿されたコードは、比較のためにテストしていませんが、非常に非効率的である可能性があります (各ビットを保存するために bool を使用するなど)。同じ質問に直面している人は、両方の回答を調べて、どちらが自分に適しているかを確認したいと思うかもしれません.

    public class Crc16DNP3
    {
        const ushort polynomial = 0xA6BC; //0xA001;
        ushort[] table = new ushort[256];

        public ushort ComputeChecksum(byte[] bytes)
        {
            ushort crc = 0;
            for (int i = 0; i < bytes.Length; ++i)
            {
                byte index = (byte)(crc ^ bytes[i]);
                crc = (ushort)((crc >> 8) ^ table[index]);
            }
            crc = SwapBytes((ushort)(crc ^ 0xffff));
            return crc;
        }

        public byte[] ComputeChecksumBytes(byte[] bytes)
        {
            ushort crc = ComputeChecksum(bytes);
            return BitConverter.GetBytes(crc);
        }

        // SwapBytes taken from http://stackoverflow.com/questions/19560436/bitwise-endian-swap-for-various-types
        private ushort SwapBytes(ushort x)
        {
            return (ushort)((ushort)((x & 0xff) << 8) | ((x >> 8) & 0xff));
        }

        public Crc16DNP3()
        {
            ushort value;
            ushort temp;
            for (ushort i = 0; i < table.Length; ++i)
            {
                value = 0;
                temp = i;
                for (byte j = 0; j < 8; ++j)
                {
                    if (((value ^ temp) & 0x0001) != 0)
                    {
                        value = (ushort)((value >> 1) ^ polynomial);
                    }
                    else
                    {
                        value >>= 1;
                    }
                    temp >>= 1;
                }
                table[i] = value;
            }
        }
    }
于 2016-03-15T01:18:33.603 に答える
2

最初のリンクのコードの何が問題になっていますか? また、メッセージ内での CRC バイトの順序も指定します。

x 16以下の多項式を逆にする必要があります。ビット形式の多項式は です10011110101100101。先頭1(x 16 ) を削除すると、次の 4 つのグループになります0011 1101 0110 0101。逆つまり: 1010 0110 1011 1100. したがって、設定する必要がありますpolynomial = 0xA6BC

初期値はすでにゼロです。最終的な CRC の補完は、 で簡単に行うことができます^ 0xffff

于 2014-09-19T14:57:22.480 に答える