返回串口调试

技术知识库 & 调试文档 65 篇硬核手册

Web Serial Pro Multi-Module Offline Documentation Hub

主题 同步中 本地离线 知识库总览
ID: INDUSTRIAL-02 工业控制与高级协议 (Industrial Control)

Modbus CRC16 校验:查表法与移位法及串口调试对照

#Modbus CRC16 校验计算器#串行数据校验和计算#在线 16进制 校验和计算

长线 RS-485 上电机启停、变频器噪声容易造成 bit 翻转。Modbus RTU 强制使用 CRC16:对「地址 + 功能码 + 数据」整段计算 16 位冗余,附在帧尾;接收方重算不一致则 静默丢弃(多数从站不回异常)。现场「HEX 发了没应答」里,有相当一部分是 CRC 字节序或计算范围错了,不是 485 线断了。

必记三条 1. 多项式实现常用反射形式 0xA001(对应 0x8005)。 2. 初值 `0xFFFF`,对「除 CRC 外整帧」逐字节更新。 3. 结果 低字节先上线(little-endian):例如算得 0x0BC4,线上顺序是 C4 0B。 校验范围 不含 CRC 自身,也不含 Modbus ASCII 的 :\r\n(那是另一套 LRC)。

标准测试向量(务必写进单测) | 数据(HEX) | CRC 低→高 | 完整发送帧 | |---|---|---| | 01 03 00 00 00 02 | C4 0B | 01 03 00 00 00 02 C4 0B | | 01 06 00 01 00 03 | 自算核对 | 写单寄存器示例 | 你的 MCU / Python / JS 实现必须先过第一行向量,再谈查表优化。

移位法 vs 查表法 | 方法 | 优点 | 缺点 | 适用 | |---|---|---|---| | 移位法 | 代码短、无大表 | 高频帧时 CPU 忙 | 51 / 资源极紧 | | 查表法 | 每字节 O(1) | 约 512 字节表 | 从站 / 上位机主流 | 上位机与网页工具内部多为查表法;两端用 同一测试向量 对齐,比争论「谁的算法正宗」更有效。

串口现场对照(本站) 1. 打开 https://www.serialpro.top/ ,HEX 模式,波特率与从站一致(常见 9600 8N1)。 2. 发送完整帧:01 03 00 00 00 02 C4 0B(空格仅编辑用,勿把空格字节发出)。 3. 有正确应答 → CRC 与电气基本过关,再对寄存器表。 4. 无应答: - 先换回环/短线,排除 485 A/B、终端、供电; - 再自算 CRC:是否误成高字节在前 0B C4; - 是否把 CRC 算进了校验范围; - 是否多发了 \r\n(文本模式残留)。 5. 应答功能码变 83 等异常码:CRC 往往已对,问题在地址/寄存器映射。

实现检查清单 - [ ] 单测向量 01 03 00 00 00 02C4 0B - [ ] 线上顺序 CRC_L 然后 CRC_H - [ ] 异常应答帧同样带 CRC - [ ] 写多寄存器时「字节数」字段纳入 CRC 计算 - [ ] HEX 工具忽略空白;不要把空格 0x20 算进帧

和乱码、超时怎么分工 | 现象 | 先查 | |---|---| | HEX 噪声无结构 | 波特率 / 共地 / 485 电平 | | 帧结构像但从不回 | 地址、DE 方向、CRC | | 偶发 CRC 错 | 终端 120Ω、EMI、偏置 | | 固定错一字节 | 端序或漏算字段 | 把 CRC 在上下位机用同一套测例钉死,再谈复杂寄存器表——这是 Modbus 串口联调里 性价比最高 的一步。本站适合现场快速发标准帧;算法细节可在固件里对照本文向量。完整帧格式见《Modbus RTU 帧格式详解》。

// 快速高效的 Modbus CRC16 查表法 JavaScript 引擎
const CRC16_TABLE_HI = [
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  // ... 完整 256 字节的 CRC 计算预存表(在 utils.ts 中已被完整实现)
];

function calculateCRC16(buffer) {
  let crcHi = 0xFF;
  let crcLo = 0xFF;
  for (let i = 0; i < buffer.length; i++) {
    const idx = crcLo ^ buffer[i];
    crcLo = crcHi ^ CRC16_TABLE_HI[idx]; // 快速查表
    crcHi = CRC16_TABLE_LO[idx];
  }
  return (crcHi << 8) | crcLo; // 组装 16 位循环校验字
}
代码范例 (javascript)
// 快速高效的 Modbus CRC16 查表法 JavaScript 引擎
const CRC16_TABLE_HI = [
  0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  // ... 完整 256 字节的 CRC 计算预存表(在 utils.ts 中已被完整实现)
];

function calculateCRC16(buffer) {
  let crcHi = 0xFF;
  let crcLo = 0xFF;
  for (let i = 0; i < buffer.length; i++) {
    const idx = crcLo ^ buffer[i];
    crcLo = crcHi ^ CRC16_TABLE_HI[idx]; // 快速查表
    crcHi = CRC16_TABLE_LO[idx];
  }
  return (crcHi << 8) | crcLo; // 组装 16 位循环校验字
}