2

基于在线 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

我找到了答案,我将在这里分享..可能对其他人有用。

str输入 = 503002080000024400003886030400000000010100

初始 = 0xFFFF

聚 = 0x1021

str输出 = 354E

参考 =在线 CRC 计算

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

这是一个适用于我的应用程序的示例。我有点挣扎,现在我知道了,因为我必须使用 char ptrs 而不是 16 位 int 指针(因为 CCIT 是 LSB 顺序优先,所以我们从缓冲区中选择 1 个字节,将其移动 8 次使其成为 16 位以验证上MSB 位 0x8000)。

当人们与 16 位 CRC 作斗争时发现的大多数原因(而 8 位大部分时间都有效):

  • 缓冲区应该由 8bit ptr 调用
  • 在 XOR 之前移动!
  • 永远不要使用 int 或 unsigned int.. 而是使用 short!我的应用程序在 16 位和 32 位 Microchip PIC 上运行,使用 int 在 16 位 pic 上产生 16 位值,在 32 位平台上产生 32 位值(这么多零!)。

BOOL = 无符号字符。UINT16 = 无符号短。该函数在代码中运行,因此不是 while/forloop。完成后,CRC 被复制到 *crc 指向的地址。这样所有其他任务(M95 调制解调器、MCP 的 I2C、Flash 日志、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,但一个lottt没有用。请注意,许多在线“示例”确实在 XOR 后面使用 <<1,但必须在 xor 之前完成。

POLY_16 是 0x1021。下一个机会是构建一个表格选择器。:)

格雷茨,约翰

于 2018-06-04T07:07:12.447 回答