CAN(Controller Area Network) ID Filtering, CAN 필터 설정, STM32 CAN 필터 설정

728x90
반응형

CAN(Controller Area Network)은 다수의 디바이스가 하나의 통신라인을 이용해 통신하는 가장 대표적인 병렬 통신방식 중 하나다. 이건 뭐 내가 설명하는 것보다는 위키백과의 설명이 더 잘되어 있으니 아래 내용을 참고하기 바란다. 오늘 설명하고자 하는 것은 CAN 통신의 ID Filtering 방법이다. 할 때마다 헷갈려서 정리해서 기록하려 한다. 후....

 

https://ko.wikipedia.org/wiki/CAN_%EB%B2%84%EC%8A%A4

 

CAN 버스 - 위키백과, 우리 모두의 백과사전

CAN 통신(Controller Area Network)은 차량 내에서 호스트 컴퓨터 없이 마이크로 컨트롤러나 장치들이 서로 통신하기 위해 설계된 표준 통신 규격이다. CAN 통신은 메시지 기반 프로토콜이며 최근에는 차

ko.wikipedia.org

 

 

CAN 은 다수의 장치가 하나의 통신 라인에 연결되기 때문에 각 장치마다 고유의 ID를 부여해야한다. 다수의 장치의 데이터를 수신하는 ECU나 어떤 장치는 설정된 ID가 보내는 데이터만 수신해야 하는데, 이렇게 지정된 ID가 보내는 데이터만 수신하도록 하는 기능이 CAN Filtering이다. 

 

즉, "내가 원하는 장치가 보내는 데이터만 수신 할 수 있도록 Filtering을 적용한다."라고 생각하면 된다.

 

 

설명은 STM32의 STM32F446RET 기준으로 설명하도록 하겠다. 다른 MCU를 사용해도 큰 차이는 없고, 타사의 MCU 또한 Filtering 방법은 차이가 없다. 내용만 이해하면 다른 MCU에도 쉽게(?) 적용할 수 있을 것이다. 그리고 포스팅에서 실험은 IXXAT 사의 canAnalyser3 mini를 활용했다. 모두 증명하고 확인하고 기록하는 내용이다!! 

 

 

 

CAN Filter는 ID Lisk 모드와 ID Mask 모드가 있다. list 모드와 mask 모드라고 부른다. 그리고 필터링할 ID의 범위를 지정할 수 있는데 32bit 모드와 16bit 모드가 있다. 이 부분은 다른 MCU의 CAN도 모두 동일하다. 

 

총 4가지 조합이 나올 수 있다. 

 

16Bit, ID List mode

16Bit, ID Mask mode

32Bit, ID List mode

32Bit, ID Mask mode

 

여기에 CAN 버전인 Standard(STD, 2.0A), Extended(EXT, 2.0B)를 고려한다면 8가지 조합이 나올 수 있다. CAN 2.0A STD는 11bit로 0x000~0x7FF 까지ID 를 부여할 수있고, CAN2.0B EXT는 29bit로 0x00000000~0x1FFFFFFF 까지 ID를 부여 할 수 있다. 

 

그럼 ID List mode, ID Mask mode에 대해 알아보도록 하자.(건너뛰지 말고 순서대로 읽어야 내용을 전부 이해할 수 있습니다 :) )

 

ID List mode ?

ID List모드는 지정된 특정 ID만 통과시키는 방식이다. 아래 코드를 보자. 

 

ST에서는 filter를 설정할 수 있도록 구조체를 제공한다. 사용하고자 하는 모드, ID 범위, mask값을 지정해주면 된다. 

canFilter.FilterMode Filter의 동작모드를 설정한다. ID LIst 모드와 ID Mask 모드를 설정할 수 있다. 
canFilter.FilterScale  Filter의 ID 범위를 지정한다. 16bit, 32bit
canFilter.FilterIdHigh Filter ID 의 상위 16bit
canFilter.FilterIdLow Filter ID 의 하위 16bit
canFilter.FilterMaskIdHigh Filter ID Mask 의 상위 16bit
canFilter.FilterMaskIdLow  Filter ID Mask 의 하위 16bit

ID 모드는 지정된 ID만 통과시킨다. canFilter.FilterMode를 위 코드와 같이 CAN_FILTERMODE_IDLIST로 설정하고, canFilter.FilterIdHigh 변수에 통과시키고자 하는 ID의 상위 16bit 값을 적용해주면 된다. 위 코드에서 CAN 버전은 STD(2.0A)로 설정했고 보내는 ID(Tx ID)와 데이터를 수신하는 ID를 동일하게 설정했다.

 

fixedId 변수에 Tx ID를 집어넣고 <<5를 해줬다. 이건 뭐지? 그리고 canFilter.FilterIdHigh 변수에 fixedId를 넣어줬고 canFilter.FilterIdLow에는 0을 넣어줬다. 이 부분에 대해 살펴보자!

 

레지스터를 살펴보면 답이 나온다. 

STD ID는 ID Register(CAN_RIxR, x = 0, 1)의 상위 11비트를 사용한다. canFilter 구조체에서 ID의 구분을 상위 16bit, 하위 16bit로 나누었기 때문에 하위 비트에 해당하는 canFilter.FilterIdLow에는 0을 넣어주고, canFilter.FilterIdHigh 에는 수신할 ID 값을 넣어준다. 상위 16bit 중 STD ID는 상위 11bit를 사용하기 때문에 shift 연산으로 5칸 이동시킨 것이다. 

이렇게 하면 송신하는 측에서 0x201로 보내는 데이터만 수신하게 된다. 그렇다면 EXT(2.0B)는??? 마찬가지로 상위 bit, 하위 bit를 구분해서 ID 값을 넣어주면 된다. 

 

 

canVersion을 CAN_ID_EXT로 변경해주고, CAN Tx ID를 29bit 값으로 변경한다. 본 포스팅에서는 0x1F1234A9로 변경했다. 29bit 범위라면 어떤 값을 지정해도 상관없다. fixedId에 Tx ID를 왼쪽으로 3칸 이동한 값을 넣어준다.

위 코드와 같이 canFilter.FilterIdLow에 0xFFFF를 and 연산한 값에 CAN 버전 값을 or 연산한 값을 넣어준다. 이걸 풀어서 계산해보면..

 

우선 0x1F1234A9를 왼쪽으로 3칸 이동시키면 다음과 같다. 

여기에 CAN_ID_EXT를 or 연산해주면 다음과 같다.(CAN_ID_EXT 값은 0x04)

 

여기서 하위 16bit(2Byte) 값을 canFilter.FilterIdLow 변수에 넣어주기 위해 0xFFFF를 and 연산한다!

ID 값을 왼쪽으로 3칸 이동시킨 이유는 아래 레지스터를 보면 알 수 있다. 하위 3비트가 IDE, RTR을 설정하는 영역이고, EXID 의 시작이 bit3부터기 때문이다.

상위 16bit 값은 0x1F1234A9를 왼쪽으로 3칸 이동한 값을 다시 오른쪽으로 16칸 이동시켜 canFilter.FilterIdHigh 변수에 그대로 넣어주면 된다. 

 

여기서 왜 CAN 버전을 or 연산해서 넣어주냐면,, IDE 레지스터는 ID가 Extexded 인 경우에 1로 만들어줘야 되기 때문이다. 아래 레지스터를 보면 좀 더 이해가 잘(?)될 것이다 ^^ 

 

여기서 주의할 점은 CAN EXT는 ID 값이 29bit기 때문에 필터 범위를 반드시 32bit로 해줘야 한다.! 반.드.시.!!!  

 

설명이 길었다.. 나름 자세히 써보려고 했다. 왜냐고? 이걸 검색해서 들어온 사람이라면 분명 모르는 사람이 들어왔을 테니까? 

 

그럼 이제 mask 모드에 대해 알아보자. 

 

ID Mask mode?

Mask 모드는 내가 지정한 범위의 ID 만 수신하도록 하는 기능이다. 즉, 여러 장치의 데이터를 수신할 수 있다. 우선 STD에서 어떻게 설정하는지 살펴보자 .

 

첫번쨰로 코드에서 아래 부분을 수정해 줘야한다. 

CAN의 filter mode 를 ID Mask 모드로 변경하고 ID 범위를 16bit로 변경한다. STD 에 필터 ID 범위는 16bit, 32bit 상관없다. 어차피 아이디가 11bit라서 아무튼 이렇게 설정하고 아래에 canFilter.FilterMaskIdHigh, canFilter.FilterMaskIdLow 변수를 보자.

 

0x7F0을 왼쪽으로 5칸 이동한 값을 각각 넣어줬다. 이제 이 부분에 대해 설명하겠다. (canFilter.FilterMaskIdHigh, canFilter.FilterMaskIdLow 두 변수에 값을 모두 넣어줘야 한다. 이유는.. 아직 잘 모르겠다 ㅋㅋㅋㅋ)

 

CAN의 Mask 값은 해당 비트가 1인 경우만 확인하고 0이면 don't care 다. 이게 무슨말이냐면.

현재 위 코드는 위 표와 같이 ID를 0x200 << 5, Mask 값을 0x7F0 << 5 으로 설정했다.  ID 값의 상위 7bit와 Mask 값의 상위 7bit 의 값중 둘 다 bit의 값이 1인 ID의 데이터만 통과시키겠다는 의미다. 아래 그림을 참고해 이해하기 바란다. 

이렇게 설정하면 하위 4bit는 don't care라서 0이던, 1이던 다 수신하게 된다. 

즉 0x200~0x20F사이의 ID로 들어오는 데이터를 수신할 수 있다.

 

CAN EXT(2.0B)도 동일한 원리다. 계산 방법도 위와 동일하다. 

위 표와같이 ID 값이 0x1F821990이고 Mask 값이 0x1FFFFFF8 이면 0x1F821990부터 0x1F821997까지 총 8개의 ID 값을 통과시킬 수 있다.

코드를 보자.

 

 

 

정리해보면

 

1. CAN은 하드웨어 레벨에서 원하는 ID의 데이터만 수신할 수 있는 Filter 기능이 있다.

2. ID의 필터링 범위(Scale)는 16bit 와 32bit가 있다.

3. 필터링 모드에는 list 모드와 mask 모드가 있다.

4. ID list 모드는 지정된 하나의 ID만 통과된다.

5. ID mask 모드는 지정된 범위의 모든 ID를 통과시킨다. 

6. 필터링에는 IDE와 RTR도 고려되어야 한다. 

7. 필터링 범위는 CAN의 버전과 관계없이 모두 적용 가능하다. 29bit ID를 갖는 EXT에도 16bit 필터링을 적용할 수 있다. 

8. CAN은 Tx ID와 Rx ID를 다르게 설정할 수 있다.

9. 같은 CAN 버스에 동일한 ID가 존재하면 안 된다.

 

 

 

최대한 자세히(?) 설명해보려고 노력했다. 혹시 이해가 안되는부분이 있거나 틀린 부분이 있다면, 댓글 부탁드립니다 

 

 

- 끝 -

728x90
반응형