Нахождение правильного полинома CR C - PullRequest
0 голосов
/ 04 августа 2020

Я использую контроллер подвеса simpleBG C от Basecam electronics. Контроллер имеет последовательный API для связи, который требует вычисления контрольной суммы crc16 для команд, отправленных контроллеру (https://www.basecamelectronics.com/file/SimpleBGC_2_6_Serial_Protocol_Specification.pdf) (стр.3)

Я хочу отправить команду сброса в контроллер, который имеет следующий формат:

Заголовок: {начальный символ: '$', идентификатор команды: '114', размер полезной нагрузки: '3', контрольная сумма заголовка: '117'}

Полезная нагрузка: {3,0,0} (3 байта, соответствующие параметрам сброса и времени сброса)

контрольная сумма crc16:? (с использованием полинома 0x8005, рассчитанного для всех байтов , кроме начального символа )

Шестнадцатеричное представление моей команды: 0x24720375030000, и мне нужно найти контрольную сумму crc16 для 0x720375030000. Я использовал разные калькуляторы cr c, но контроллер не отвечает на команду, и я предполагаю, что контрольная сумма cr c неверна. Чтобы найти правильную контрольную сумму crc16, я отправил все возможные комбинации контрольной суммы crc16 и обнаружил, что контроллер отвечает, когда контрольная сумма равна «7b25». поэтому правильная команда в шестнадцатеричном формате: «24 720375030000 7b25». Но эта контрольная сумма 7b25 не соответствует полиному 0x8005. Как я могу найти правильную функцию вычисления полинома или crc16?

1 Ответ

0 голосов
/ 04 августа 2020

Вы пробовали использовать код из приложения к документу, который вы связали? Он отлично работает и выдает 0x257b для CR C ваших данных примера. Затем это записывается в поток в порядке обратного порядка байтов, что дает ожидаемое 7b 25.

Вот более простая и быстрая реализация C, чем в приложении:

#include <stddef.h>

// Return a with the low 16 bits reversed and any bits above that zeroed.
static unsigned rev16(unsigned a) {
    a = (a & 0xff00) >> 8 | (a & 0x00ff) << 8;
    a = (a & 0xf0f0) >> 4 | (a & 0x0f0f) << 4;
    a = (a & 0xcccc) >> 2 | (a & 0x3333) << 2;
    a = (a & 0xaaaa) >> 1 | (a & 0x5555) << 1;
    return a;
}

// Implement the CRC specified in the BASECAM SimpleBGC32 2.6x serial protocol
// specification. Return crc updated with the length bytes at message. If
// message is NULL, then return the initial CRC value. This CRC is like
// CRC-16/ARC, but with the bits reversed.
//
// This is a simple bit-wise implementation. Byte-wise and word-wise algorithms
// using tables exist for higher speed if needed. Also this implementation
// chooses to reverse the CRC bits as opposed to the data bits, as done in the
// specficiation appendix. The CRC only needs to be reversed once at the start
// and once at the end, whereas the alternative is reversing every data byte of
// the message. Reversing the CRC twice is faster for messages with length
// greater than two bytes.
unsigned crc16_simplebgc(unsigned crc, void const *message, size_t length) {
    if (message == NULL)
        return 0;
    unsigned char const *data = message;
    crc = rev16(crc);
    for (size_t i = 0; i < length; i++) {
        crc ^= data[i];
        for (int k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
    }
    return rev16(crc);
}

#include <stdio.h>

// Example usage of crc_simplebgc(). A CRC can be computed all at once, or with
// portions of the data at a time.
int main(void) {
    unsigned crc = crc16_simplebgc(0, NULL, 0);         // set initial CRC
    crc = crc16_simplebgc(crc, "\x72\x03\x75", 3);      // first three bytes
    crc = crc16_simplebgc(crc, "\x03\x00\x00", 3);      // remaining bytes
    printf("%04x\n", crc);                              // prints 257b
    return 0;
}
...