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

무료무료 기술 자료

이 글은 바로 읽을 수 있으며 기초 학습과 검색 유입에 적합합니다.

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 의 문자 프레 임 정의 는 모 드에 따라 다릅니다 .

모드시작位데이터 비트패리티정지 비트总位数

R TU 는 2 개의 정 지 비 트를 사용하여 비트 수 를 합 산 할 때 확인 하지 않습니다 - 이것은 하드 요구 사항 이며 , 많은 사람들이 직 렬 포 트 매 개 변 수를 구성 할 때 패 리티 가 없지만 정 지 비 트를 1 에서 2 로 변경 하는 것을 잊 어 버리 므로 통신 이 불안 정 하지만 완전히 작동 하지 않으며 확인 하기가 어렵습니다 .

2. 2 계산 예 제

取一个바이트:이 중 1 의 수는 4 (짝 수) 입니다 .

  • 짝수 패리티 → 패리티 = 0,保持 1 的总数为偶数(4 个)

하드 웨어 U ART 는 전송 시 체크 비 트를 자동 으로 계산 하고 채 우 며 수신 시 체크 비 트를 자동 으로 확인 합니다 .수신 자 검 사가 실패 하면 U ART 하드 웨 어는 패 리티 오류 를 표시 하지만 데이터를 자동 으로 삭제 하지는 않습니다 - 삭제 할지 여 부는 소프트웨어 에 달려 있습니다 .

2. 3 패 리티 의 한 계

奇짝수 패리티只能检测전송 중에 정확히 2 비트 가 뒤 집 어 지고 패 리티 가 변 하지 않으면 검 사가 통과 되지만 데이터가 이미 잘못 되었습니다 . RS - 48 5 에서 전 자기 간 섭 은 동시에 멀 티 비트 플 립 보다 단일 비트 플 립 을 일으킬 확률 이 훨씬 높 기 때문에 패 리티 는 실제로 유용 하지만 결코 만 능 하지는 않습니다 .

디버깅建议分析仪抓 UART 帧看每个문자的奇짝수 패리티错误기호。시리얼 포트助手(如 SSCOM)可以显示奇偶错误次数,这个计数器如果一直在涨,설명你的物理线路有电磁干扰문제--可能是电缆不屏蔽、和变频器走到一个桥架里了、或者终端电阻没接导致信号反射。


三、帧层(一):LRC 체크섬 -- Modbus ASCII 모드

3.1 LRC 是什么

LRC 체크섬(Longitudinal Redundancy Check,LRC)是 Modbus ASCII 모드使用的帧체크섬算法。它是一个 8 位(1 바이트)的체크섬,位于帧的末尾,체크섬范围是슬레이브 주소到데이터区的所有바이트,不包括帧头(콜론 :)和帧尾(줄바꿈(CRLF)符 CR/LF)。

3.2 Modbus ASCII 帧结构

:   01  03  21  02  00  02  D7  CR  LF
│   └─────────┬────────────┘   │
帧头       LRC 체크섬范围      LRC码

一个完整的 Modbus ASCII 请求帧:

:0103020002F8rn

3.3 LRC 算法

算法极其简单--三步:

  1. 将주소码到데이터区的所有바이트相加求和
  2. 取和的低 8 位(模 256)
  3. 取其补码(256 减去这个值,或者按位取反后加 1)

예제:프레임 : 01 03 21 02 00 02

求和:0x01 + 0x03 + 0x21 + 0x02 + 0x00 + 0x02 = 0x29
低 8 位:0x29
补码:256 - 0x29 = 0xD7
LRC 체크섬 = D7

전체 프레임为:: 01 03 21 02 00 02 D7 rn

3.4 LRC 的 C 언어实现

/**
 * 계산 Modbus ASCII LRC 체크섬
 * buf: 需要체크섬的데이터(从주소码到데이터区的所有바이트)
 * len: 바이트数
 * 返回值: 1 바이트 LRC 체크섬
 */
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(데이터: bytes) -> int:
    """계산 Modbus ASCII LRC 체크섬"""
    return (256 - (sum(데이터) & 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,바이트 B 的第 3 位从 1 变 0),求和结果不变,LRC 체크섬通过。这也是为什么 Modbus RTU 使用更强的 CRC-16 而不是 LRC--RTU 모드用于2진수데이터传输,对可靠性要求更高,而 ASCII 모드主要用于디버깅和兼容老设备。


四、帧层(二):CRC-16 체크섬 -- Modbus RTU 모드

4.1 CRC-16 Modbus 的数学定义

Modbus RTU 使用 CRC-16 算法,매개변수如下:

매개변수
宽度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 레지스터
  3. CRC 레지스터右移 1 位,最高位补 0,检查移出的最低位
  4. 移出位 = 1 → CRC 레지스터与 0xA001 异或;移出位 = 0 → 不做操作
  5. 重复步骤 3~4,共 8 次(处理完一个바이트的 8 个位)
  6. 重复步骤 2~5,处理프레임中下一个바이트
  7. 所有바이트处理完成后,CRC 레지스터的低바이트在前、高바이트在后,即为 CRC-16 체크섬

4.3 CRC-16 Modbus C 언어实现

/**
 * 계산 Modbus RTU CRC-16 체크섬(逐位계산法)
 * buf: 需要체크섬的데이터(从주소码到데이터区的所有바이트)
 * len: 바이트数
 * 返回值: 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 值,每바이트只做一次查表 + 一次异或 + 一次移位。

高位表查表法(最常用):

/* CRC 高位表 */
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,
    /* ... 完整 256 项,此处省略 */
};

/* CRC 低位表 */
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,
    /* ... 完整 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 바이트,可直接从 Modbus 프로토콜사양附录中抄过来,Modbus.org V1.1b3 사양的第 40 页给出了完整的예제表。

4.5 验证你的 CRC 实现

用已知프레임测试:

프레임: 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 位的条件下)
  • 所有奇数个比特错误
  • 所有突发错误,길이 ≤ 16 位
  • 99.998% 的更长突发错误

简单说,在 Modbus 帧通常不超过 256 바이트的前提下,CRC-16 可以捕捉几乎所有物理层传输错误。用 CRC 검증通过的데이터帧,基本可以信任。


五、적용层:异常响应码

物理层和帧체크섬都通过了,从设备收到了一个完整有效的 Modbus 帧——但逻辑上是错的。这时候从设备不是沉默,而是返回一个异常响应,告诉마스터「你让我做的事我做不了」。

5.1 异常响应的帧형식

正常响应和异常响应的区别只有一个:기능 코드的最高位

  • 正常响应:기능 코드 = 原始기능 코드(如 0x03 读유지 레지스터)
  • 异常响应:기능 코드 = 原始기능 코드 + 0x80(如 0x83),然后跟一个바이트的异常码

예제:마스터请求读레지스터 01 03 00 00 00 01 84 0A

正常响应:01 03 02 00 7B F9 8D(读回 2 바이트데이터 00 7B

异常响应(假设레지스터不存在):01 83 02 C0 F1

  • 83 = 0x03(原기능 코드)+ 0x80
  • 02 = 异常码,表示「非法데이터주소」

5.2 표준异常码速查表

异常码名称含义常见原因
0x01Illegal 기능非法的기능 코드设备不支持该기능 코드(如给只读设备发写指令)
0x02Illegal 데이터 주소非法的데이터주소레지스터주소超出范围,或시작주소+数量越界
0x03Illegal 데이터 Value非法的데이터值쓰기的值超出了레지스터的允许范围
0x04Slave Device Failure从设备故障从设备在执行操作时发生了不可恢复的错误
0x05Acknowledge确认(正在处理中)请求已接受但需要较长时间处理,마스터应대기
0x06Slave Device Busy从设备忙设备正在处理另一个命令,暂时无法响应
0x07Negative Acknowledge否定确认从设备不能执行该功能(通常是非特定错误)
0x08Memory Parity 오답内存奇짝수 패리티错误扩展文件区一致性체크섬失败

0x01 到 0x04 是最容易遇到的,0x05 到 0x08 在常规 Modbus 设备上比较少见——很多设备厂商只实现了前 4 个异常码。

5.3 异常码的实际디버깅用法

「为什么设备不回데이터?」排除物理层和 CRC 문제后,看异常码:

收到 0x01(非法功能):你发了一个设备不支持的기능 코드。最常见的시나리오是——你用 0x03(读유지 레지스터)去读了一个只能通过 0x04(读입력 레지스터)访问的模拟量입력。去翻设备手册的레지스터 매핑表,确认该주소对应的访问기능 코드。

收到 0x02(非法주소):你的시작주소加上请求数量超出了设备支持的주소范围。比如设备只有 10 个유지 레지스터(주소 0-9),你请求了从주소 0 开始的 12 个레지스터——跨过了边界。解决方法:减小每次请求的레지스터 수량,或者在读之前先用 0x11(보고서슬레이브 ID)确认设备유형。

收到 0x03(非法데이터值):你要쓰기的值对设备没有意义。比如设备支持 0-100 的데이터范围,你쓰기了 200。或者쓰기时的데이터바이트数与기능 코드要求的길이不일치。

完全没有响应:不是异常码,而是什么都没有。可能的原因:CRC 错误(从设备静默丢弃)、帧间隔(3.5 个문자时间)没有正确实现、设备주소不일치。这时候需要用逻辑分析仪抓总线,确认从设备收到了什么、UART 硬件上有没有奇짝수 패리티错误기호。


六、超时机制:마스터的最后一道防线

Modbus 사양要求마스터설정一个超时时间。在以下情况下,超时会触发:

  1. 마스터发出请求后,슬레이브在规定时间内没有任何响应
  2. 슬레이브检测到帧错误(CRC/LRC 失败),静默丢弃帧,마스터收不到回复
  3. 슬레이브 주소不存在——프레임发到了空주소上

超时时间的设置有一个约束:必须大于从设备最长可能的响应时间。계산방식为:

超时时间 > 传输지연 × 2 + 슬레이브处理时间

在 9600bps 下,一个典型的 Modbus RTU 请求(读 1 个레지스터)약 8 바이트 = 64 位,传输时间 = 64 / 9600 ≈ 6.7ms。响应약 7 바이트 = 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 룩업 테이블의 전체 데이터와 높은 비트 및 낮은 비트 구현의 공식 예제를 제공합니다.

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

실제 프로젝트에 이 자료를 활용하시겠습니까?

도구 센터에서 프레임 분석, CRC 검증, 장비 디버깅을 진행하거나 요청을 제출하여 선정 및 연동 제안을 받아보세요.

엔지니어 회원

이 글을 실행 가능한 디버깅 자료로 활용하세요

가입하면 고급 프레임 분석, 자료 패키지 다운로드, 코드 예제, 엔지니어링 사례, 우선 기술 지원을 이용할 수 있어 실제 프로젝트 납품에 적합합니다.

고급 도구 무제한 이용
자료 패키지와 코드 패키지
완전한 엔지니어링 사례 라이브러리
우선 기술 지원 채널

《“Modbus 통신 오류의 일반적인 탐지 방법”》 有 1 条评论

답글 작성

이메일 주소는 공개되지 않습니다. 必填项已用 * 标注