This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F2.8377万D:VCU2 CRC与手动计算

Guru**** 2602065 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/666669/tms320f28377d-vcu2-crc-vs-manual-calculation

部件号:TMS320F2.8377万D

你好。

我已通过示例项目中的VCU2函数计算了测试阵列"0xAF41"的CRC-16。

对于"INIT_CRC16 = 0x0000""Calculated_CRC = 0x1C73",对于"INIT_CRC16 = 0xff",对于"Calculated_CRC = 0x9C7E"。

如果我手动计算此测试阵列的CRC-16,我将获得相同的初始值"0"结果,但对于初始化"0xFFFFFF"("calculated_CRC = 0x1C57",请参见下图)。

如果我想要通过VCU计算的CRC等于手动计算的CRC,我必须在 测试阵列前面设置"init_CRC16 = 0x0000"和实际初始值(0xFFff)写入(在这种情况下,测试阵列将为"0xFFFFFAF41")。 然后 ,"Calculated_CRC = 0x1C57"。

 这是否是CRC VCU计算的正常行为? 在调用CRC VCU函数以获得正确结果之前,是否需要在数组前面写入初始值?

我知道在线CRC计算器会产生CRC VCU函数之类的结果,但我无法理解他们为什么会这样做以及我必须做什么。 可能全球惯例是计算CRC?

我的CRC参数:

名称:CRC-16
宽:16
Poly:0x8005
初始化:0xFFFF
参考:错误
RefOut:错误
XorOut:0xFFFF

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Aleksey:

    在0xFFFF的情况下,您调用的是VCU库中的哪些特定功能,以及如何设置它?

    在进行CRC计算之前,种子(初始化)与第一个值0xAF41是XOR。 现在我注意到答案实际上是你最后得到的翻转输出

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="Vishal Coelho"]

    在0xFFFF的情况下,您调用的是VCU库中的哪些特定功能,以及如何设置它?

    [/引述]

    我使用文件"CRC16.c"中的函数"Calculate_CRC16"(我已 附上)。 从示例项目“2837x_vcu2_crc_16”中进行CRC计算后,我只为结果值添加了XOR和0xFFFF。 我不会反映任何价值观。

    e2e.ti.com/.../CRC16.c

    您是否看到过我的手动计算? 您为什么用第一个数据字提取OR初始值? 我认为我们必须将初始化值放在移位寄存器中,当最高位为“1”时,与其它数据字节一样,对Poly执行XOR。 我弄错了吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您是否看到过我的手动计算? 您为什么用第一个数据字提取OR初始值? 我认为我们必须将初始化值放在移位寄存器中,当最高位为“1”时,与其它数据字节一样,对Poly执行XOR。 我错了吗?[/QUOT]

    您可以将原始值或初始值视为先前CRC计算的结果,并且您将从该点继续计算。 如果您这样想,则应该用低字节0x41AF (C代码的形式为0x41AF,而不是0xAF41)来XOR 0xFFFF的低字节0x41AF (您的C代码的形式为0x41AF,而不是0xAF41),执行CRC,移动结果,然后用高字节0x41AF将其作为XOR。 并完成整个流程。 我在下面两张图片中做了这件事。  

    此表驱动型实施的灵感来自  

    这是一篇很长的文章,但在我所有的搜索中,这是关于这个主题的最好的文献。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的。 谢谢。 我很高兴我们阅读了同样 的文献。

    我有数据,例如0x31.3233万343536373839...,34.3536万,我37.3839万我想为其计算CRC。 如果我使用示例中的VCU2,我必须写入数组

    静态连接uint16_t testInput[NWORDS]=

    0x3231,0x3433,0x3635,0x3837,0x0039,
    };

    并使用"成员"  

    crc.parity = crc_parity_偶 数;

    这意味着我们先计算0x31,然后计算 0x32,0x33等。 对吧? 这就是为什么我在 "CRC16.c"中的数组中写入0x41AF,而不是 0xAF41 (0xAF41 -真实数据)。 如果我使用init = 0x0000为该数据(0xAF41)手动计算CRC (第一个帖子中的图片),使用VCU2 (但我必须写入0x41AF),使用CRC C代码函数(我们稍后将讨论)或使用在线CRC计算器之一(例如,下图中的此计算器) 我将得到相同的结果- 0x1C73。

    如果我使用  init = 0xFFFF计算0xAF41的CRC,结果将是:

    -用于手动计算- 0x1C57;

    -用于VCU2,在线计算器和 CRC C代码函数- 0x9C7E。

    我已经在第一篇文章中写过这方面的内容。

    现在,让我们来谈谈 CRC C代码函数以及解释CRC的文档,该文档由 Ross N. Williams编写。

    在Internet上,我找到 了一个CRC C代码函数(参见文件“CRC_Functions.c”)。

    e2e.ti.com/.../CRC_5F00_functions.c

    在"CRC_Functions.c"中有函数"MakeCRC16Table"和函数"GetCRC16"。 如果你 仔细 检查 你会发现  

    "CRC = crc16Table[((CRC >> 8)^* buf++)和0xFF]^(CRC << 8);"

    与相同

    "同时(len-) r =(r<<(8))^ t[(r >> 24)^*p+];"

    在威廉 姆斯的文档中,他们计算的是32位数据块,而不是 “GetCRC16”中的16位数据块。 这就是为什么我们使用">>24"而不是">>8"的原因。

      在威廉姆斯的文件中,该行旁边是下一个注释:

    Williams写道,我们不能以这种方式将算法用于"init"而不是0x0000,而 是用于CRC C代码函数 "GetCRC16",在线CRC计算器和(我认为) VCU2执行此操作! (顺便提一下,对于在线CRC计算器,有一个关于此情况的解释-"在移位寄存器中使用零以外的初始值时,8.6 的结果不正确。" -   )

    如果我们检查 Williams在"while (len--) r =(r<8)^ t[(r>> 24)^*p+]"上方的文档,我们将找到使用任何初始值进行正确计算的算法:

    我已 将 "GetCRC16"函数更改为此算法(请参见  "CRC_Functions.c"中的"GetCRC16_P"),并将其用于计算我的0xAF41的CRC,结果为 0x1C57。 此值与手动CRC计算相同!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉回复延迟,我不得不再次阅读William的文档,因为已经有一段时间了。 但在第10部分,在你张贴的片段之后,他说

    "标题:如果寄存器的初始值为零,则循环的前四次迭代将具有从右侧移动消息前四个字节的唯一效果。 这是因为前32个控制位都是零,所以没有任何东西被XORed到寄存器中。 即使初始值不是零,算法的前4个字节迭代也只会将消息的前4个字节移动到寄存器中,然后用某个常量值对它们进行XORing (这是寄存器初始值的函数)。

    这些事实与XOR属性相结合

    (A异或B)异或C = A异或(B异或C)

    意味着消息字节实际上无需经过寄存器的W/4字节。 相反,它们可以在用于对查找表进行索引之前以XORD格式插入到顶部字节中。 这将导致算法的以下修改版本。

     

    +----------- <消息(非增强)
    |
    五 3 2 1 0字节
    | --------------------++
    XOR---<|||||
    | --------------------++
    | ^
    | |
    | XOR
    | |
    | 0++------------++ 算法
    五 --------------------++ -------------------
    | --------------------++ 1.将寄存器向左移动
    | --------------------++ 一个字节,读入新的
    | --------------------++ 消息字节。
    | --------------------++ 2. XOR刚旋转的顶部字节
    | --------------------++ 从注册到
    +----------- >>------------+ 生成的下一个消息字节
    --------------------++ 索引到表([LD] 0255)。
    --------------------++ 3.将表值提取到中
    --------------------++ 注册。
    --------------------++ 4.转至1增强型IFF
    255++------------++ 消息字节。 


    ....

    这是一个相同的算法,将产生相同的结果。 C代码如下所示:

    r=0;while (len--) r =(r<8)^ t[(r >> 24)^*p+];

    是您可能在当前表驱动的CRC实现中找到的代码。 为了便于携带,一些FF掩模可能需要在这里和那里进行AND运算,但基本上,上面的循环就是它。 我们将其称为直接表算法。"

    此外,从您发布的链接 :http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html#ch86

    "逐位执行CRC计算时,这对移位寄存器的初始值意味着什么,比如顶部的笔和纸张方法? 答案:必须使用第一个输入字节的初始值'XORed'初始化寄存器。 对于CRC-16,初始值必须用XORed和前两个输入字节,对于CRC-32,则用前四个输入字节,依此类推。"

     

    这意味着您实际上正在计算0xFFFF ^ 0x41AF = 0xBE50的CRC

      CRC (0xBE50)= 0x6381

      最终结果= 0x6381 ^ 0xFFFF = 0x97CE

    并且不是初始值为零的CRC 0x41AFFFFF。 从我所读到的(非零)初始CRC寄存器值的全部要点是捕获消息中的前导零,即为前导消息零提供非零CRC。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    好的。 非常感谢您的解释。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    Aleksey,

    如果问题已解决,请关闭此线程。