출 처 : Mod bus 중국 어 네트워크 (mod bus . cn) - 국내 선 도 적 인 Mod bus 통신 프로토 콜 기술 커뮤니티
Mod bus 통신 오류 탐 지 및 진단 : 패 리티 에서 예외 코 드에 이르 기까지 전체 시스템 · 작성 자 : Mod bus 기술 팀 · 게시 20 26 - 07 - 01
Mod bus 프로토 콜 의 오류 탐 지는 문자 레벨 의 패 리티 , 프레 임 레벨 의 L RC / CR C 및 응용 프로그램 레벨 의 예외 응답 코드 및 시간 초 과 메 커 니 즘 의 세 가지 수준 으로 나 뉘 어져 있습니다 .이 문서 에서는 각 탐 지 모 드의 작동 원 리 , 알고리즘 구현 (실 행 가능한 C / Python 코드 포함) 및 실제 디 버 깅 용 도를 하나 씩 해 체 하고 전체 예외 코드 빠른 체크 테이블 및 문제 해결 프로세 스를 제공합니다 . Mod bus CR C , L RC , 패 리티 , Mod bus 예외 코드 , Mod bus 오류 탐 지 , CR C 16 Mod bus .
在 RS-485 バス上传输一个 Modbus フレーム,就像在嘈杂的车间里喊话--喊出去的是 한 비트 뒤 집 어 온 도 판 독 값 이 25 ° C 에서 26 ° C 로 변경 되거나 밸 브 가 " 왜 움직 이지 않는 지 " 는 이유가 여기에 묻 혀 있습니다 .
Mod bus 는 1979 년 부터 계 층 적 오류 탐 지 메 커 니 즘 을 가지고 있습니다 : 각 문 자는 패 리티 를 사용하여 비트 오류 를 차단 하고 전체 프레 임 은 CR C (R TU 모 드) 또는 L RC (AS C II 모 드) 로 캡 슐 화 되며 응용 프로그램 계 층 은 예외 응답 코드를 통해 호스트 스테 이션 에 " 당신의 요청 에 문제가 있습니다 . " 라고 말합니다 .이 세 계 층 메 커 니 즘 은 시간 초 과 재 발 송 전략 과 함께 Mod bus 가 거의 50 년 동안 산업 현 장에서 살아남 을 수있는 신뢰 성의 기초 를 형성 합니다 .
솔직히 말 해서 , Mod bus 에 러 검 지는 암호화 수준 이 아닙니다 - CR C 16 은 변 조 에 저항 하지 않으며 L RC 는 연속 적인 짝 수 비트 오류 를 놓 칠 수 있습니다 .그러나 이러한 메 커 니 즘 은 96 00 b ps , 수십 미 터 RS - 48 5 버 스의 물리적 환경 에서는 충분 합니다 .그들의 가치 는 이론 적 완벽 함이 아니라 구현 의 단순 성과 낮은 계산 오 버 헤 드 입니다 - 8 비트 MC U 는 100 바 이트 미 만의 코 드로 CR C 16 계산 을 수행 할 수 있습니다 .
오류 탐 지를 위한 3 계 층 아 키 텍 처
Mod bus 직 렬 통신 에 대한 오류 탐 지는 위에서 아래 로 전체 통신 스 택 을 커 버 하는 세 가지 계 층 으로 나 뉘 어져 있습니다 .
응용 프로그램 계 층 : 예외 응답 코드 + 시간 초 과 재 전 송
↓
프레 임 레이 어 : CR C - 16 (R TU) 또는 L RC (AS C II)
↓
문자 레이 어 : 패 리티 (E ven / Odd / None)
文字层
フレーム层프레 임 검 사가 실패 하면 디 바 이스 에서 메시 지가 조용히 삭제 되고 어떤 내용 도 응답 하지 않습니다 .
アプリケーション層이러한 오류 는 예외 응답 코드를 통해 마스터 스테 이션 에 통 지 됩니다 .
세 계 층 은 자신의 역할을 수행 하지만 디 버 깅 을 할 때 엔지니 어는 응용 프로그램 계 층 의 예외 코드를 쉽게 볼 수 있으며 물리적 계 층 의 패 리티 오류 를 무시 합니다 - 패 리티 오류 는 장치 의 하드 웨어 수준 에서 삭제 되어 볼 수 없기 때문입니다 .
2) 문자 레이 어 : 패 리티
2. 1 원칙
패 리티 는 각 U ART 문자 프레 임 에 체크 비 트를 추가 하여 전체 프레 임 에서 "1 " 의 총 수가 홀 수 (O dd) 또는 짝 수 (E ven) 가 되도록 합니다 .
Mod bus 의 문자 프레 임 정의 는 모 드에 따라 다릅니다 .
| モード | スタート地点。 | data bit | check digit | stop bit | 总位数 |
|---|
R TU 는 2 개의 정 지 비 트를 사용하여 비트 수 를 합 산 할 때 확인 하지 않습니다 - 이것은 하드 요구 사항 이며 , 많은 사람들이 직 렬 포 트 매 개 변 수를 구성 할 때 패 리티 가 없지만 정 지 비 트를 1 에서 2 로 변경 하는 것을 잊 어 버리 므로 통신 이 불안 정 하지만 완전히 작동 하지 않으며 확인 하기가 어렵습니다 .
2. 2 계산 예 제
取一バイト単位。:이 중 1 의 수는 4 (짝 수) 입니다 .
- even parity → check digit = 0,保持 1 的总数为偶数(4 个)
하드 웨어 U ART 는 전송 시 체크 비 트를 자동 으로 계산 하고 채 우 며 수신 시 체크 비 트를 자동 으로 확인 합니다 .수신 자 검 사가 실패 하면 U ART 하드 웨 어는 패 리티 오류 를 표시 하지만 데이터를 자동 으로 삭제 하지는 않습니다 - 삭제 할지 여 부는 소프트웨어 에 달려 있습니다 .
2. 3 패 리티 의 한 계
パリティ検査只能检测전송 중에 정확히 2 비트 가 뒤 집 어 지고 패 리티 가 변 하지 않으면 검 사가 통과 되지만 데이터가 이미 잘못 되었습니다 . RS - 48 5 에서 전 자기 간 섭 은 동시에 멀 티 비트 플 립 보다 단일 비트 플 립 을 일으킬 확률 이 훨씬 높 기 때문에 패 리티 는 실제로 유용 하지만 결코 만 능 하지는 않습니다 .
デバッグ建议分析仪抓 UART フレーム看每个文字的奇偶検証エラー标记。シリアルアシスタント(如 SSCOM)可以表示奇偶エラー次数,这个カウンター·カウンターもし一直在涨,説明你的物理线路有電磁干渉による干渉問題--可能是电缆不屏蔽、和周波数変換器走到一个桥架里了、或者終端抵抗没接导致信号の反射。
三、フレーム层(一):LRC check -- Modbus ASCII モード
3.1 LRC What is it
纵向冗余チェック(Longitudinal Redundancy Check,LRC)是 Modbus ASCII モード使用的フレームチェック算法。它是一个 8 位(1 byte)的チェックコード,位于フレーム的末尾,チェック範囲是駅からの住所到データ区的すべてのバイト,不包括フレーム头(冒号 :)和フレーム尾(回车换行符 CR/LF)。
3.2 Modbus ASCII フレーム構造
: 01 03 21 02 00 02 D7 CR LF
│ └─────────┬────────────┘ │
フレーム头 LRC チェック範囲 LRC码
一个完全的 Modbus ASCII Request frame:
:0103020002F8rn
3.3 LRC 算法
算法极其简单--三步:
- 将アドレス码到データ区的すべてのバイト相加求和
- 取和的低 8 位(模 256)
- 取其补码(256 减去这个值,或者按位取反后加 1)
example:message : 01 03 21 02 00 02
求和:0x01 + 0x03 + 0x21 + 0x02 + 0x00 + 0x02 = 0x29
低 8 位:0x29
补码:256 - 0x29 = 0xD7
LRC checksum = D7
完全フレーム为:: 01 03 21 02 00 02 D7 rn
3.4 LRC 的 C 语言実装
/**
* result Modbus ASCII LRC checksum
* buf: 需要チェック的データ(住所から。码到データ区的すべてのバイト)
* len: byte count
* 戻り値は: 1 byte LRC checksum
*/
unsigned char LRC(unsigned char *buf, unsigned short len)
{
unsigned char lrc = 0;
while (len--) {
lrc += *buf++;
}
// 取补码:256 - lrc,等效于 (-lrc)
return (unsigned char)(-lrc);
}
用 Python 验证:
def calc_lrc(data: bytes) -> int:
"""result Modbus ASCII LRC checksum"""
return (256 - (sum(data) & 0xFF)) & 0xFF
# 测试
msg = bytes([0x01, 0x03, 0x21, 0x02, 0x00, 0x02])
lrc = calc_lrc(msg)
print(f"LRC: 0x{lrc:02X}") # 出力: LRC: 0xD7
3.5 LRC 的局限
LRC 只能检测到一定比例的エラー。もし两バイト単位。的同一个比特位同时翻转(比如バイト A 的第 3 位从 0 变 1,byte B 的第 3 位从 1 变 0),求和结果不变,LRC 検証済み。。这也是なぜか。 Modbus RTU 使用更强的 CRC-16 而ではない LRC--RTU モード用于二进制データ传输,对可靠性要求更高,而 ASCII モード主要用于デバッグ和兼容老デバイス。
四、フレーム层(二):CRC-16 check -- Modbus RTU モード
4.1 CRC-16 Modbus 的数学定义
Modbus RTU 使用 CRC-16 algorithm,参数如下:
| parameter | Value |
|---|---|
| 宽度 | 16 位 |
| 生成多項式 | 0x8005(x¹⁶ + x¹⁵ + x² + 1) |
| 实际运算多項式 | 0xA001(0x8005 位反转形式) |
| 初期値は | 0xFFFF |
| 入力バイト反射 | 否 |
| 出力 CRC 反射 | 是(最终结果高低バイト交換) |
| 出力异或值 | 0x0000 |
这里的「位反转」是 CRC 参数体系中很容易搞混的概念。Modbus 的計算实际上是按位処理的、从 LSB 方向移位,使用反转多項式 0xA001,計算结果自然就是反转的--所以最终必要なし。再做一次全局反转,只需要高低バイト交換。送信时低バイト数前に,ハイバイト在后。
4.2 CRC-16 Modbus 算法流程(逐位計算法)
逐位計算虽然慢,但能让人看清每一步发生了什么:
- 预置 16 位 CRC レジスタ为
0xFFFF - 将报文的第一バイト単位。与 CRC レジスタ的低 8 位异或,结果存回 CRC register
- CRC レジスタ右移 1 位,最高位补 0,チェック移出的最低位
- 移出位 = 1 → CRC レジスタ与 0xA001 XOR;移出位 = 0 → 不做操作
- 重复步骤 3~4,共 8 次(処理完一バイト単位。的 8 个位)
- 重复步骤 2~5,処理报文中下一バイト単位。
- すべてのバイト処理完成后,CRC レジスタ的低バイト数前に、ハイバイト在后,即为 CRC-16 checksum
4.3 CRC-16 Modbus C 语言実装
/**
* result Modbus RTU CRC-16 checksum(逐位計算法)
* buf: 需要チェック的データ(住所から。码到データ区的すべてのバイト)
* len: byte count
* 戻り値は: 16 位 CRC 值(低バイト数前に)
*/
unsigned short CRC16_Modbus(unsigned char *buf, unsigned short len)
{
unsigned short crc = 0xFFFF;
unsigned short i, j;
for (i = 0; i < len; i++) {
crc ^= buf[i]; // 步骤 2
for (j = 0; j < 8; j++) { // 步骤 3~5 循环 8 次
if (crc & 0x0001) {
crc = (crc >> 1) ^ 0xA001; // 移出位为 1
} else {
crc >>= 1; // 移出位为 0
}
}
}
// 注意:Modbus CRC 送信时低バイト数前に
return crc;
}
4.4 查表法 -- 組込みデバイス上的標準実装
逐位計算每バイト単位。要做 8 次循环,对エンベデッド·イン MCU 开销太大。工程上用的是查表法,预先計算 256 バイト単位。的 CRC 值,バイトあたりのバイト只做一次查表 + 一次异或 + 一次移位。
高位表查表法(most common):
/* CRC high位表 */
static const unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
/* ... complete 256 项,此处省略 */
};
/* CRC low位表 */
static const unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
/* ... complete 256 项,此处省略 */
};
unsigned short CRC16_Modbus_Table(unsigned char *buf, unsigned short len)
{
unsigned char crcHi = 0xFF;
unsigned char crcLo = 0xFF;
unsigned short index;
while (len--) {
index = crcLo ^ *buf++;
crcLo = crcHi ^ auchCRCHi[index];
crcHi = auchCRCLo[index];
}
return (crcHi << 8) | crcLo;
}
完全的高低位表共 512 bytes,可直接从 Modbus protocol specification附录中抄过来,Modbus.org V1.1b3 规范的第 40 页给出了完全的サンプル表。
4.5 验证你的 CRC 実装
用已知报文测试:
message: 01 03 00 00 00 01
正确的 CRC: 84 0A(低バイト数前に)
验证步骤:
crc = 0xFFFF
crc ^= 0x01 → 0xFFFE
bit0=0, crc>>1 → 0x7FFF
bit1=1, (0x3FFF) ^ 0xA001 → 0x9FFE
...
最终 crc = 0x0A84
送信时低バイト数前に: 84 0A
整个报文送信序列:01 03 00 00 00 01 84 0A
你也可以用 Modbus Poll 或 Modbus 小程序直接算 CRC,和你的代码実装交叉验证。
4.6 CRC 的检错能力
CRC-16 可以检测到以下エラータイプ:
- すべての单比特エラー
- すべての双比特エラー(在报文不超过 32767 位的条件下)
- すべての奇数个比特エラー
- すべての突发エラー,Length ≤ 16 位
- 99.998% 的更长突发エラー
简单说,在 Modbus フレーム通常不超过 256 バイト的前提下,CRC-16 可以捕捉几乎すべての物理層は传输エラー。用 CRC verification経由的データフレーム,基本可以信任。
五、アプリケーション層:異常な応答码
物理層は和フレームチェック都経由了,从デバイス受信しました一个完全有效的 Modbus フレーム——但逻辑上是错的。这时候从デバイスではない沉默,而是戻る一个異常な応答,告诉マスター「你让我做的事我做不了」。
5.1 異常な応答的フレーム形式
普通の反応和異常な応答違いはありません只有一个:機能コード的最高位。
- 普通の反応:function code = 元の機能コード(如 0x03 Read the hold register)
- Exception Response:function code = 元の機能コード + 0x80(如 0x83),然后跟一バイト単位。的異常コード。
example:マスターリクエスト读レジスタ 01 03 00 00 00 01 84 0A
普通の反応:01 03 02 00 7B F9 8D(读回 2 bytesdata 00 7B)
Exception Response(假设レジスタ不存在):01 83 02 C0 F1
83= 0x03(オリジナル機能コード)+ 0x8002= Exception Code,表示「Illegal data address」
5.2 標準異常なスピードチェック表
| Exception Code | Name | 含义 | 常见原因 |
|---|---|---|---|
| 0x01 | Illegal Function | 非法的機能コード | デバイスはこの機能をサポートしません码(如给読み取り専用デバイス发命令を書く。) |
| 0x02 | Illegal Data Address | 非法的データアドレス | レジスター·アドレス超出範囲,或開始アドレス+数量越界 |
| 0x03 | Illegal Data Value | 非法的データ值 | 写入的值超出了レジスタ的允许範囲 |
| 0x04 | Slave Device Failure | 从機器の故障 | 从デバイス在执行操作时发生了不可恢复的エラー |
| 0x05 | Acknowledge | Confirm(処理中です。中) | リクエストは受け付けました但需要较长时间処理,マスター应待機中 |
| 0x06 | Slave Device Busy | 从デバイスビジー | デバイス処理中です。另一个命令,暂时无法レスポンス |
| 0x07 | Negative Acknowledge | 否定確認 | 从デバイス不能执行该功能(通常是非特定エラー) |
| 0x08 | Memory Parity Error | 内存奇偶検証エラー | 扩展文件区一致性検証の失敗 |
0x01 to 0x04 是最容易遇到的,0x05 to 0x08 在常规 Modbus デバイス上比较少见——很多デバイス厂商只実装了前 4 个異常コード。。
5.3 異常コード。的实际デバッグ用法
「なぜか。デバイス不回データ?」排除物理層は和 CRC 問題后,看異常コード。:
收到 0x01(Illegal function):你发了一个デバイスサポートなし。的機能コード。最も一般的な的场景是——你用 0x03(read holding registers)去读了一个只能経由 0x04(read input registers)アクセス的模拟量入力。去翻デバイス手册的レジスタマッピングテーブル,確認该アドレス对应的アクセス機能コード。
收到 0x02(違法な住所。):你的開始アドレス加上リクエスト数量超出了デバイスサポート的アドレス範囲。比如デバイス只有 10 レジスタを保持する。(address 0-9),你リクエスト了住所から。 0 始まりました。 12 Registers——跨过了边界。解決方法:减小每次リクエスト的レジスタの数,或者在读之前先用 0x11(駅からの報告 ID)機器の確認タイプ。
收到 0x03(Illegal data value):你要写入的值对デバイスない意义。比如デバイスサポート 0-100 的データ範囲,你写入了 200。或者写入时的データBytesの数与機能コード要求の長ささ不マッチング。
完全没応答がある。:ではない異常コード。,而是什么都ない。可能的原因:CRC Error(从デバイス静默丢弃)、フレーム間隔(3.5 个文字の時間)ない正确実装、デバイスアドレス不マッチング。这时候需要用ロジックアナライザ抓バス,確認从デバイス受信しました什么、UART 硬件上有ない奇偶検証エラー标记。
六、タイムアウト机制:マスター的最后一道防线
Modbus 规范要求マスター設定一个タイムアウト時間。在以下情况下,タイムアウト会触发:
- マスター发出リクエスト后,スレーブ在规定时间内ない任何レスポンス
- スレーブ检测到フレームエラー(CRC/LRC 失敗),静默丢弃フレーム,マスター受信できない。回复
- 駅からの住所不存在——报文发到了空アドレス上
タイムアウト時間的設定有一个约束:必须大于从デバイス最长可能的応答時間。計算方式为:
タイムアウト時間 > 传输延迟 × 2 + スレーブ処理时间
在 9600bps 下,一个典型的 Modbus RTU Request(读 1 Registers)约 8 bytes = 64 位,传输时间 = 64 / 9600 ≈ 6.7ms。レスポンス约 7 byte = 56 位,传输时间 ≈ 5.8ms。加上スレーブ処理时间(假设最慢 50ms),双向总时间约 6.7 + 50 + 5.8 ≈ 62.5ms。留一倍余量,タイムアウト设 100-200ms 比较合理。
버스에 여러 슬레이브가있는 경우 폴링이 가장 느린 장치 (예를 들어 오래된 PLC 가 요청을 처리하는 데 100 ms) 를 고려하십시오. Modbus 사양에 의해 권장되는 기본 시간 초과는 1 초입니다 - 이것은 현대적인 장치에 비해 큰 값이지만 초기 디버깅을 시작하는 데는 안전합니다.
7. 완전한 장애물 제거 프로세스
"Modbus 통신 실패" 에 직면하면 다음 순서에 따라 계층별로 확인합니다.
| 레이어 검사항목 도구 결정 방법 물리적 레이어 RS-48 5 배 선 (A/B, 공동 접 지, 터미 널 저항) 멀 티미터켜기, 버스유휴수준 ≥ 200 m V 문자계 층 직 렬 포트매개 변 수 (보트레이트, 데이터비트, 체크비트, 정 지비트) 로 직 분석 기 측정 된 비트 폭 = 1/ba ud 문자계 층 패리티오류로 직 분석 기/직 렬 도우미패리티오류카운 트 = 0 프레 임 계 층 CR C 검 증 Mod bus 애 플 릿/자체작성 코드수신 CR C = CR C 프레 임 계 층 프레 임 간 격 계산 (≥ 3. 5 문자시간) 논 리 분석 기프레 임 간유휴시간 ≥ 3. 6 ms@96 00 b ps 애플 리케이션 계 층 슬 레이브주소장치매뉴 얼/다이 얼 스위치요청 주소 = 슬 레이브 실제주소애플 리케이션 계 층 기능 코드 + 주소 범위장치레지스터매 핑 테이블 기능 코드 및 레지스터주소장치지원 범위내 응용 프로그램 계 층 예외 응답코드 직 렬 포트어시스턴 트/패 킷 캡 처기능 코드최대 값 이 1 인 경우예외코드 검사 응용 프로그램 계 층 시간초과패 킷 캡 처보기타 임스 탬 프 응답시간초과구성 | |||
|---|---|---|---|
| < |
특히 "01 03 00 00 00 01" 과 같은 표준 Modbus 요청과 상호 작용할 때 ASCII 문자열로 직접 보내지 마십시오 - 바이너리 프레임이 전송되어야합니다.0 x 31 0 x 30 0 x 33 0 x 30 0 x 30 0 x 30 0 x 30 0 x 30 0 x 31 (ASCII 문자열의 "010300000001" 이 아닌 6 바이트를 ASCII 패널에 보낸 초보자는 0 0 0 03 00 00 00 01 을 사용했습니다.이것은 거의 모든 Modbus 학습자가 저지른 실수입니다.
CRC 체크 코드의 올바른 계산은 Modbus 통신의 신뢰할 수있는 초석입니다.그러나 엔지니어링 현장의 문제의 90 % 는 CRC 자체에 있지 않습니다 - 배선, 매개 변수, 주소 범위에서 경계 초과, 기능 코드에서 잘못된 선택. CRC 는 "데이터가 옳아야합니다" 라고 말할 때 자신감을주는 안전망과 같습니다.데이터가 확실히 잘못되었을 때, 먼저 앞의 몇 층을 확인하십시오.
이 문서의 코드를 프로젝트에서 교차 검증하기 위해 넣으십시오. 인터넷에서 CRC 코드를 복사하여 직접 사용할 수 있기를 기대하지 마십시오. 바이트 순서가 반전되어 CRC 가 영원히 검증되지 않는 사례가 너무 많습니다.관심있는 사람들은 www. example. com V 1. 1 b 3 사양의 부록 섹션을 방문하여 CRC 룩업 테이블의 전체 데이터와 높은 비트 및 낮은 비트 구현의 공식 예제를 제공합니다.
문제가 있으면 다시 이야기하다.
1