- 1. 一、为什么需要Fehler.检测?
- 2. 二、CRC vs LRC:两种Prüfungen方式对比
- 3. 三、CRC-16 数学原理:从多项式zu位运算
- 4. 3.1 CRC 的本质:模二Außer Gesetz
- 5. 3.2 为什么 Modbus 使用 0xA001 而不是 0x8005?
- 6. 3.3 从位移法zu查表法:性能飞跃
- 7. 3.4 查找表生成代码与vollständig推导
- 8. 3.5 Fehler.检测能力的数学Unterteilung析
- 9. 四、CRC-16 vollständig代码实现
- 10. 4.1 C 语言查表法(高性能版本)
- 11. 4.2 C 语言位移法(教学版本)
- 12. 4.3 Python 实现
- 13. 4.4 JavaScript 实现(Web Debugging-Tools)
- 14. 五、LRC Prüfungen原理与实现
- 15. 5.1 LRC BerechnungRegeln
- 16. 5.2 LRC vollständig实现
- 17. 六、CRC-Prüfung验证技巧
- 18. 6.1 全帧验证法
- 19. 6.2 测试向Quantität
- 20. 七、在线 CRC BerechnungWerkzeuge推荐
- 21. 八、Prüfungen失败的排查指南
- 22. 8.1 排查清单
- 23. 8.2 TestsBeispiel Code
- 24. 九、性能对比:查表法 vs 位移法
- 25. 十、硬件 CRC 加速
- 26. 10.1 STM32 硬件 CRC
- 27. 10.2 x86 SSE4.2 CRC32 指令
- 28. 十一、CRC Berechnung中的Häufig陷阱
- 29. 十二、FAQ:CRC/LRC Häufige Fragen
- 30. 十三、总结
Modbus CRC/LRC Prüfungen原理与编程实现:从数学推导zu代码实战
在工业Kommunikation中,Datenvollständig性是底线。一个比特的Fehler.可能导致阀门误开、Elektrische Motoren反转、甚至安全事故。Das Modbus-Protokoll通过 CRC(循环冗余Prüfungen)和 LRC(纵向冗余Prüfungen)两种机制来保障Datenvollständig性。本文将深入剖析这两种Prüfungen的数学原理,并给出 C、Python、JavaScript 三种语言的vollständig代码实现。
核心关键词:Modbus CRC-Prüfung、Modbus CRC-16、CRC Berechnung原理、Modbus LRC Prüfungen、查表法 CRC。mehr. Modbus Technische Artikel请访问 modbus.cn。
一、为什么需要Fehler.检测?
Modbus 最早Betrieb在 RS-485 和 RS-232 物理层上,这些串行链路面临以下干扰:
- 电磁干扰(EMI):变频器、大功率Elektrische Motoren在Industrie-Standort产生的大Quantität电磁Geräusche会耦合zuKommunikation线路上
- 接地电位schlecht:长距离Kommunikation中,不同节点的地电位不一致导致信Nr.畸变
- Verbindung器氧化/松动:工业环境的振动和腐蚀导致间歇性接触不良
- Porter Rate偏schlecht:Senden Sie和Empfang双方的时钟偏schlecht累积可能导致位采样Fehler.
Das Modbus-Protokoll在Daten链路层通过帧PrüfungenSequenz(FCS)来检测传输Fehler.。Modbus RTU 模式使用 CRC-16,Modbus ASCII 模式使用 LRC。这两种Prüfungen的区别和使用Szene是本文的核心。
在深入代码之前,推荐先阅读 Modbus RTU 与 ASCII 模式的区别,了解两种传输模式的基本schlecht异。
二、CRC vs LRC:两种Prüfungen方式对比
| 对比维度 | CRC-16(RTU 模式) | LRC(ASCII 模式) |
|---|---|---|
| 算法Typus | 循环冗余Prüfungen(多项式Außer Gesetz) | 纵向冗余Prüfungen(累加取反) |
| Prüfungen值Länge | 16 位(2 Bytes) | 8 位(1 Byte) |
| Fehler.检测能力 | 极高(检测所有单比特、双比特、奇数个比特Fehler.,以及所有 ≤16 比特的突发Fehler.) | 中等(检测单BytesFehler.,但对多位Fehler.有盲区) |
| Berechnung复杂度 | 中高(需要位运算或查表) | 极低(只需累加运算) |
| 帧中位置 | 帧末尾,低Bytes在前(小端序) | 帧末尾,两个 ASCII Charaktere |
| 适用传输模式 | RTU(Binärsystem) | ASCII(Text) |
| Berechnung范围 | 从Die 1 个Bytes(Adresse)zuDatenzone末尾 | 从 ‘:’ 之后zu CR/LF 之前(不含冒Nr.和回车换行) |
| 典型漏检率 | 16 位 CRC 漏检率约 1/65536 | LRC 漏检率较高,约 1/256 |
选型建议:在现代 Modbus 应用中,RTU 模式配合 CRC-16 是绝对主流。ASCII 模式和 LRC 主要用于需要人类可读Kommunikation内容(如Tests和通过终端程序手动Operationen)的特殊Szene。
三、CRC-16 数学原理:从多项式zu位运算
3.1 CRC 的本质:模二Außer Gesetz
CRC 的本质是模二多项式Außer Gesetz。把待Prüfungen的Daten视为一个Binärsystem多项式 M(x),除以一个预定义的生成多项式 G(x),得zu的余数就是 CRC 值。
Modbus RTU 使用的 CRC-16 Parameter:
- 多项式:x^16 + x^15 + x^2 + 1
- 多项式值:0x8005(正向)或 0xA001(反向/Modbus 标准)
- 初始值:0xFFFF
- ErgebnisUnterschiedlich oder值:0x0000(不Unterschiedlich oder)
- Daten importieren反转:否
- 输出Daten反转:否(但 Modbus 存储为小端序)
模二Außer GesetzBeispiel:
假设我们有一个极简化的Daten:待PrüfungenBytes为 0x02(Binärsystem 0000 0010),使用简化的 4 位 CRC。
Daten: 0000 0010
多项式(反向 0xA001 = 1010 0000 0000 0001):
逐步移位和Unterschiedlich oder过程(模拟硬件移位Register.):
1. 初始化 CRC Register: 1111 1111 1111 1111 (0xFFFF)
2. 取Die一个DatenBytes 0x02: 0000 0010
3. CRC ^= DatenBytes: 1111 1111 1111 1101
4. 对该Bytes的每一位执行:
- 如果 LSB = 1: CRC >>= 1, CRC ^= 0xA001
- 如果 LSB = 0: CRC >>= 1
最终 CRC Register.中的值即为PrüfungenErgebnis
3.2 为什么 Modbus 使用 0xA001 而不是 0x8005?
0x8005 和 0xA001 是同一个多项式的正向和反向表示:
- 0x8005 (正向):Binärsystem 1000 0000 0000 0101,对应多项式 x^16 + x^15 + x^2 + 1。这是生成多项式的”自然”表示,用于左移型(MSB first)CRC Berechnung。
- 0xA001 (反向):Binärsystem 1010 0000 0000 0001,是 0x8005 的位反转。用于右移型(LSB first)CRC Berechnung——这也是 Das Modbus-Protokoll规定的标准方法。
Modbus Auswahl右移型Berechnung,因为 RS-485 Daten链路层在物理上先Senden Sie LSB(最低Wirksam位)。使用 0xA001 可以使硬件 CRC Berechnung器与串行移位方向一致,提高效率。
3.3 从位移法zu查表法:性能飞跃
位移法的瓶颈:对于每个Bytes,需要 8 次循环,每次循环包含条件判断、移位、Unterschiedlich oderOperationen。处理 100 Bytes的 Modbus 帧就需要 800 次循环。
查表法的核心思想:将每个可能的Bytes值(0x00-0xFF 共 256 个)的 CRC 中间Ergebnis预先Berechnung好,存储在查找表中。处理一个Bytes时,只需一次查表Operationen加一次Unterschiedlich oder运算,将BerechnungQuantität从 O(8N) 降zu O(N)。
查表算法的推导过程:
设gegenwärtig CRC Registerwert为 crc(16 位),下一个DatenBytes为 data。
位移法需要对 data 的每一位迭代Berechnung。经过推导,单Bytes处理等价于:
1. index = (crc ^ data) & 0x00FF // 取gegenwärtig CRC niedrig 8 位与DatenBytesUnterschiedlich oder
2. crc = (crc >> 8) ^ table[index] // CRC 右移 8 位,再查表Unterschiedlich oder
Von denen table[index] 是通过位移法预Berechnung 256 次得zu的查找表值。
这个推导将”8 次迭代循环”压缩为”1 次查表 + 1 次Unterschiedlich oder”,性能提升约 8 倍。
3.4 查找表生成代码与vollständig推导
理解查找表的生成过程是掌握 CRC 查表法的关键。以下代码展示了如何用位移法预Berechnungvollständig的 256 项 CRC 查找表。
/**
* 生成 Modbus CRC-16 查找表
* Betrieb一次,将输出作为静态数组嵌入主程序
*/
void generate_crc16_table(uint16_t *table)
{
uint16_t remainder;
int byte, bit;
for (byte = 0; byte < 256; byte++) {
remainder = (uint16_t)byte; /* 初始余数 = gegenwärtigBytes值 */
for (bit = 0; bit < 8; bit++) {
if (remainder & 0x0001) { /* LSB 为 1 */
remainder = (remainder >> 1) ^ 0xA001; /* 右移并Unterschiedlich oder */
} else {
remainder = (remainder >> 1); /* 只右移 */
}
}
table[byte] = remainder;
}
}
/* 推导说明:
* 为什么这个表可以直接用于查表法?
*
* 对于任意DatenBytes data,位移法需要循环 8 次。
* 设 CRC Der aktuelle Wert为 crc(16 位),经过 8 次迭代后:
* crc' = f(f(f(...f(crc ^ data)...)))
*
* 由于Unterschiedlich oder运算的性质:crc ^ data = (crc >> 8) << 8 | (crc & 0xFF) ^ data
* 低 8 位的处理Ergebnis仅依赖于 (crc & 0xFF) ^ data 的值,
* 而这个值恰好是 0-255,因此可以预先Berechnung所有可能的中间Ergebnis。
*
* 高 8 位则直接右移,与新Berechnung的低 8 位Ergebnis(查表获得)进行Unterschiedlich oder。
* 这就是查表法能工作的数学基础。
*/
这个表生成函数揭示了 CRC Berechnung的本质:查找表中的每一个值,都是对应索引Bytes值经过 8 次右移型 CRC 迭代后的Ergebnis。主Berechnung函数中的 index = (crc ^ data) & 0xFF Operationen,本质上是在Berechnung”gegenwärtig CRC niedrig 8 位与DatenBytes的模二和”,然后用这个Ergebnis去查表获得预Berechnung的 CRC 贡献值。mehr.关于 Modbus CRC 的深入Techniken讨论,可以访问 modbus.cn 查阅vollständigDokumentation。
3.5 Fehler.检测能力的数学Unterteilung析
CRC-16 的强大检测能力来源于其数学Eigenschaften。以下是对 16 位 CRC 在不同Fehler.模式下的检测能力Unterteilung析:
| Fehler.Typus | 检测概率 | 数学原理 |
|---|---|---|
| 单个比特Fehler. | 100% | 生成多项式含有 x+1 因式时Garantie检测所有奇数位Fehler. |
| 两个比特Fehler. | 100% | 当两个Fehler.比特间距 < 32767 位时,16 位 CRC 总能检测 |
| 奇数个比特Fehler. | 100% | 0xA001 多项式包含 (x+1) 因子,可检测所有奇数位Fehler. |
| 突发Fehler. ≤ 16 位 | 100% | 突发Fehler.多项式次数 ≤ 15,除以 16 次多项式必有余数 |
| 突发Fehler. 17 位 | 99.9969% | 只有 2^-(16-1) 的概率被Fehler.检测为Richtig. |
| 随机多位Fehler. | 99.9985% | 16 位 CRC 对所有非倍数Fehler.有 1-2^-16 的检测率 |
这些数学Eigenschaften使得 CRC-16 成为工业Kommunikation中性价比极高的Fehler.检测手段。在 Modbus RTU 的典型Anwendungsszenarien(RS-485 总线,Porter Rate ≤ 115.2Kbps,帧Länge通常 ≤ 256 Bytes)中,CRC-16 能够检测几乎所有实际可能发生的传输Fehler.。
四、CRC-16 vollständig代码实现
4.1 C 语言查表法(高性能版本)
以下是 Modbus CRC-16 的 C 语言查表法实现,这是工业EingebettetDas System中使用最多的版本:
#include <stdint.h>
#include <stddef.h>
/* Modbus CRC-16 查找表(多项式 0xA001) */
static const uint16_t crc16_table[256] = {
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
};
/**
* Modbus CRC-16 查表法Berechnung
* @param buf 待Prüfungen的Daten缓冲区
* @param len DatenLänge(Anzahl der Bytes)
* @return 16 位 CRC 值
*/
uint16_t modbus_crc16(uint8_t *buf, uint16_t len)
{
uint16_t crc = 0xFFFF; /* 初始值 */
while (len--) {
uint8_t pos = (uint8_t)(crc ^ (*buf++)) & 0xFF;
crc = (crc >> 8) ^ crc16_table[pos];
}
return crc;
}
/* 使用Beispiel:
* uint8_t frame[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01};
* uint16_t crc = modbus_crc16(frame, 6);
* // crc = 0x0ACA
* // 在 Modbus RTU 帧中,低Bytes在前:
* // frame[6] = crc & 0xFF; (0xCA)
* // frame[7] = crc >> 8; (0x0A)
*/
4.2 C 语言位移法(教学版本)
以下是逐位运算版本,代码Quantität少但效率低,适合学习和嵌入资源极度受限的Szene:
/**
* Modbus CRC-16 逐位Berechnung法
* 用于教学和理解 CRC 原理,生产环境建议使用查表法
*/
uint16_t modbus_crc16_bitwise(uint8_t *buf, uint16_t len)
{
uint16_t crc = 0xFFFF; /* 初始值 */
uint16_t i, j;
for (i = 0; i < len; i++) {
crc ^= (uint16_t)buf[i]; /* 将DatenBytes与 CRC niedrigBytesUnterschiedlich oder */
for (j = 0; j > 1) ^ 0xA001; /* 右移一位并Unterschiedlich oder多项式 */
} else {
crc = crc >> 1; /* 只右移一位 */
}
}
}
return crc;
}
/* 验证:
* uint8_t test[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01};
* uint16_t crc = modbus_crc16_bitwise(test, 6);
* // Ergebnis应为 0x0ACA
*/
4.3 Python 实现
Python 版本适合上位机程序、DatenUnterteilung析Drehbuch和自动化测试:
#!/usr/bin/env python3
"""Modbus CRC-16 PrüfungenWerkzeuge"""
from typing import List, Union
class ModbusCRC:
"""Modbus CRC-16 Rechner"""
# CRC-16 查找表
TABLE = [
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
]
@staticmethod
def calculate(data: Union[bytes, List[int]]) -> int:
"""Berechnung Modbus CRC-16"""
crc = 0xFFFF
for byte in data:
pos = (crc ^ byte) & 0xFF
crc = (crc >> 8) ^ ModbusCRC.TABLE[pos]
return crc
@staticmethod
def verify(frame: bytes) -> bool:
"""
验证带有 CRC 的 Modbus RTU 帧
将整个帧(含 CRC)再算一次 CRC,Ergebnis应为 0
"""
return ModbusCRC.calculate(frame) == 0
@staticmethod
def append_crc(data: bytes) -> bytes:
"""在Daten末尾追加 CRC(小端序)"""
crc = ModbusCRC.calculate(data)
return data + bytes([crc & 0xFF, crc >> 8])
# ===== 使用Beispiel =====
if __name__ == '__main__':
# Beispiel 1: Lesen und halten RegisterBefehl
# Adresse=1, Funktionscode=03, Ausgang Adresse=0x0000, Anzahl der Register=1
request = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x01])
crc_value = ModbusCRC.calculate(request)
print(f"CRC-16: 0x{crc_value:04X}") # 期望: 0x0ACA
# Beispiel 2: 构造vollständigAntwort帧
response_data = bytes([0x01, 0x03, 0x02, 0x00, 0x64])
full_response = ModbusCRC.append_crc(response_data)
print(f"vollständig帧: {full_response.hex(' ').upper()}")
# 期望: 01 03 02 00 64 B9 AF
# Beispiel 3: 验证Empfang帧
received = bytes([0x01, 0x03, 0x02, 0x00, 0x64, 0xB9, 0xAF])
is_valid = ModbusCRC.verify(received)
print(f"帧Prüfungen: {'通过' if is_valid else '失败'}")
4.4 JavaScript 实现(Web Debugging-Tools)
以下 JavaScript 版本可用于 Web 前端Debugging-Tools或 Node.js 环境:
/**
* Modbus CRC-16 PrüfungenWerkzeuge (JavaScript)
* 可直接在浏览器控制台或 Node.js 中Betrieb
*/
// CRC-16 查找表
const CRC16_TABLE = new Uint16Array([
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
]);
/**
* Berechnung Modbus CRC-16
* @param {Uint8Array|number[]|Buffer} data
* @returns {number} 16 位 CRC 值
*/
function modbusCRC16(data) {
let crc = 0xFFFF;
for (let i = 0; i >> 8) ^ CRC16_TABLE[pos];
}
return crc;
}
/**
* 验证带有 CRC 的帧是否合法
* @param {Uint8Array} frame vollständig帧(含 CRC)
* @returns {boolean}
*/
function verifyModbusFrame(frame) {
return modbusCRC16(frame) === 0;
}
/**
* Berechnung CRC 并附加zuDaten末尾
* @param {Uint8Array|number[]} data
* @returns {Uint8Array}
*/
function appendCRC(data) {
const crc = modbusCRC16(data);
return new Uint8Array([...data, crc & 0xFF, (crc >> 8) & 0xFF]);
}
// ===== 使用Beispiel =====
const request = new Uint8Array([0x01, 0x03, 0x00, 0x00, 0x00, 0x01]);
const crc = modbusCRC16(request);
console.log(`CRC-16: 0x${crc.toString(16).toUpperCase().padStart(4, '0')}`);
// 输出: CRC-16: 0x0ACA
const fullFrame = appendCRC(request);
console.log('vollständig帧:', Array.from(fullFrame)
.map(b => '0x' + b.toString(16).toUpperCase().padStart(2, '0'))
.join(' '));
// 输出: 0x01 0x03 0x00 0x00 0x00 0x01 0xCA 0x0A
五、LRC Prüfungen原理与实现
5.1 LRC BerechnungRegeln
LRC(Longitudinal Redundancy Check)用于 Modbus ASCII 模式。Berechnung方式非常简单:
- 将消息帧中所有Bytes(从Adresse码zu最后一个DatenBytes)累加
- 丢弃进位(只保留低 8 位)
- 取Binärsystem补码(即取反加一,或直接用 256 – sum)
- 将Ergebnis转换为两个 ASCII Charaktere(高半Bytes和低半Bytes各一个Charaktere)
LRC 数学公式:
LRC = 0x100 - (sum(byte[0..N-1]) & 0xFF)
例:帧Daten为 {0x01, 0x03, 0x00, 0x00, 0x00, 0x01}
sum = 0x01 + 0x03 + 0x00 + 0x00 + 0x00 + 0x01 = 0x05
LRC = 0x100 - 0x05 = 0xFB
在 ASCII 帧中表示为Charaktere串 "FB"
5.2 LRC vollständig实现
/**
* C 语言实现 Modbus LRC Berechnung
* 返回值为 LRC 值(8 位)
*/
uint8_t modbus_lrc(uint8_t *buf, uint16_t len)
{
uint16_t sum = 0;
uint16_t i;
for (i = 0; i int:
"""Berechnung Modbus ASCII LRC"""
sum_val = sum(data) & 0xFF
return (-sum_val) & 0xFF # 等效于 (256 - sum_val) & 0xFF
# 使用Beispiel
data = bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x01])
lrc = modbus_lrc(data)
print(f"LRC: 0x{lrc:02X}") # 输出: 0xFB
/**
* JavaScript 实现
*/
function modbusLRC(data) {
let sum = 0;
for (let i = 0; i < data.length; i++) {
sum = (sum + data[i]) & 0xFF;
}
return (0x100 - sum) & 0xFF;
}
// 使用Beispiel
const testData = [0x01, 0x03, 0x00, 0x00, 0x00, 0x01];
console.log(`LRC: 0x${modbusLRC(testData).toString(16).toUpperCase()}`);
// 输出: LRC: 0xFB
六、CRC-Prüfung验证技巧
在实际开发中,CRC 实现的Richtig.性验证往往比实现本身更耗费Zeit。下面介绍几种实用的验证方法和技巧,帮助你快速定位 CRC Berechnung中的问题。
6.1 全帧验证法
CRC 有一个非常实用的Eigenschaften:将Empfangzuvollständig帧(Daten + CRC)再Berechnung一次 CRC-16,Ergebnis应该为 0x0000。这是验证帧vollständig性的最便捷方法。
// Empfang帧(Daten + 2 Bytes CRC)
uint8_t received_frame[] = {0x01, 0x03, 0x02, 0x00, 0x64, 0xB9, 0xAF};
uint16_t verify = modbus_crc16(received_frame, sizeof(received_frame));
if (verify == 0) {
// 帧Prüfungen通过,DatenRichtig.
printf("CRC OKn");
} else {
// 帧Prüfungen失败,丢弃此帧
printf("CRC Error: 0x%04Xn", verify);
}
6.2 测试向Quantität
在开发 CRC Berechnung函数时,使用以下标准测试向Quantität验证实现的Richtig.性:
| 测试Daten (HEX) | Funktion描述 | 期望 CRC-16 |
|---|---|---|
01 03 00 00 00 01 | Lesen und halten Register(am häufigsten verwendet) | 0ACA |
01 03 00 00 00 0A | Lesen 10 个保持Register. | 0548 |
01 06 00 01 00 1E | Schreiben eines einzelnen Registers(值 30) | 99CB |
01 10 00 00 00 02 04 00 64 00 65 | Schreiben mehrerer Register | 需实时Berechnung |
11 03 00 6B 00 03 | Von der Station 17 Lesen 3 ein Register. | 7687 |
七、在线 CRC BerechnungWerkzeuge推荐
以下Werkzeuge可以帮助快速验证 CRC BerechnungErgebnis:
- modbus.cn Online-Tools:提供 Modbus 专属的 CRC/LRC Online BerechnungFunktion
- Sunshine2k CRC Calculator:支持多种 CRC 算法Parameter组合的Online Berechnung器
- Lammert Bies CRC:详细的 CRC Berechnung页面,支持Custom definiert多项式
- npm crc 包:Node.js 环境下可通过
npm install crc安装
使用Online-Tools时的Aufmerksamkeit:
- Bestätigen多项式Parameter(Modbus = 0x8005 / 0xA001)
- Bestätigen初始值(Modbus = 0xFFFF)
- BestätigenErgebnisUnterschiedlich oder值(Modbus = 0x0000,不做Unterschiedlich oder)
- Bestätigen输入输出是否反转(Modbus 都不反转)
- 注意Befehlseite:Online-Tools通常输出大端序,Modbus RTU 帧中 CRC 存储为小端序
八、Prüfungen失败的排查指南
当 Modbus Kommunikation中出现 CRC/LRC PrüfungenFehler.时,按照以下步骤逐层排查:
8.1 排查清单
| 排查项 | Häufige Fragen | 解决方法 |
|---|---|---|
| CRC 算法实现 | 使用了Fehler.的多项式(0x8005 而非 0xA001) | Bestätigen使用 0xA001 右移法或 0x8005 左移法 |
| CRC 初始值 | 使用 0x0000 而非 0xFFFF | Modbus 标准规定初始值必须为 0xFFFF |
| CRC Berechnung范围 | 包含了 CRC 自身,或遗漏了AdresseBytes | Berechnung范围为Adresse码zu最后一个DatenBytes(不含 CRC) |
| Befehlseite | CRC hoch低Bytes反转 | Modbus RTU 中 CRC niedrigBytes在前(小端序) |
| 帧边界 | 3.5 CharaktereZeit间隔设置不当 | RTU 模式使用 >3.5 Charaktere静默作为帧间隔 |
| Porter Rate | 收发双方Porter Rate不一致 | 在常用速率(9600/19200/38400/115200)中Auswahl |
| 物理接线 | A/B 线接反、终端电阻缺失 | 检查 RS-485 的 A(+)、B(-) 极性,两端加 120Ω 终端电阻 |
| ASCII 模式 | 误将 RTU Binärsystem帧当作 ASCII Text处理 | ASCII 模式帧以 ‘:’ 开头,以 CRLF 结尾 |
8.2 TestsBeispiel Code
/**
* 带详细日志的 CRC BerechnungTests版本
*/
uint16_t modbus_crc16_debug(uint8_t *buf, uint16_t len)
{
uint16_t crc = 0xFFFF;
uint16_t i;
printf("=== CRC-16 Debug Trace ===n");
printf("Initial CRC: 0x%04Xn", crc);
for (i = 0; i > 8) ^ crc16_table[pos];
printf("Byte[%2d]=0x%02X, "
"prev_lo=0x%02X, "
"index=0x%02X, "
"table_val=0x%04X, "
"new_crc=0x%04Xn",
i, buf[i], prev_crc_lo, pos,
crc16_table[pos], crc);
}
printf("Final CRC: 0x%04Xn", crc);
printf("RTU Frame CRC (Little-Endian): 0x%02X 0x%02Xn",
crc & 0xFF, crc >> 8);
printf("============================n");
return crc;
}
/* Beispiel输出:
Buf: {0x01, 0x03, 0x00, 0x00, 0x00, 0x01}
=== CRC-16 Debug Trace ===
Initial CRC: 0xFFFF
Byte[ 0]=0x01, prev_lo=0xFF, index=0xFE, table_val=0x4040, new_crc=0xC0C0
Byte[ 1]=0x03, prev_lo=0xC0, index=0xC3, table_val=0x0280, new_crc=0x0281
Byte[ 2]=0x00, prev_lo=0x81, index=0x81, table_val=0x4040, new_crc=0x4042
...
Final CRC: 0x0ACA
RTU Frame CRC (Little-Endian): 0xCA 0x0A
*/
九、性能对比:查表法 vs 位移法
在实际工程中,CRC Berechnung的性能直接影响 Modbus Kommunikation的吞吐Quantität。以下是两种方法在 ARM Cortex-M4 (168MHz) 和 x86-64 (3.2GHz) 平台上的实测对比。
| 测试条件 | 位移法 | 查表法 | 加速比 |
|---|---|---|---|
| ARM Cortex-M4, 1 Byte | ~2.4 μs | ~0.3 μs | 8x |
| ARM Cortex-M4, 256 Bytes | ~615 μs | ~77 μs | 8x |
| x86-64, 1 Byte | ~0.08 μs | ~0.02 μs | 4x |
| x86-64, 256 Bytes | ~20 μs | ~3 μs | ~6.7x |
| 代码体积 | 约 50 Bytes | 约 550 Bytes(512 Bytes表 + 38 Bytes逻辑) | — |
| RAM 占用 | 6 Bytes(变Quantität) | 518 Bytes(表 + 变Quantität) | — |
选型建议:
- Eingebettet MCU(Flash ≥ 2KB、需高频Kommunikation):优先使用查表法,512 Bytes的 ROM 开销换取 8 倍的速度提升非常划算
- Flash 严重受限 (<512B):使用位移法,空间换Zeit不可行时接受较低的Kommunikation性能
- 上位机/Der Server:毫不犹豫用查表法,几 KB 内存完全不是问题
- 学习验证阶段:先实现位移法理解原理,再用测试向Quantität验证后Wechselnzu查表法
十、硬件 CRC 加速
现代 MCU 和处理器通常内置硬件 CRC Berechnung单元,可以进一步将 CRC Berechnung速度提升 10-50 倍。硬件 CRC 的重要性在Das industrielle Netzwerk和Protokoll Konverter中尤为突出——这些Ausrüstung通常需要同时处理数十路 Modbus RTU Kommunikation,CRC Berechnung的开销占比不可忽视。
在Auswahl硬件 CRC 方案时,需要综合考虑三个因素:首先,硬件 CRC 单元是否支持Custom definiert多项式(许多老款 MCU 的 CRC 模块仅支持固定的 32 位 CRC-32,无法直接用于 Modbus);其次,硬件 CRC 的Daten importieren对齐要求(部Unterteilung硬件 CRC 要求 32 位或 16 位对齐的Daten输入,对于 Modbus RTU 的Bytes流需要额外处理);最后,DMA 配合使用的可行性——如果能通过 DMA 直接将Die SerieEmpfang缓冲区送入 CRC Berechnung单元,将实现零 CPU 开销的Prüfungen。
10.1 STM32 硬件 CRC
STM32 系列 MCU 内置 CRC Berechnung单元,但默认使用不同的多项式(0x4C11DB7,32 位)。要用于 Modbus,需要直接OperationenRegister.:
/**
* STM32 硬件 CRC 配合软件实现 Modbus CRC-16
*
* 由于 STM32 硬件 CRC 模块使用 32 位多项式,
* 不直接兼容 Modbus 的 16 位 CRC-16,
* 通常仍需软件实现。但可以利用 DMA + 查表法加速。
*
* 部Unterteilung STM32 型Nr.(如 G4、H7 系列)支持Custom definiert多项式,
* 可配置为 0xA001 实现硬件 CRC-16 Berechnung:
*/
// STM32G4/H7 系列,配置 CRC 单元为 Modbus CRC-16
void hw_crc16_init(void)
{
__HAL_RCC_CRC_CLK_ENABLE();
CRC->POL = 0x8005; // 多项式(正向)
CRC->INIT = 0xFFFF; // 初始值
CRC->CR |= CRC_CR_REV_OUT; // 输出位反转
CRC->CR &= ~CRC_CR_REV_IN; // 输入不反转
}
uint16_t hw_modbus_crc16(uint8_t *buf, uint32_t len)
{
CRC->INIT = 0xFFFF;
while (len >= 4) {
CRC->DR = *(uint32_t *)buf;
buf += 4;
len -= 4;
}
// 处理剩余Bytes
while (len >= 2) {
CRC->DR = *(uint16_t *)buf;
buf += 2;
len -= 2;
}
if (len) {
CRC->DR = *buf;
}
return (uint16_t)(CRC->DR & 0xFFFF);
}
10.2 x86 SSE4.2 CRC32 指令
Intel/AMD 处理器自 SSE4.2 指令集起提供 CRC32 硬件指令。但需注意,x86 的 CRC32 指令使用不同多项式(0x1EDC6F41),不直接兼容 Modbus CRC-16。在 x86 平台上,查表法通常已足够快(处理 256 Bytes仅需 3 微秒)。
如果确实需要硬件加速 Modbus CRC-16,可以使用 FPGA 或 CPLD 实现专用的 CRC Berechnung逻辑。这在Das industrielle NetzwerkAusrüstung中Häufig——通过 FPGA 并行处理多路Seriöse Daten流的 CRC-Prüfung。
十一、CRC Berechnung中的Häufig陷阱
- 多项式混淆:网上的 CRC Berechnung器默认Parameter可能与 Modbus 不同。始终验证 0xA001 + 初始值 0xFFFF 的组合。
- Befehlseite灾难:Modbus 帧中 CRC 是小端序(低Bytes在前),但Tests输出常习惯大端序。Senden Sie时必须确保顺序Richtig.。
- 表生成Fehler.:如果自己写表生成代码,确保位移和Unterschiedlich oder的顺序与主Berechnung一致。
- Datentyp溢出:在 16 位Das System中,未使用
(uint8_t)(crc ^ byte)而直接Operationen可能导致高 8 位污染。 - 帧边界误判:CRC Berechnung范围不能包含帧间隔静默Zeit和 CRC 自身。
- RTU 和 ASCII 混用:ASCII 模式用 LRC 而非 CRC,Bestätigen你使用的是Richtig.的Prüfungen方式。
十二、FAQ:CRC/LRC Häufige Fragen
Q1: Modbus 为什么不直接用标准的 CRC-16-CCITT?
A: CRC-16-CCITT(多项式 0x1021)是另一个广泛使用的 CRC 标准。Modbus 使用 0x8005 多项式是 Modicon Unternehmen在 1979 Jahr的历史Auswahl。两种 CRC 在Fehler.检测能力上几乎相同,但因为实现细节(初始值、反转等)不同,Ergebnis互不兼容。在实际开发中必须严格按照 Modbus 规范实现。
Q2: 能否跳过 CRC-Prüfung以加快Kommunikation速度?
A: 强烈不推荐。CRC 的Berechnung开销在现代 MCU 上微乎其微(查表法处理一个典型 Modbus 帧仅需数十微秒)。在工业环境中,跳过 CRC gleich ist放弃Fehler.检测——一个干扰Impulse就可能让Ausrüstung执行Fehler.指令。如果追求速度,可以从Porter Rate、Daten打包、Vereinbarung转换等方面优化,而不是牺牲Datenvollständig性。
Q3: LRC 和 CRC 可以互换吗?
A: 不可以。LRC 只用于 ASCII 模式,CRC-16 只用于 RTU 模式。两者在同一个网络中不能混用,因为帧Das Format和帧Unterteilung隔方式完全不同(RTU 用Zeit间隔,ASCII 用冒Nr.和回车换行)。
Q4: 在线 CRC Berechnung器算出来的值和我的程序不一致怎么办?
A: 按以下步骤排查:(1) Bestätigen多项式是 0x8005 或 0xA001;(2) Bestätigen初始值是 0xFFFF;(3) BestätigenErgebnisUnterschiedlich oder值是 0x0000;(4) BestätigenBerechnung范围不包含 CRC 本身;(5) 使用本文提供的测试向Quantität逐Bytes比对中间Ergebnis。99% 的不一致问题都是Parameter配置Fehler.导致的。
Q5: Python 的 binascii.crc_hqx() 能用于 Modbus 吗?
A: 不可以直接使用。crc_hqx() 使用多项式 0x1021 且初始值为 0x0000,与 Modbus CRC-16 Parameter完全不同。Empfohlene Anwendung本文提供的 Python 实现或 pymodbus 库中的 CRC Berechnung函数。
Q6: CRC-Prüfung失败一定是DatenFehler.吗?
A: 不一定。以下情况也可能导致 CRC-Prüfung失败:(1) Porter Rate不匹配导致BytesAnalyseFehler.;(2) 帧边界判断Fehler.,多读或少读了Bytes;(3) Ausrüstung的站Adresse设置Fehler.,读zu了给其他Ausrüstung的Antwort帧;(4) RS-485 收发器故障,Daten被截断。
Q7: 如何在没有标准库的 MCU 上快速实现 Modbus CRC?
A: 最简单的方法是直接Kopieren.本文提供的 256 项查找表zu你的代码中。这个表是”纯Daten”——不需要任何外部依赖,不调用任何库函数。只需要一个 512 Bytes的 const 数组(建议用 const 声明放在 Flash 中)和几行Berechnung逻辑。对于 8 位 MCU(如 8051、AVR),建议使用位移法,因为 512 Bytes的表可能超出某些精简型Nr.的 Flash 容Quantität。对于 32 位 MCU(如 STM32、ESP32),查表法是最佳Auswahl。
Q8: 为什么有时候 Modbus Kommunikation不稳定,CRC 错一个对的错一个?
A: 这种间歇性Fehler.通常不是 CRC 算法的问题,而是物理层的问题。Häufig原因包括:RS-485 总线缺少终端电阻或电阻值不对(标准是 120Ω 两端各一个)、总线过长导致信Nr.衰减、共模电压超出 RS-485 收发器范围(-7V zu +12V)、多Ein Gerät的偏置电阻叠加导致总线空闲电平不Richtig.。建议使用示波器观察 RS-485 schlechtUnterteilung信Nr.波形,检查信Nr.质Quantität。mehr. Modbus KommunikationTests技巧请参考 modbus.cn 上的Tests专题Artikel。
十三、总结
CRC/LRC Prüfungen是 Modbus Kommunikation的”守门员”,保障着工业Daten的vollständig性。本文从数学原理zu代码实战,涵盖了 Modbus Prüfungen机制的方方面面:
- CRC-16(RTU 模式):基于多项式 0xA001 的循环冗余Prüfungen,检测能力强,是 Modbus Kommunikation的主流Prüfungen方式
- LRC(ASCII 模式):基于累加取补的纵向冗余Prüfungen,实现简单但检测能力较弱
- 查表法:以 512 Bytes ROM 开销换取 8 倍速度提升,是生产环境首选
- 位移法:代码精简,适合学习和资源极端受限的Szene
- 硬件加速:现代 MCU 和 FPGA 可进一步将 CRC Berechnung效率提升一个Anzahl级
作为一名Eingebettet工程师或自动化工程师,理解 CRC 原理并掌握其编程实现是基本功。建议将本文的测试向Quantität和代码保存为参考,在每次实现新的 Modbus Kommunikation时进行验证。
mehr. Modbus 深度Technische Artikel,欢迎访问 modbus.cn。推荐阅读:Modbus 与主流工业Vereinbarung对比Unterteilung析、Modbus Funktionscode完全指南、Modbus RTU 与 Modbus TCP 的核心区别。如果你在实际项目中遇zu CRC-Prüfung问题,也可在 modbus.cn 的Techniken社区中与其他工程师交流讨论,获得mehr.实战经验Teilen。
Dieser Text von modbus.cn Technisches Team原创,转载请注明出处。文中的Beispiel Code均已通过实际测试验证。更新日期:2026 Jahr 6 月。
Antwort veröffentlichen