当前位置: 首页 > 知识库问答 >
问题:

如何计算从最后一个字节开始的CRC

高锦
2023-03-14
-- First frame of data
RxFrame.Data <= (
    1 => x"39", -- LSB
    2 => x"38",
    3 => x"37",
    4 => x"36",
    5 => x"35",
    6 => x"34",
    7 => x"33"
);

-- Second/last frame of data
RxFrame.Data <= (
    1 => x"32",
    2 => x"31", -- MSB
    3 => xx,    -- "xx" means irrelevant data, not part of CRC calculation.
    4 => xx,    -- This occurs only in the last frame, when it specified in
    5 => xx,    -- byte 0 which bytes contain data
    6 => xx,
    7 => xx
);

-- Calculated CRC should be 0x31C3
-- First incoming frame of data
RxFrame.Data <= (
    1 => x"39", -- LSB
    2 => x"38",
    3 => x"37",
    4 => x"36",
    5 => x"35",
    6 => x"34",
    7 => x"33"
);

-- Second incoming frame of data
RxFrame.Data <= (
    1 => x"32",
    2 => x"31",
    3 => x"21",
    4 => x"83",
    5 => x"04",
    6 => x"FC",
    7 => x"1C"
);

-- Third/last incoming frame of data
RxFrame.Data <= (
    1 => x"9A",
    2 => x"66",
    3 => x"76",
    4 => x"43", -- MSB
    5 => xx,    -- Irrelevant data, specified in byte 0
    6 => xx,
    7 => xx
);

-- Calculated CRC should be 0x2848

从CANopen标准验证SDO块传输的CRC计算算法

共有1个答案

古文康
2023-03-14

这里有一个C语言的示例,您可以对其进行修改。既然您提到了VHDL,这是一个适合于转换到门和触发器中的稍微明智的实现。然而,如果循环对您来说比内存和门更珍贵,那么还有一个字节式的表驱动版本,它将在1/8的循环数中运行。

这与正常的CRC计算相反。然后,它将相同大小的输入与正常CRC一起应用于零,以获得正常CRC在该输入上的值。运行零所需的周期数与逆CRC相同,即O(n),其中n是输入的大小。如果延迟太大,可以减少到O(log n)个循环,并在门上进行一些投资。

#include <stddef.h>

// Update crc with the CRC-16/XMODEM of n zero bytes. (This can be done in
// O(log n) time or cycles instead of O(n), with a little more effort.)
static unsigned crc16x_zeros_bit(unsigned crc, size_t n) {
    for (size_t i = 0; i < n; i++)
        for (int k = 0; k < 8; k++)
            crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
    return crc & 0xffff;
}

// Update crc with the CRC-16/XMODEM of the len bytes at mem in reverse. If mem
// is NULL, then return the initial value for the CRC. When done,
// crc16x_zeros_bit() must be used to apply the total length of zero bytes, in
// order to get what the CRC would have been if it were calculated on the bytes
// fed in the opposite order.
static unsigned crc16x_inverse_bit(unsigned crc, void const *mem, size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0;
    crc &= 0xffff;
    for (size_t i = 0; i < len; i++) {
        for (int k = 0; k < 8; k++)
            crc = crc & 1 ? (crc >> 1) ^ 0x8810 : crc >> 1;
        crc ^= (unsigned)data[i] << 8;
    }
    return crc;
}

#include <stdio.h>

int main(void) {
    // Do framed example.
    unsigned crc = crc16x_inverse_bit(0, NULL, 0);
    crc = crc16x_inverse_bit(crc, (void const *)"9876543", 7);
    crc = crc16x_inverse_bit(crc, (void const *)"21", 2);
    crc = crc16x_zeros_bit(crc, 9);
    printf("%04x\n", crc);

    // Do another one.
    crc = crc16x_inverse_bit(0, NULL, 0);
    crc = crc16x_inverse_bit(crc, (void const *)"9876543", 7);
    crc = crc16x_inverse_bit(crc, (void const *)"21!\x83\x04\xfc\x1c", 7);
    crc = crc16x_inverse_bit(crc, (void const *)"\x9a" "fvC", 4);
    crc = crc16x_zeros_bit(crc, 18);
    printf("%04x\n", crc);
    return 0;
}

以下是crc16x_zeros_bit()的O(log n)版本:

// Return a(x) multiplied by b(x) modulo p(x), where p(x) is the CRC
// polynomial. For speed, a cannot be zero.
static inline unsigned multmodp(unsigned a, unsigned b) {
    unsigned p = 0;
    for (;;) {
        if (a & 1) {
            p ^= b;
            if (a == 1)
                break;
        }
        a >>= 1;
        b = b & 0x8000 ? (b << 1) ^ 0x1021 : b << 1;
    }
    return p & 0xffff;
}

// Return x^(8n) modulo p(x).
static unsigned x2nmodp(size_t n) {
    unsigned p = 1;                     // x^0 == 1
    unsigned q = 0x10;                  // x^2^2
    while (n) {
        q = multmodp(q, q);             // x^2^k mod p(x), k = 3,4,...
        if (n & 1)
            p = multmodp(q, p);
        n >>= 1;
    }
    return p;
}

// Update crc with the CRC-16/XMODEM of n zero bytes.
static unsigned crc16x_zeros_bit(unsigned crc, size_t n) {
    return multmodp(x2nmodp(n), crc);
}
 类似资料:
  • 我想知道是否有可能找出服务器使用TCP连接发送给客户端的最后一个字节。具体来说,我有一个客户端和一个服务器,都是C语言。他们使用XMLRPC进行通信,连接是TCP。客户端可以向服务器发送一个大请求,由于一些计算,服务器可能需要一些时间才能回复。在连接的任何部分,如果断开连接,整个过程都应该从头开始,这会导致服务器容易受到DoS攻击。 我的问题是,我是否可以找出连接断开的位置,以便在重新建立连接(对

  • 问题内容: 我在计算本月下一个最后一天何时发送预定的通知时遇到问题。 这是我的代码: 这是导致问题的线,我相信: 如何使用日历正确设置下个月的通知的最后一天? 问题答案: 这将返回当前月份的实际最大值。例如,现在是leap年的2月,因此它返回29作为。

  • 问题内容: 我想学习最好/最简单的方法,将一个字符串转换为另一个字符串,但只有一个子集,从一个字符的开头到最后一个索引。 例如,将。什么样的代码片段会做到这一点,并且最快捷?(我希望这不会引起争论,但是我找不到关于如何在Swift中处理子字符串的好课程。 问题答案: 最好的方法是结合使用属性和全局功能。 寻找从背面开始的字符串 使用并设置为 没有扩展,纯真的Swift 雨燕2.0 现在是的一部分,

  • 我有一组原点-终点坐标,我想计算它们之间的最短路径。 我的出发地坐标有时位于一条长直线道路的中间。然而,由OSMNX/NETWorkX计算的最短路径将不考虑中间边缘到最近的节点路径。 OSMnx或networkx中是否有任何现成的函数,我可以使用它来找到在道路中间起点/终点的最短路径? 如果没有这样的功能,我会考虑使用以下步骤。 获取起点和终点的最近边 获取这些最近边的节点:假设(a,b)为起点,

  • 我正在写一个简单的日历课程。我正在尝试重载,以便使用它将日历移动到下个月。然而,我找到下个月开始日期的算法并不完全正确。 1月定义为0,12月为11,周日为0,周六为6。start Day、previousStartDay、nextStartDay、月份和年份都是私有类变量 当我在2013年进行测试时,日期直到3月都是正确的。在这一点上,它将下一个开始日定为周二,而不是周一。 我也试过: 然而,它

  • 问题 你需要查找星期中某一天最后出现的日期,比如星期五。 解决方案 Python的 datetime 模块中有工具函数和类可以帮助你执行这样的计算。 下面是对类似这样的问题的一个通用解决方案: #!/usr/bin/env python # -*- encoding: utf-8 -*- """ Topic: 最后的周五 Desc : """ from datetime import dateti