#SOLVED - MODBUSRTU 模式CRC 计算......有什么问题?这是 DPS5020 用户手册的印刷错误吗?

问题描述

我是意大利人,很抱歉我的英语不好。 我正在分析DPS5020电源模块使用的MODBUS协议(rs232 com口),无法理解RTU模式下的CRC计算方法(第3页)https://cloud.kyme32.ro/ftp_backup/DPS5020%20PC%20Software(2017.11.04)/DPS5020%20CNC%20Communication%20%20Protocol%20V1.2.pdf。 在第 4 页上发送字节 1、3、0、2、0、2 的第一个示例中,指示值 CRC = 65CB(十六进制)(交换了 2 个字节)。 我也在网上尝试了几个 CRC 计算器,但找不到正确的值。 我也做了一个计算和位正确旋转的分步图,但值不返回给我。 是否需要使用帧(6)的所有字节进行计算还是仅使用数据值(4)?我两个都试过都没有成功... 能否请您放一张关于如何完成计算和返回值的小图(16位xor与A001值,向右旋转是/否......等)? 我知道最后你必须在它们之间交换 2 个字节,但无论如何单个值都不会返回给我。 或者它只是手册的印刷错误? 我真的很沮丧。非常感谢。

#解决 DPS5020 文档(通信协议)中的错误解释:该文档指出应该在位右移之后而不是 BEFORE 之后检查 LSB !!!!!!

错误的解释

  1. 在 CRC 生成期间,每个八位字符都与寄存器的内容异或。
  2. 结果向最低有效位 (LSB) 方向移动,并在最高有效位 (MSB) 的位置插入零。
  3. 提取并检查 LSB。
  4. 如果 LSB 是 1,则寄存器的异或 (XOR) 发生在一个固定的预设值。
  5. 如果 LSB 为 0,则不会发生异或 (XOR)。

合理解释

  1. 在 CRC 生成期间,每个八位字符都与寄存器的内容异或。
  2. 提取并检查 LSB(我的神奇之处)。
  3. 结果向最低有效位 (LSB) 方向移动,并在最高有效位 (MSB) 的位置插入零。
  4. 如果之前提取的 LSB(我的魔术位)是 1,则寄存器的异或 (XOR) 会以固定的预设值发生。
  5. 如果之前提取的 LSB(我的魔术位)是 0,则不会发生异或 (XOR)。

非常感谢 Mark Adler 的支持

解决方法

帧中的所有字节都用于 CRC 计算。

这是 CRC 的 C 实现,它应该可以回答您关于究竟要移位什么和异或何时移位的问题:

#include <stddef.h>
#include <stdint.h>

uint16_t crc16modbus_bit(uint16_t crc,void const *mem,size_t len) {
    unsigned char const *data = mem;
    if (data == NULL)
        return 0xffff;
    for (size_t i = 0; i < len; i++) {
        crc ^= data[i];
        for (unsigned k = 0; k < 8; k++) {
            crc = crc & 1 ? (crc >> 1) ^ 0xa001 : crc >> 1;
        }
    }
    return crc;
}

(当调用 mem 等于 NULL 时返回初始 CRC 值。)