LINUX.ORG.RU

Нужна помощь в поиске алгоритма для CRC16 - CCITT

 


0

1

Есть микроконтроллер arduino mega 2560, который нужно подружить с ККТ PAYONLINE 01-ФА, в документации _https://disk.yandex.ru/d/ypcRmv7JlPbWCw описан пример как реализовать расчет CRC16-CCITT, но он не подходит. мне известны пакеты данных которые отправляет официальная программа «Тест драйвер ККТ» например: 02 05 10 1E 00 00 00 0B или 02 05 11 1E 00 00 00 0A и ответ от самой ККТ: 02 | 10 | 10 | 00 | 1E 90 0A 04 00 00 9E DE 18 01 00 75 02 00 | AE или соответственно 02 | 30 | 11 | 00 | 1E 43 31 08 07 13 01 17 01 38 00 90 0A 04 00 00 4E 41 00 00 01 01 10 1A 0B 18 0A 06 23 00 ED 29 00 00 0C 00 00 00 00 00 FC 15 CF CB 01 00 | FD по документации указано что первый бит это стартовый, второй(иногда еще и 3 бит) это длина пакета данных (без учета стартового бита и CRC) и в конце это сам CRC. я перепробовал множество популярных полиномов но ни один не подходит, также пробовал программу по подбору полинома для crc16, который перебирает все варианты, делал реверс инжиниринг программы «Тест драйвер ККТ», там есть намеки на CRC32 и CRC16-CCITT, но в ассемблере я не сильно шарю, файл из IDA тоже приложу по ссылке выше. Заранее спасибо за помощь.

Перемещено CrX из general

Ответ на: комментарий от Bfgeshka

если взять это пакет данных 02 05 10 1E 00 00 00 0B , то 0B это crc. я пытался самостоятельно рассчитать crc но 0B не выходит, стартовый бит 02 в расчет не входит, второй бит 05 это длина пакета данных (10 1E 00 00 00)

denis2107
() автор топика

CCITT

есть несколько вариаций:

        case CCITT_0xFFFF:
            return crc(nBytes, straight_8, straight_16, 0xffff, 0x1021);
        case CCITT_0x0000_AKA_XMODEM:
            return crc(nBytes, straight_8, straight_16, 0x0000, 0x1021);
        case CCITT_KERMIT:
            return crc(nBytes, reverse_8, reverse_16, 0xffff, 0x1021);
        case CCIT_0x1D0F:
            return crc(nBytes, straight_8, straight_16, 0x1d0f, 0x1021);

весь код привести не могу, вот куски, чтобы получилось рассчитать:

typedef uint8_t bit_order_8(uint8_t value);
typedef uint16_t bit_order_16(uint16_t value);

uint16_t straight_16(uint16_t value) {
    return value;
}

uint16_t reverse_16(uint16_t value) {
    uint16_t reversed = 0;
    for (int i = 0; i < 16; ++i) {
        reversed <<= 1;
        reversed |= value & 0x1;
        value >>= 1;
    }
    return reversed;
}

uint8_t straight_8(uint8_t value) {
    return value;
}

uint8_t reverse_8(uint8_t value) {
    uint8_t reversed = 0;
    for (int i = 0; i < 8; ++i) {
        reversed <<= 1;
        reversed |= value & 0x1;
        value >>= 1;
    }
    return reversed;
}

uint16_t crc(int nBytes, bit_order_8 dataBitOrder, bit_order_16 remainderBitOrder,
        uint16_t initial, uint16_t polynomial) {
    uint16_t crc = initial;
    for (int byte = 0; byte < nBytes; byte++) {
        crc ^= (dataBitOrder(rawBuffer[byte]) << 8);
        for (uint8_t bit = 8; bit > 0; --bit) {
            if (crc & 0x8000) {
                crc = (crc << 1) ^ polynomial;
            } else {
                crc = (crc << 1);
            }
        }
    }
    return remainderBitOrder(crc);
}

//твою документацию я, естественно, не читал. :) в моем примере - nBytes - размер данных, от которых надо посчитать КС, сами данные в rawBuffer.

aol ★★★★★
()
Последнее исправление: aol (всего исправлений: 1)

по документации указано что первый бит это стартовый

Не путай ж с пальцем. «Стартовый» и «стоповый» - это служебные биты. Даже если CRC считается побитно (хотя для программной реализации так никто делать не будет) в ней учитываются только информационные биты октета.

Гугли A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, он хоть и написан 30 лет назад, но ничего лучшего нет. Самые распространённые косяки реализации — зеркалирование (reflection) или его отсутствие не там, где надо (оно может быть либо перед расчетом, либо после), или не то начальное значение суммы (оно не для всех алгоритмов 0).

anonymous
()
Ответ на: комментарий от anonymous

прошу прощения у всех за свою недалекость, не заметил в документации следующее: Байт N+2 – контрольная сумма сообщения – байт LRC – вычисляется поразрядным сложением (XOR) всех байтов сообщения (кроме байта 0) там имеется стандартный нижний уровень и альтернативный, и я бился о второй вариант, видя схему пакетов данных похожую на протокол CashCode CCNET. оказалось все проще чем я думал

denis2107
() автор топика

в документации

https://github.com/ckormanyos/crc-catalog

crc-catalog implements numerous CRCs using a bitwise algorithm implemented as a single C++ template. This can be useful for verifying existing or new CRC algorithms. Well-known CRCs are implemented as specific functions with intuitive names. There are function bindings for both the C++ as well as the C language.

Using crc-catalog is straightforward. For instance, let’s calculate the standard check of CRC16/CCITT-FALSE

For additional information on the parameters and origins of most of these CRCs implemented in this repo, see also http://reveng.sourceforge.net/crc-catalogue/

Catalogue of parametrised CRC algorithms
This catalogue lists cyclic redundancy check algorithms fully specified in the literature or known to be in use in the field. The algorithms are specified as parameter sets in the Rocksoft™ Model set out in Ross Williams’ 1993 paper «A Painless Guide to CRC Error Detection Algorithms». Each algorithm is supported by references providing evidence and some incidental context of its use. CRC RevEng, an arbitrary-precision CRC calculator and algorithm finder, serves as a reference implementation of the catalogue and likewise, the catalogue provides supporting evidence for the presets in the calculator.

The CRC catalogue was first published on 30 March 2005. This edition (first published 4 July 2012) has been expanded with more complete citations, and reformatted for more reliable rendering.

https://reveng.sourceforge.io/crc-catalogue/ Last updated 9 September 2023

dataman ★★★★★
()

Документация:

Байт N+2 – контрольная сумма сообщения – байт LRC – вычисляется поразрядным сложением (XOR) всех байтов сообщения (кроме байта 0).

02 05 10 1E 00 00 00 0B -> 05 ^ 10 ^ 1E = 0B

Тут вот некоторые очень недовольны когда на вопросы отвечают RTFM или читай man и предлагают разжевать всё за пассажира. Вот прям нагляднейший результат этого сюсюканья.

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 1)

Байт N+2 – контрольная сумма сообщения – байт LRC – вычисляется поразрядным сложением (XOR) всех байтов сообщения (кроме байта 0)

Черным по белому же написано.

anonymous
()