Modbus 통신 오류의 일반적인 탐지 방법

freeFree Technical Resource

This content is free to read, suitable for basic learning and search traffic.

Modbus 통신 오류의 일반적인 탐지 방법

출 처 : 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 bitcheck digitstop 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 算法

算法极其简单--三步:

  1. 将アドレス码到データ区的すべてのバイト相加求和
  2. 取和的低 8 位(模 256)
  3. 取其补码(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,参数如下:

parameterValue
宽度16 位
生成多項式0x8005(x¹⁶ + x¹⁵ + x² + 1)
实际运算多項式0xA001(0x8005 位反转形式)
初期値は0xFFFF
入力バイト反射
出力 CRC 反射是(最终结果高低バイト交換)
出力异或值0x0000

这里的「位反转」是 CRC 参数体系中很容易搞混的概念。Modbus 的計算实际上是按位処理的、从 LSB 方向移位,使用反转多項式 0xA001,計算结果自然就是反转的--所以最终必要なし。再做一次全局反转,只需要高低バイト交換。送信时低バイト数前に,ハイバイト在后。

4.2 CRC-16 Modbus 算法流程(逐位計算法)

逐位計算虽然慢,但能让人看清每一步发生了什么:

  1. 预置 16 位 CRC レジスタ为 0xFFFF
  2. 将报文的第一バイト単位。与 CRC レジスタ的低 8 位异或,结果存回 CRC register
  3. CRC レジスタ右移 1 位,最高位补 0,チェック移出的最低位
  4. 移出位 = 1 → CRC レジスタ与 0xA001 XOR;移出位 = 0 → 不做操作
  5. 重复步骤 3~4,共 8 次(処理完一バイト単位。的 8 个位)
  6. 重复步骤 2~5,処理报文中下一バイト単位。
  7. すべてのバイト処理完成后,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(オリジナル機能コード)+ 0x80
  • 02 = Exception Code,表示「Illegal data address」

5.2 標準異常なスピードチェック表

Exception CodeName含义常见原因
0x01Illegal Function非法的機能コードデバイスはこの機能をサポートしません码(如给読み取り専用デバイス发命令を書く。)
0x02Illegal Data Address非法的データアドレスレジスター·アドレス超出範囲,或開始アドレス+数量越界
0x03Illegal Data Value非法的データ值写入的值超出了レジスタ的允许範囲
0x04Slave Device Failure从機器の故障从デバイス在执行操作时发生了不可恢复的エラー
0x05AcknowledgeConfirm(処理中です。中)リクエストは受け付けました但需要较长时间処理,マスター应待機中
0x06Slave Device Busy从デバイスビジーデバイス処理中です。另一个命令,暂时无法レスポンス
0x07Negative Acknowledge否定確認从デバイス不能执行该功能(通常是非特定エラー)
0x08Memory 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 规范要求マスター設定一个タイムアウト時間。在以下情况下,タイムアウト会触发:

  1. マスター发出リクエスト后,スレーブ在规定时间内ない任何レスポンス
  2. スレーブ检测到フレームエラー(CRC/LRC 失敗),静默丢弃フレーム,マスター受信できない。回复
  3. 駅からの住所不存在——报文发到了空アドレス上

タイムアウト時間的設定有一个约束:必须大于从デバイス最长可能的応答時間。計算方式为:

タイムアウト時間 > 传输延迟 × 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 룩업 테이블의 전체 데이터와 높은 비트 및 낮은 비트 구현의 공식 예제를 제공합니다.

문제가 있으면 다시 이야기하다.

Put this resource to use in a real project?

Go to the Tool Center for message parsing, CRC verification and device debugging, or submit your requirements for selection and integration advice.

Engineer Membership

Turn this article into actionable debugging resources

After activation, you can use advanced message parsing, resource pack downloads, code examples, engineering cases and priority technical support, suitable for real project delivery.

Unlimited Advanced Tools
Resource & Code Packs
Complete Engineering Case Library
Priority Technical Support

《“Modbus 통신 오류의 일반적인 탐지 방법”》 有 1 条コメント

Leave a Reply

Your email address will not be published. Required fields are marked *.