You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Modbus RTU CRC计算异常:PIC程序结果与在线模拟器不符

排查Modbus CRC计算结果不符的问题

我帮你梳理下这段代码里的问题,你现在遇到的CRC结果和在线模拟器对不上的情况,大概率是核心逻辑缺失和细节处理不到位导致的,咱们一步步来修正:

原代码里的关键问题

  • 核心移位判断逻辑未完成:你代码里的if...后面没写完,这是Modbus CRC计算的核心步骤——每次移位后如果最低位是1,必须异或多项式,这部分缺失肯定会导致结果错误。
  • 固定循环次数为14:Modbus CRC是根据传入的消息长度来计算的,硬写14次只会适配特定长度的帧,大部分场景下结果都会错。
  • 冗余变量干扰:代码里定义了data[14]但没用到,容易混淆逻辑,建议删掉。
  • 字节序处理缺失:最后输出CRC时没考虑Modbus协议的字节序要求(低字节在前),这也是很多人和在线工具对不上的常见原因。

修正后的完整代码

void CalculateModbusCRC(unsigned char *msg, unsigned int msgLen, unsigned char *out) {
    unsigned int crc = 0xFFFF; // Modbus CRC-16的固定初始值
    const unsigned int poly = 0xA001; // 标准Modbus CRC多项式(0x8005的位反转)

    // 遍历消息的每个字节
    for (unsigned int i = 0; i < msgLen; i++) {
        crc ^= msg[i]; // 当前字节与CRC寄存器先异或

        // 处理当前字节的每一位
        for (unsigned int j = 0; j < 8; j++) {
            // 检查CRC寄存器的最低位是否为1
            if (crc & 0x0001) {
                crc >>= 1; // 右移一位
                crc ^= poly; // 最低位为1时,异或多项式
            } else {
                crc >>= 1; // 最低位为0时,直接右移
            }
        }
    }

    // Modbus协议要求CRC低字节在前,高字节在后
    out[0] = (unsigned char)(crc & 0xFF); // 提取CRC的低8位
    out[1] = (unsigned char)(crc >> 8);   // 提取CRC的高8位
}

关键细节说明

  1. 消息长度传入:现在函数需要你传入消息的实际长度msgLen,这样不管是6字节的读寄存器帧还是更长的帧,都能正确计算。
  2. 多项式选择:0xA001是Modbus专用的CRC-16多项式,它是标准CRC多项式0x8005的位反转,因为Modbus采用反向CRC算法,必须用这个值才能和在线工具匹配。
  3. 字节序处理:在线模拟器输出的CRC通常是低字节在前的格式(比如测试帧0x01 0x03 0x00 0x00 0x00 0x01的正确CRC是0x84 0x0A),所以我们把CRC的低8位放在输出数组的第一个位置,高8位放第二个位置。

你可以用上面的测试帧来验证修正后的代码,应该就能和在线模拟器的结果一致了。

内容的提问来源于stack exchange,提问作者user7331387

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:00:47