Что за отсутствие CRC-CCITT (0xFFFF)?

На основе онлайн-вычисления 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;
        }

    }
}

person new bie    schedule 18.04.2013    source источник


Ответы (2)


Я нашел ответ, и я поделюсь здесь .. может быть полезен другим.

стрИнпут = 503002080000024400003886030400000000010100

начальный = 0xFFFF

поли = 0x1021

стрВыход = 354E

reference = Онлайн-расчет 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;
}
person new bie    schedule 18.04.2013

Вот пример, который работает в моем приложении. Я немного боролся, теперь я знаю это, потому что мне пришлось использовать char ptrs вместо 16-битных указателей int (потому что CCIT - это сначала порядок LSB, поэтому мы выбираем 1 байт из буфера, сдвигаем его 8 раз, чтобы сделать его 16-битным для проверки верхнего Старший бит 0x8000).

Большинство причин, обнаруженных, когда люди борются с 16-битной CRC (в то время как 8-битная в большинстве случаев работает):

  • Буфер должен вызываться 8-битным ptr
  • Сдвиг ДО XOR!
  • Никогда не используйте int или unsigned int.. но используйте short! Мое приложение работает на 16- и 32-битных микрочиповых PIC, и использование int приводит к 16-битным значениям на 16-битном изображении и 32-битным значениям (так много нулей!) на 32-битных платформах.

BOOL = символ без знака. UINT16 = короткое без знака. Функция работает в коде, поэтому не в цикле while/forloop. Когда это сделано, CRC копируется по адресу, указанному *crc. Таким образом, все остальные задачи (модем M95, I2C MCP, журналы флэш-памяти, 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;                        
                    }
                }

Я использовал множество CRC, найденных в Интернете, но многие из них не сработали. Имейте в виду, что во многих онлайн-«примерах» используется ‹‹1 после XOR, но это должно быть сделано до xor.

POLY_16 — это 0x1021. Следующей возможностью является создание сборщика таблиц. :)

Грец, Джон

person John Schellingerhout    schedule 04.06.2018