2

16 進文字列データを入力したときのオンライン CRC 計算に基づく=

503002080000024400003886030400000000010100

結果CRC-CCITT(0xFFFF) = を取得します

0x354E (期待される結果)

.

以下のコードを使用しますが、CalcCRC16()の結果は0xACEEです。以下のスクリプトの欠如は何ですか?

using System;
using System.Windows.Forms;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Diagnostics;

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {

        public Form1() {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e) {
            string result = CalcCRC16("503002080000024400003886030400000000010100");            
            Debug.Print(result);
            // result = ACEE
            // result expected = 354E
        }

        // CRC-CCITT (0xFFFF) with poly 0x1021
        // input (hex string) =  "503002080000024400003886030400000000010100"
        // result expected (hex string) = "354E"
        public string CalcCRC16(string strInput) {
            ushort temp = 0;
            ushort crc = 0xFFFF;
            byte[] bytes = GetBytesFromHexString(strInput);
            for (int j = 0; j < bytes.Length; j++) {
                crc = (ushort)(crc ^ bytes[j]);
                for (int i = 0; i < 8; i++) {
                    if ((crc & 0x0001) == 1)
                        crc = (ushort)((crc >> 1) ^ 0x1021);
                    else
                        crc >>= 1;
                }
            }
            crc = (ushort)~(uint)crc;
            temp = crc;
            crc = (ushort)((crc << 8) | (temp >> 8 & 0xFF));
            return crc.ToString("X4");
        }

        public Byte[] GetBytesFromHexString(string strInput) {
            Byte[] bytArOutput = new Byte[] { };
            if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0) {
                SoapHexBinary hexBinary = null;
                try {
                    hexBinary = SoapHexBinary.Parse(strInput);
                    if (hexBinary != null)
                        bytArOutput = hexBinary.Value;
                }
                catch (Exception ex) {
                    MessageBox.Show(ex.Message);
                }
            }
            return bytArOutput;
        }

    }
}
4

2 に答える 2

3

私は答えを見つけたので、ここで共有します..他の人に役立つかもしれません。

strInput = 503002080000024400003886030400000000010100

初期値 = 0xFFFF

ポリ = 0x1021

strOutput = 354E

参照 =オンライン CRC Calc

public string CalcCRC16(string strInput) {
    ushort crc = 0xFFFF;
    byte[] data = GetBytesFromHexString(strInput);
    for (int i = 0; i < data.Length; i++) {
        crc ^= (ushort)(data[i] << 8);
        for (int j = 0; j < 8; j++) {
            if ((crc & 0x8000) > 0)
                crc = (ushort)((crc << 1) ^ 0x1021);
            else
                crc <<= 1;
        }
    }
    return crc.ToString("X4");
}

public Byte[] GetBytesFromHexString(string strInput) {
    Byte[] bytArOutput = new Byte[] { };
    if (!string.IsNullOrEmpty(strInput) && strInput.Length % 2 == 0) {
        SoapHexBinary hexBinary = null;
        try {
            hexBinary = SoapHexBinary.Parse(strInput);
            if (hexBinary != null) {
                bytArOutput = hexBinary.Value;
            }
        }
        catch (Exception ex) {
            MessageBox.Show(ex.Message);
        }
    }
    return bytArOutput;
}
于 2013-04-18T02:54:48.560 に答える
0

私のアプリケーションで動作する例を次に示します。16 ビットの int ポインターの代わりに char ptrs を使用する必要があったため、多少苦労しました (CCIT は最初に LSB オーダーであるため、バッファーから 1 バイトを選択し、それを 8 回シフトして 16 ビットにして上位を検証します)。 MSB ビット 0x8000)。

人々が 16 ビット CRC に苦労しているときに見つかるほとんどの原因 (ほとんどの場合、8 ビットは機能します):

  • バッファは 8 ビット ptr で呼び出す必要があります
  • XORの前にシフト!
  • int または unsigned int.. は絶対に使用しないでください。ただし、short を使用してください。私のアプリケーションは 16 ビットおよび 32 ビットの Microchip PIC で実行され、int を使用すると、16 ビットの pic では 16 ビットの値になり、32 ビットのプラットフォームでは 32 ビットの値 (ゼロがたくさん!) になります。

BOOL = 符号なし文字。UINT16 = unsigned short。関数はコードで実行されるため、while/forloop ではありません。完了すると、CRC は *crc が指すアドレスにコピーされます。このようにして、すべてのその他のタスク (M95 モデム、MCP の I2C、フラッシュ ログ、TCP/IP などは、あまり大きな遅延なく処理されます)。

BOOL CRC_16(UINT16 ui16_Bytes, char *src, UINT16 *crc)
{    
    static BOOL bNew = FALSE;
    static UINT16  remainder = 0;   
    static UINT16 i = 0;
    static UINT16 ui16_Loc_bytes;
    static char *ptr;
    static char locData;
    if(!bNew)
    {
    ui16_Loc_bytes = ui16_Bytes;
    ptr = src;
    locData = *ptr;
    i = 8;
    remainder = 0x0000;
    bNew = TRUE;
    }
    if(ui16_Loc_bytes)
    {
    if(i == 8)
    {
        remainder ^= (((UINT16)locData)<<8);                //Only 8bits at a time filled with zeros
    }
    if(i)
    {
        if (remainder & 0x8000)
        {
        remainder = (remainder << 1);
        remainder ^= POLYNOMIAL_16;
        }
        else
        {       
        remainder = (remainder << 1);
        }       
        i--;
    }
    else
    {
        ui16_Loc_bytes--;
        ptr++;
        locData = *ptr;
        //ptr++;
        i = 8;
    }

    }
    else
    {
    bNew = FALSE;
    *crc = remainder;
    return TRUE;
    }
    return FALSE;
}


if(SDKaart.ui16_RecBytes >= SDKaart.ui16_ByteLen)//30-5-2018 edited SDKaart.CMD[SDKaart.ui8_ActiefCMD].ui16_RecLen)
                    {
                    SD_DESELECT;
                    if(SDKaart.bInitReady && SDKaart.b_BlockRead)
                    {
                        if(CRC_16(512,(char*)&SDKaart.Mem_Block.SD_Buffer[0], &SDKaart.ui16_MemBlock_CRC))
                        {                       
                        if((((UINT16)SDKaart.Mem_Block.SD_Buffer[512]<<8)|(UINT16)SDKaart.Mem_Block.SD_Buffer[513]) == SDKaart.ui16_MemBlock_CRC)
                        {
                            SDKaart.bRXReady = TRUE;
                            SDKaart.TXStat = SPI_IDLE;
                            printf("CRC16 OK %x\r\n",SDKaart.ui16_MemBlock_CRC);
                        }
                        else
                        {
                            SDKaart.bRXReady = TRUE;
                            SDKaart.TXStat = SPI_IDLE;
                            printf("CRC16 %u != 0x%x 0x%x\r\n",SDKaart.ui16_MemBlock_CRC,SDKaart.Mem_Block.SD_Buffer[512], SDKaart.Mem_Block.SD_Buffer[513] );
                        }
                        //printf("CRC citt: %u\r\n", Calculate_CRC_CCITT((char *)&SDKaart.Mem_Block.SD_Buffer[0],512));
                        }
                    }
                    else
                    {
                        SDKaart.bRXReady = TRUE;
                        SDKaart.TXStat = SPI_IDLE;
                    }
                    }
                    else
                    {                       
                    if(SD_SPI_TX_READY)
                    {
                        SDKaart.bNewSPIByte = TRUE;
                        SPI1BUF = SD_EMPTY_BYTE;                        
                    }
                }

オンラインで見つけた多くの crcs を使用しましたが、多くは機能しませんでした。オンラインの「例」の多くは XOR の後ろで <<1 を使用していますが、xor の前に使用する必要があることに注意してください。

POLY_16 は 0x1021 です。次の機会は、テーブル ピッカーを作成することです。:)

グリーツ、ジョン

于 2018-06-04T07:07:12.447 に答える