简体   繁体   English

什么缺少CRC-CCITT(0xFFFF)?

[英]What the lack of CRC-CCITT (0xFFFF)?

Based Online CRC calculation , when I entered hex string data = 基于在线CRC计算 ,当我输入十六进制字符串数据=

503002080000024400003886030400000000010100 503002080000024400003886030400000000010100

I get result CRC-CCITT (0xFFFF) = 我得到结果CRC-CCITT(0xFFFF) =

0x354E (Expected Result) 0x354E(预期结果)

.

I use the code below, but the results of CalcCRC16() are 0xACEE . 我使用下面的代码,但CalcCRC16()的结果为0xACEE What the lack of script below? 下面缺少什么脚本?

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;
        }

    }
}

I found the answer and I will share here.. may be useful to others. 我找到了答案,我将在这里分享..可能对其他人有用。

strInput = 503002080000024400003886030400000000010100 strInput = 503002080000024400003886030400000000010100

initial = 0xFFFF 初始= 0xFFFF

poly = 0x1021 多边形= 0x​​1021

strOutput = 354E str输出= 354E

reference = Online CRC Calc 参考= 在线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;
}

Here's an example which works in my application. 这是一个适用于我的应用程序的示例。 I struggled somewhat, now I know its because I had to use char ptrs in stead of 16bit int pointers (because CCIT is LSB order first, so we pick 1 byte from the buffer, shift it 8 times to make it 16bit to validate the upper MSB bit 0x8000). 我有些挣扎,现在我知道了,因为我必须使用char ptrs代替16bit的int指针(因为CCIT首先是LSB顺序,所以我们从缓冲区中选择1个字节,将其移位8次以使其变为16bit,以验证高位MSB位0x8000)。

Most causes found when people struggle with 16bit CRC (while 8bit most of the time works): 人们在使用16位CRC进行挣扎时发现了大多数原因(而大多数时候8bit起作用):

  • Buffer should be called by 8bit ptr 缓冲区应由8bit ptr调用
  • Shifting BEFORE the XOR! 在XOR之前转移!
  • Never use int or unsigned int.. but use short! 切勿使用int或unsigned int ..而是使用short! My application runs on 16 and 32bit Microchip PIC's and using ints results in 16bit values on the 16bit pic and 32bit values (so lot of zeros!) on 32bit platforms. 我的应用程序在16位和32位Microchip PIC上运行,使用int会在16位pic上产生16位值,在32位平台上产生32位值(很多零!)。

BOOL = unsigned char. BOOL =未签名的字符。 UINT16 = unsigned short. UINT16 =无符号的短路。 The function runs in code, so not a while/forloop. 该函数在代码中运行,因此不是while / forloop。 When done, the CRC is copied to the address pointed by *crc. 完成后,将CRC复制到* crc指向的地址。 This way all ather tasks (M95 modem, MCP's I2C, Flash logs, TCP/IP etc. will be handled without too large delays). 这样,所有其他任务(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;                        
                    }
                }

I have used many crcs found online, but a lottt didn't work. 我使用了许多在网上找到的crcs,但是lottt没用。 Be aware a lot of online "examples" do use <<1 behind the XOR, but it must be done before xor. 请注意,许多在线“示例”确实在XOR后面使用<< <<,但是必须在xor之前完成。

POLY_16 is 0x1021. POLY_16为0x1021。 Next oppurtunity is to build a table picker. 下一个机会是构建表选择器。 :) :)

Greetz, John 约翰·格蕾兹

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM