【问题标题】:Finding out the correct CRC polynomial找出正确的 CRC 多项式
【发布时间】:2020-08-04 08:24:49
【问题描述】:

我正在使用 Basecam Electronics 的 simpleBGC 云台控制器。控制器有一个用于通信的串行 API,需要计算发送到控制器的命令的 crc16 校验和(https://www.basecamelectronics.com/file/SimpleBGC_2_6_Serial_Protocol_Specification.pdf)(第 3 页)

我想向控制器发送复位命令,格式如下:

标头:{start char:'$',命令 id:'114',有效负载大小:'3',标头校验和:'117'}

Payload:{3,0,0}(3 个字节对应重置选项和重置时间)

crc16 校验和:? (使用多项式 0x8005 计算所有字节除了起始字符​​strong>)

我的命令的十六进制表示是:0x24720375030000,我需要找到 0x720375030000 的 crc16 校验和。我使用了不同的 crc 计算器,但控制器没有响应命令,我认为 crc 校验和不正确。 为了找到正确的 crc16 校验和,我发送了所有可能的 crc16 校验和组合,并发现控制器在校验和为“7b25”时做出响应。 所以十六进制的正确命令是:“24 720375030000 7b25”。 但是这个校验和 7b25 不对应多项式 0x8005。 如何找到正确的多项式或 crc16 计算函数?

【问题讨论】:

标签: byte crc16


【解决方案1】:

您是否尝试过您链接的文档附录中的代码?它工作正常,并为您的示例数据的 CRC 生成 0x257b。然后以小端顺序将其写入流中,给出您所期望的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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多