본문 바로가기
통신 프로토콜

자동차 통신 프로토콜 4부: CAN (2부) – Arbitration과 에러 처리 완전 이해

by 버그없는토마토 2025. 12. 26.

CAN통신 프로토콜 – Arbitration과 에러 처리 완전 이해


들어가며

여러분의 차에 3개의 ECU가 동시에 메시지를 보내려고 했어요.

이럴 땐 누구의 것을 먼저 받고, 처리해야할까요?

상황:

엔진 제어 ECU: "나 RPM 데이터 보낼게! ID: 0x123"
변속기 ECU: "나는 기어 상태 보낼게! ID: 0x456"
제동 ECU: "나는 압력값 보낼게! ID: 0x789"

동시에 CAN 버스에 접근...

어? 3개가 동시에?!
그럼 버스 충돌이 되는 거 아니야?

아니다. CAN은 이미 생각해 뒀어.
가장 높은 우선순위(낮은 ID)가 자동으로 메시지를 보낼 수 있게.

결과:
ID 0x123 (엔진 ECU): "내가 먼저 보낼게"
ID 0x456 (변속기 ECU): "알겠어, 잠깐만"
ID 0x789 (제동 ECU): "나도 기다려"

완벽하게 조정됨! (Arbitration)

그런데 만약 데이터가 전송 중에 손상되면?

정상 상황:
CAN 메시지 → 모든 ECU가 수신 ✓

에러 발생:
CAN 메시지 → (에러 발생!) → 감지 → 폐기 → 재전송

누가 감지? 어떻게?
CRC, Bit Error, Stuff Error...

이게 바로 CAN의 에러 처리!

이번 글에서는 CAN의 Arbitration(중재) 메커니즘과 4가지 에러 처리 방식을 한번 설명해볼게요
비유를 통해 쉽게 설명하려고 노력해볼테니 힘내봅시다


3분 요약

바쁜 당신을 위한 핵심:

Arbitration = 여러 메시지가 동시에 올 때, 가장 낮은 ID가 우선 송신

우선순위 = ID 0x001 > ID 0x100 > ID 0x7FF 순서로 결정

에러 처리 = CRC 오류, Bit Error, Stuff Error 감지 후 
           Error Active → Error Passive → Bus Off 상태로 진행

Wired-OR = 물리적으로 Recessive(1)와 Dominant(0)의 
          전자기적 특성으로 ID 비교 수행

결론: CAN은 자동으로 중재하고, 에러도 자동으로 감지한다!

 

Arbitration (중재)란?

정의

Arbitration은 CAN 버스에서 여러 노드가 동시에 송신하려 할 때,
가장 높은 우선순위(낮은 ID)의 노드가 버스를 획득하고 나머지는 자동으로 대기하는 메커니즘
이다.

특징:

승자: ID가 가장 낮은 노드
패자: ID가 높은 노드 (자동으로 수신 모드로 전환)
충돌: 없음 (자동으로 조정됨)
재시도: 패자는 다음 기회에 자동으로 재시도
비용: 추가 하드웨어 불필요 (버스 논리로 자동 처리)

Arbitration의 원리: Wired-OR

CAN 버스에서는 Wired-OR 논리를 사용해서 Arbitration을 수행한다.

CAN 비트 논리:

Dominant (0): 회로가 LOW 상태
             (우선도 높음, 승리)

Recessive (1): 회로가 HIGH 상태
              (우선도 낮음, 패배)

Wired-OR 규칙:
Dominant(0) + Recessive(1) = Dominant(0)
Recessive(1) + Recessive(1) = Recessive(1)

예시:
노드 A: 0 보냄 (Dominant)
노드 B: 1 보냄 (Recessive)
버스: 0 (Dominant이 이김!)

Arbitration 과정 (단계별)

상황: 3개 노드가 동시에 메시지 송신 시도

노드 1: ID = 0x123 (이진: 0001 0010 0011)
노드 2: ID = 0x456 (이진: 0100 0101 0110)
노드 3: ID = 0x789 (이진: 0111 1000 1001)

Stage 1: 첫 번째 ID 비트 비교
─────────────────────────────
노드 1: 0 보냄 (Dominant)
노드 2: 0 보냄 (Dominant)
노드 3: 0 보냄 (Dominant)

버스 상태: 0 (모두 0이니까 Dominant)

결과: 3개 모두 계속 진행

Stage 2: 두 번째 ID 비트 비교
─────────────────────────────
노드 1: 0 보냄 (Dominant)
노드 2: 1 보냄 (Recessive)
노드 3: 1 보냄 (Recessive)

버스 상태: 0 (Dominant이 우선!)

결과: 노드 2, 3은 "어? 내가 1을 보냈는데 0이 와?"
     → Arbitration Lost! 수신 모드로 전환
     → 노드 1만 계속 송신

Stage 3: 세 번째 ID 비트 비교
─────────────────────────────
노드 1: 0 보냄 (Dominant)
노드 2: (수신 모드로 전환됨)
노드 3: (수신 모드로 전환됨)

버스 상태: 0

결과: 노드 1만 계속 송신

... (계속 반복)

최종 결과:

노드 1이 전체 ID를 성공적으로 송신
노드 2, 3은 자동으로 수신 모드로 전환되어 데이터 수신

Arbitration을 통한 우선순위 결정

CAN 메시지 Frame 구조:

SOF (1비트) → ID (11비트) ← Arbitration 영역
              ↓
           여기서 우선순위 결정!

ID 값이 작을수록 우선순위 높음:

ID = 0x001: 최고 우선순위
ID = 0x100: 중간 우선순위
ID = 0x7FF: 최저 우선순위

예: 자동차의 ECU 배치

엔진 제어: ID = 0x100 (높은 우선순위)
           → RPM은 실시간 중요 데이터

변속기 제어: ID = 0x200 (중간 우선순위)
            → 기어 상태도 중요하지만 엔진보다는 낮음

냉각수 온도: ID = 0x300 (낮은 우선순위)
            → 변화 느려서 낮은 우선순위

에어컨 제어: ID = 0x400 (매우 낮은 우선순위)
            → 안전성 관련 없음

실제 시나리오: 엔진 고장 감지

정상 상황:
엔진 ECU (ID=0x100): RPM 데이터 20ms마다 송신
변속기 ECU (ID=0x200): 기어 상태 20ms마다 송신

갑자기 엔진에 문제 발생:
엔진 ECU: "긴급! 고장 감지 메시지를 지금 당장 보내야 해!"
          → ID = 0x050 (높은 우선순위로 설정)
변속기 ECU: "나는 기어 상태를 20ms 간격으로 보낼 예정이야"
           → ID = 0x200

동시에 송신 시도:

타이밍: 엔진 ECU와 변속기 ECU가 정확히 같은 시간에 송신 시도

Arbitration 과정:
엔진 ECU: 첫 번째 비트 0 보냄 (Dominant)
변속기 ECU: 첫 번째 비트 0 보냄 (Dominant)
버스: 0 (계속 진행)

...비트 계속 비교...

엔진 ECU: ID 0x050의 5번째 비트 = 1 보냄 (Recessive)
변속기 ECU: ID 0x200의 5번째 비트 = 0 보냄 (Dominant)
버스: 0 (Dominant 우선)

변속기 ECU가 보낸 0이 이김!
엔진 ECU는 "어? 내가 1을 보냈는데 0이 왔다?"
         → Arbitration Lost!
         → 자동으로 수신 모드로 전환

...비트 계속 비교...

결과: 변속기 ECU의 ID 0x200이 완성됨

변속기 ECU: 전체 메시지 송신 완료

타이밍: 전체 송신 시간 약 130μs

엔진 ECU: "내 차례까지 기다려야겠네"
         → 변속기 메시지 수신 대기
         → 그 다음 송신 기회에 고장 메시지 송신

하지만 여기서 중요한 점:
엔진 고장은 긴급이니까 ID를 0x050으로 설정해서
다음 기회에 최우선 송신되도록 함.

결과: 안전성 보장!

에러 감지 (Error Detection)

CAN의 4가지 에러 감지 메커니즘

1. Bit Error
   └─ 보낸 비트와 받은 비트가 다른 경우

2. CRC Error
   └─ Cyclic Redundancy Check 불일치

3. Stuff Error
   └─ 5개 이상 연속된 같은 비트 감지

4. Frame Error
   └─ 고정된 포맷 위반 (SOF, EOF 등)

1. Bit Error (비트 오류)

정의: 노드가 보낸 비트와 버스에서 읽은 비트가 다른 경우

발생 원인:
- 노이즈: 외부 전자기파 간섭
- 임피던스 불일치: 케이블 손상
- 비트 타이밍 오류: 클럭 스큐(skew)

감지 방식:

노드 A가 0을 보냄:
버스에 0 출력 → "나 0 보냈다"
버스 읽음 → "어? 1이 와?"
→ Bit Error 감지!

구체 예시:

송신하는 비트 시퀀스: 10110101
노드가 보낸 상태: 1
노드가 읽은 상태: 0 (아, 노이즈 때문에!)

→ 즉시 Error Frame 송신 (에러 알림)

영향:
- 그 메시지는 폐기됨
- 모든 노드에서 CRC 재계산 불일치 (CRC Error도 동시 감지)
- 전송 재시도

2. CRC Error (순환 중복 검사 오류)

정의: CRC 체크섬 불일치로 인한 데이터 손상 감지

CRC 계산:
원본 데이터: 0x123 = 0001 0010 0011
CRC 폴리노미얼: 0x18D
계산된 CRC: 0x45

송신 메시지: [0x123][CRC: 0x45]

수신 측:
받은 데이터: 0x123
받은 CRC: 0x45
수신측 재계산 CRC: 0x45
→ 일치! 정상

에러 상황:
송신: [0x123][CRC: 0x45]
     (전송 중 노이즈!)
수신: [0x125][받은 CRC: 0x45]  ← 데이터가 0x123 → 0x125로 변함!

수신측 재계산:
받은 데이터 0x125의 CRC: 0x67
받은 CRC: 0x45
→ 0x67 ≠ 0x45
→ CRC Error 감지!

결과: 메시지 폐기, 재전송 요청

장점:
- 데이터 손상을 높은 확률로 감지 (99.98%)
- 단순한 계산으로 빠른 검증

3. Stuff Error (스터핑 오류)

정의: 5개 이상의 연속된 같은 비트가 나타나는 경우

배경:
CAN 프로토콜에서는 버스 정렬을 위해 
"5개 연속 같은 비트가 나타나면 반대 비트를 삽입"한다.

정상 Stuff 프로세스:

원본 비트: 1111101
                 ↓ (5개 연속 1)
송신 비트: 11111 0 1 (0을 삽입해서 분리)

수신 측:
수신 비트: 11111 0 1
          ↓ 5개 연속이니까 다음 0 제거
복원 비트: 1111101

에러 상황:
정상 송신: 11111 0 1
          (전송 중 노이즈!)
수신: 11111 1 1 (0이 1로 변함!)

수신 측:
"어? 6개 연속 1? 이건 Stuff Error!"
→ Error Frame 송신

결과: 메시지 폐기, 재전송

목적:
CAN 네트워크의 비트 동기화를 유지하기 위함.
Stuff Error는 "포맷 오류"로 취급.

4. Frame Error (프레임 오류)

정의: CAN 메시지의 고정 포맷 규칙을 위반한 경우

CAN Frame 구조:

SOF | 주소 필드 | 제어 필드 | 데이터 필드 | CRC | ACK | EOF
  1비트   11비트    6비트     0-64비트   16비트  2비트  7비트

Frame Error 감지:

1. ACK 필드 오류
   수신 노드가 ACK 비트(0)를 보내야 하는데 안 보냄
   → Frame Error

2. EOF (End of Frame) 필드 오류
   EOF는 반드시 11111111 (recessive 8비트) 이어야 함
   그런데 7비트 안에 dominant 비트가 나옴
   → Frame Error

3. 제어 필드 오류
   DLC(Data Length Code)가 8을 초과
   → Frame Error

예시:

정상 Frame:
[SOF][ID][제어][데이터][CRC][ACK: 0][EOF: 11111111]

에러 Frame:
[SOF][ID][제어][데이터][CRC][ACK: 없음!][EOF: 오류!]
                                    ↑
                                Frame Error 감지!

결과: 메시지 폐기, 재전송

에러 처리 상태 머신

CAN 노드는 3가지 상태를 순환한다:

상태 1: Error Active (정상)
└─ 에러 감지 시: Error Frame 송신 가능
└─ 에러 카운트 증가

상태 2: Error Passive (경고)
└─ 에러가 너무 많음 (Error Count > 임계값)
└─ Error Frame 송신 불가 (조용히 있음)
└─ 수신은 계속 함

상태 3: Bus Off (버스 차단)
└─ 에러가 극심함 (Error Count > 최대값)
└─ 송수신 모두 차단
└─ 강제 초기화 필요

Error Counter 메커니즘

모든 CAN 노드는 2개의 카운터를 유지한다:

TEC (Transmit Error Counter):
- 송신 에러 카운트
- 송신 시 에러 발생 → +8 증가
- 성공적 송신 → -1 감소
- 수신 중 에러 → +1 증가

REC (Receive Error Counter):
- 수신 에러 카운트
- 수신 중 에러 발생 → +1 또는 +8 증가
- 성공적 수신 → -1 감소

상태 전이:

Active 상태:
TEC < 128 AND REC < 128
└─ 정상 작동, Error Frame 송신 가능

Passive 상태:
TEC ≥ 128 OR REC ≥ 128
└─ Error Frame 송신 금지 (다른 노드 방해 금지)
└─ 에러만 세도록 함

Bus Off 상태:
TEC ≥ 256 OR REC ≥ 256
└─ 송수신 모두 차단
└─ 수동 초기화 필요 (리부팅)

실제 에러 처리 흐름

Step 1: 에러 감지
────────────────────
CAN 노드가 메시지 수신 중 CRC Error 감지

Step 2: Error Frame 송신 (6비트 Error Flag)
────────────────────
자신의 상태에 따라:
- Active라면: Error Flag (Dominant 비트 6개)
- Passive라면: 조용히만 있음

Step 3: 다른 노드의 반응
────────────────────
"어? Error Flag 받았어?"
→ 그 메시지는 모두가 폐기

Step 4: Error Counter 조정
────────────────────
에러 발생한 노드:
TEC +8 (또는 +1, 상황에 따라)

Step 5: 상태 확인
────────────────────
TEC >= 128? → Error Passive로 전환
TEC >= 256? → Bus Off로 전환

Step 6: 재전송
────────────────────
Message Buffer에 메시지 보관
다음 버스 기회에 자동 재전송

최대 재시도: 제한 없음 (또는 SW 정책에 따라)

실무 시나리오

시나리오 1: 3개 메시지 동시 송신 - Arbitration 승자 결정

상황:

17:30:42.123456 (정확히 같은 시간)

엔진 ECU: "나 RPM 보내자! ID = 0x100"
변속기 ECU: "나 기어 보내자! ID = 0x200"
제동 ECU: "나 압력 보내자! ID = 0x580"

동시에 CAN 버스 접근 시도!

Arbitration 과정:

타이밍: t = 0ns (SOF 시작)

비트 0: ID의 첫 번째 비트
  엔진: 0 (0x100 = 0000 0100 0000)
  변속기: 0 (0x200 = 0010 0000 0000)
  제동: 0 (0x580 = 0101 1000 0000)
  버스: 0 Dominant
  → 3개 모두 계속

비트 1: ID의 두 번째 비트
  엔진: 0
  변속기: 0
  제동: 1 Recessive
  버스: 0 Dominant
  → 제동 ECU "어? Arbitration Lost!"
  → 제동 ECU 수신 모드로 전환

비트 2~7: 비트 2~7 비교
  엔진: 0000 0
  변속기: 0100 0 (0x200의 나머지)
  → 비트 5에서
    엔진: 0
    변속기: 1
  → 변속기 ECU "Arbitration Lost!"
  → 변속기 ECU 수신 모드로 전환

최종 결과:

엔진 ECU (ID=0x100): 승리! 전체 메시지 송신
변속기 ECU: 수신 모드로 전환, 엔진 메시지 수신
제동 ECU: 수신 모드로 전환, 엔진 메시지 수신

엔진 ECU가 메시지를 다 보낼 때까지 (약 130μs):
변속기, 제동 ECU는 모두 수신 중.

메시지 송신 완료 후:

변속기 ECU: "이제 내 차례!"
           → 기어 메시지 송신 시작

제동 ECU: "기다려, 먼저 온 것부터 처리해야 해"
         → 기어 메시지 수신 후 압력 메시지 송신

시간 흐름:
t = 0μs: 엔진 메시지 송신 시작
t = 130μs: 엔진 메시지 송신 완료
t = 130μs: 변속기 메시지 송신 시작
t = 260μs: 변속기 메시지 송신 완료
t = 260μs: 제동 메시지 송신 시작
t = 390μs: 제동 메시지 송신 완료

결론:
동시 송신 요청 → Arbitration으로 우선순위 결정
→ 자동으로 차례대로 송신 (충돌 없음!)

시나리오 2: CRC Error 발생 및 재전송

상황: 엔진 온도 센서 데이터 전송 중 노이즈 발생

정상 메시지:
ID: 0x300 (엔진 온도)
데이터: 0x85 0x20 (온도 = 85도, 정상 범위)
CRC: 0x1A 0x45

송신 노드 (엔진 ECU):
메시지: [SOF][ID=0x300][데이터=0x85][CRC=0x1A45][ACK][EOF]

전송 중:

t = 10ms: 송신 시작
t = 10.050ms: 데이터 필드 전송 중

"바로 그때, 외부 노이즈 발생!"
(자동차 엔진 스타터 작동)

데이터가 손상됨:
원래: 0x85 (0000 1000 0101)
수신: 0x87 (0000 1000 0111) ← 마지막 비트 1이 추가됨

수신 노드들 (변속기, 제동, 진단 ECU):

전체 메시지 수신:
[SOF][ID=0x300][데이터=0x87][CRC=0x1A45][ACK][EOF]

CRC 검증 시작:

수신한 데이터 0x87로 CRC 재계산:
계산된 CRC: 0x3B 20

받은 CRC: 0x1A 45

비교: 0x3B20 ≠ 0x1A45
→ CRC Error 감지!

Error Detection:

모든 수신 노드에서 동시에:
"CRC 안 맞다! Error Frame 송신!"

Error Frame:
[Error Flag (6개 Dominant 비트)]
[Error Delimiter (8개 Recessive 비트)]

결과:

송신 노드 (엔진 ECU):
자신이 보낸 메시지에서 Error Flag 수신
"어? Error Frame? 내 메시지에 에러가 있나?"
→ TEC +8 (Transmit Error Count 증가)
→ Message Buffer에 메시지 보관

다른 수신 노드들:
"CRC Error 감지, Error Frame 송신함"
→ REC +1 (Receive Error Count 증가)

재전송 프로세스:

t = 10.150ms: 에러 처리 완료

엔진 ECU:
"내 메시지를 다시 보내자"
→ Message Buffer에 있는 0x300 메시지 재송신

t = 10.150ms~10.200ms: 재전송

이번엔 정상:
[SOF][ID=0x300][데이터=0x85][CRC=0x1A45][ACK][EOF]

수신 노드들:
CRC 검증: 0x1A45 = 0x1A45 ✓
→ 메시지 수용, 온도값 0x85 = 85도 처리

결과:

최종 온도: 85도 (정상)
에러는 감지되고 자동으로 재전송됨
사용자는 느끼지 못함

그리고:
엔진 ECU: TEC = 8
다른 노드: REC = 1

다음 에러 발생 전까지 카운터는 천천히 감소:
성공적 송/수신 시 카운터 -1

시나리오 3: Error Passive 상태 진입

상황: CAN 버스 케이블 손상으로 연속 에러 발생

배경:
- 제어 모듈과 ECU 사이 CAN 케이블이 차체와 문질려서
  5mm 정도 외피가 벗겨짐
- 습도 높은 날씨
- 간헐적 접촉 불량

에러 발생:

t = 0s: 정상 (TEC = 0, REC = 0, Active 상태)

t = 1s: 첫 번째 메시지 송신
        노이즈로 CRC Error 발생
        → TEC = 8

t = 2s: 세 번째 메시지 수신
        Bit Error 감지
        → REC = 1

t = 3s: 네 번째 메시지 송신
        다시 CRC Error
        → TEC = 16

... (계속 반복) ...

t = 20s: TEC = 120
         REC = 50

t = 25s: TEC = 128 (또는 REC = 128)

상태 전이: Active → Error Passive

Error Passive 상태에서의 동작:

1. Error Frame 송신 금지
   → 다른 노드 방해 금지 (조용히만 있음)

2. 수신은 계속 함
   → 다른 메시지는 수신 가능

3. 에러 카운트만 계속 증가
   → TEC, REC 계속 업데이트

4. 상태 표시
   → 진단기에서 "CAN Bus Error Passive" 표시
   → 대시보드에 경고등 활성화

문제:

버스가 계속 에러 상태:
케이블 손상이 정상되지 않으면
에러는 계속 쌓임

t = 30s: REC = 200 (Bus Off 임계값에 가까움)

t = 32s: REC = 256 이상

상태 전이: Error Passive → Bus Off

Bus Off 상태 (최악):

1. 송수신 모두 차단
   → CAN 메시지 송신 불가
   → CAN 메시지 수신 불가

2. 진단기에 "CAN Bus Off" 표시
   → "CAN 통신 오류" 또는 "CAN 하드웨어 오류"

3. ECU 기능 제한
   → 안전 모드로 동작
   → 엔진 제한 토크, 변속기 기어 고정

현실:

운전자가 느끼는 현상:
- t < 25s: 정상 (에러는 백그라운드에서)
- t = 25s: "CAN Bus 경고" 표시, 성능 약간 저하
- t = 30s: "Engine Error" 경고등 켜짐
- t = 32s: 차가 기어 고정 (P 또는 N)
         "정비 필요" 경고

해결:

정비소:
"CAN 버스 케이블 손상 발견!"
→ 케이블 교체

교체 후:

Bus Off 상태에서 자동 복구 불가능
→ ECU 리셋 필요 (시동 끔 후 켜기, 또는 진단기 초기화)

복구:
t = 0s: 리셋 후
        TEC = 0, REC = 0, Active 상태 복구
        케이블 정상이니까 에러 없음 ✓

Arbitration과 에러 처리 타이밍 다이어그램

CAN 메시지 전송 타이밍:

t=0μs:        SOF (1비트)
0-130μs:      전체 메시지 전송 구간
              ├─ SOF: 1비트
              ├─ Arbitration Field: 12비트 (SOF + ID)
              ├─ Control Field: 6비트
              ├─ Data Field: 0-64비트
              ├─ CRC Field: 16비트
              ├─ ACK Field: 2비트
              └─ EOF: 7비트

Arbitration 구간 상세 (0-12μs):

t=0-1μs:      SOF (1비트, 모두 0)
              모든 노드: SOF = 0 보냄
              버스: 0 (모두 계속)

t=1-2μs:      ID 첫 번째 비트
              노드 A (ID=0x123): 0
              노드 B (ID=0x456): 0
              노드 C (ID=0x789): 0
              버스: 0 (모두 계속)

t=2-3μs:      ID 두 번째 비트
              노드 A: 0
              노드 B: 1 ← Recessive
              노드 C: 1 ← Recessive
              버스: 0 Dominant (노드 A 우선)
              노드 B, C: Arbitration Lost!
                         수신 모드 전환

t=3-12μs:     ID 나머지 비트
              노드 A만 계속 송신
              노드 B, C는 수신 모드

에러 발생 시:

정상 전송:
t=0-130μs: [메시지 정상 전송]
           ↓ CRC 검증
t=130μs:   CRC OK ✓ → ACK 비트 수신
           → 전송 완료

에러 발생:
t=0-80μs:  [메시지 전송 중]
           ↓ 노이즈 발생
t=80μs:    데이터 손상!
           ↓ 수신 노드 CRC 재계산
t=82μs:    CRC Error 감지!
           ↓ Error Frame 송신
t=84μs:    [Error Flag: 6비트 Dominant]
           [Error Delimiter: 8비트 Recessive]
           ↓ 메시지 폐기
t=92μs:    에러 처리 완료
           ↓ 송신 노드 재전송
t=94-224μs: [메시지 재전송]

면접 예상 질문

Q1: "CAN에서 여러 노드가 동시에 메시지를 보내면 충돌이 안 되나요?"
A: "충돌이 안 됩니다. CAN은 Arbitration 메커니즘으로 가장 높은 우선순위(낮은 ID)의 
   메시지가 자동으로 버스를 획득하고, 나머지는 자동으로 수신 모드로 전환됩니다.
   이를 Wired-OR 논리로 구현하는데, Dominant(0)와 Recessive(1) 비트의 전자기적 
   특성을 이용합니다."

Q2: "Arbitration Lost가 되면 어떻게 되나요?"
A: "Arbitration Lost가 되는 노드는 자신이 보내던 메시지를 중단하고 자동으로 수신 모드로 
   전환됩니다. 그리고 Message Buffer에 메시지를 보관했다가, 다음 버스 기회(다른 노드의 
   메시지가 끝난 후)에 자동으로 재송신합니다."

Q3: "CRC Error가 발생하면?"
A: "CRC Error를 감지한 노드가 Error Frame을 송신합니다. 모든 노드가 그 메시지를 폐기하고,
   송신 노드는 Message Buffer에서 메시지를 다시 꺼내 재송신합니다. 
   이 과정은 자동으로 반복됩니다."

Q4: "Stuff Error가 뭐죠?"
A: "CAN 프로토콜에서는 비트 동기화를 위해 5개의 연속된 같은 비트가 나타나면 자동으로 
   반대 비트를 삽입합니다. 만약 5개 연속 같은 비트 다음에 같은 비트가 또 나타나면, 
   이를 Stuff Error로 감지해서 메시지를 폐기하고 재전송합니다."

Q5: "Error Active, Passive, Bus Off 상태 차이는?"
A: "Active 상태에서는 에러 감지 시 Error Frame을 송신할 수 있습니다. 
   에러가 많아져서 카운터가 128을 넘으면 Passive 상태로 전환되고, 
   이 상태에서는 Error Frame을 송신하지 않아서 다른 노드를 방해하지 않습니다.
   카운터가 256을 넘으면 Bus Off 상태로 전환되어 송수신이 모두 차단됩니다.
   이 경우 ECU 리셋이 필요합니다."

핵심 정리

Arbitration:

  • 여러 메시지가 동시에 올 때 ID가 가장 낮은 메시지가 우선 송신
  • Wired-OR 논리로 구현 (Dominant 0이 Recessive 1을 이김)
  • 충돌 없이 자동으로 우선순위 결정

에러 감지:

  • Bit Error: 보낸 비트와 받은 비트 불일치
  • CRC Error: 체크섬 불일치
  • Stuff Error: 5개 연속 같은 비트 이상 감지
  • Frame Error: 포맷 규칙 위반

에러 처리:

  • Active → Passive → Bus Off 상태 전이
  • Error Counter(TEC, REC)로 상태 관리
  • 자동 재전송으로 신뢰성 보장