CAN DBC 파일을 코드로 변환하는 오픈소스: CODERDBC
자동차 산업에서 CAN(Controller Area Network) 통신은 차량 내 전자 제어 장치(ECU) 간의 실시간 데이터 통신을 위한 중요한 프로토콜 입니다. 하지만 DBC(Database CAN)파일을 코드화 하는 것을 매우 번거롭습니다. 이 포스팅에서 dbc 파일을 C 코드로 자동 변환해주는 오픈소스 도구, CODERDBC를 사용해보고 실행 결과를 정리합니다.
DBC 파일이란?
DBC 파일은 CAN 네트워크의 모든 메시지와 신호를 정의하는 텍스트 기반 파일입니다. 이 파일은 CAN 버스 상의 모든 통신 규격을 상세히 기술합니다. 다음은 DBC 파일의 한 메시지 예시입니다.
BO_ 333 UTEST_2: 8 BCM
SG_ U8_TEST_1 : 39|8@0+ (1,0) [0|255] "" BMS
SG_ U7_TEST_1 : 47|7@0+ (1,-255) [-255|-128] "" BMS
SG_ ValTest : 30|2@0+ (1,0) [0|3] "c" ESP,BMS
SG_ U28_TEST_1 : 0|28@1+ (1,0) [0|4294967295] "" ESP,BMS
이 예제에서:
BO_ 333 UTEST_2: 8 BCM
는 ID가 333인 8바이트 길이의 UTEST_2 메시지를 정의하며, BCM(Body Control Module)에서 전송됩니다.SG_
로 시작하는 줄들은 각 신호를 정의합니다.
예를 들어, U8_TEST_1
을 자세히 살펴보면:
39|8@0+
: 39번째 비트에서 시작하는 8비트 길이의 빅 엔디안, 부호 없는 값(1,0)
: 스케일 1, 오프셋 0[0|255]
: 최소값 0, 최대값 255BMS
: 이 신호를 수신하는 ECU
CODERDBC: DBC to C 변환기
CODERDBC는 이러한 DBC 파일을 파싱하여 사용 가능한 C 코드로 변환합니다. 주요 기능은 다음과 같습니다:
- 메시지와 신호에 대한 구조체 생성
- 패킹/언패킹 함수 자동 생성
- ID 기반 메시지 라우팅 로직 구현
- 값 테이블을 열거형으로 변환
사용 방법
CODERDBC를 사용하는 방법은 다음과 같습니다.
GitHub에서 CODERDBC 클론하고 빌드합니다.
$ git clone https://github.com/astand/c-coderdbc.git
$ cd c-coderdbc
$ cmake -S src -B build cmake --build build --config release
이 저장소에 포함된 예제 test.dbc로 부터 코드를 생성합니다.
$ ./build/coderdbc -dbc ./test/testdb.dbc -out /home/makepluscode/c-coderdbc/out/ -drvname drivedb -nodeutils -rw -driverdir -gendate
out 디렉토리에 생성된 폴더와 파일의 내용은 다음과 같습니다.
$ tree ./out/
./out/
├── butl
│ ├── test-binutil.c
│ └── test-binutil.h
├── conf
│ ├── dbccodeconf.h
│ └── test-config.h
├── drivedb
│ ├── butl
│ │ ├── bcm_drivedb-binutil.c
│ │ ├── bcm_drivedb-binutil.h
│ │ ├── bms_drivedb-binutil.c
│ │ ├── bms_drivedb-binutil.h
│ │ ├── eps_drivedb-binutil.c
│ │ ├── eps_drivedb-binutil.h
│ │ ├── esp_drivedb-binutil.c
│ │ └── esp_drivedb-binutil.h
│ ├── conf
│ │ ├── dbccodeconf.h
│ │ └── drivedb-config.h
│ ├── inc
│ │ └── canmonitorutil.h
│ ├── lib
│ │ ├── drivedb-fmon.h
│ │ ├── drivedb.c
│ │ └── drivedb.h
│ └── usr
│ └── drivedb-fmon.c
├── inc
│ └── canmonitorutil.h
├── lib
│ ├── test-fmon.h
│ ├── test.c
│ └── test.h
└── usr
└── test-fmon.c
11 directories, 24 files
생성된 코드 분석: UTEST_2 메시지의 예
CODERDBC가 위의 UTEST_2 메시지에 대해 생성하는 코드를 살펴보겠습니다:
구조체 정의
typedef struct
{
uint8_t U8_TEST_1;
int8_t U7_TEST_1;
uint8_t ValTest;
uint32_t U28_TEST_1;
} UTEST_2_t;
이 구조체는 DBC 파일의 각 신호를 C 데이터 타입으로 매핑합니다.
언패킹 함수
uint32_t Unpack_UTEST_2_testdb(UTEST_2_t* _m, const uint8_t* _d)
{
uint32_t _id = 333;
_m->U8_TEST_1 = (_d[4] >> 7) | (_d[5] << 1);
_m->U7_TEST_1 = (int8_t)(((_d[5] >> 7) | (_d[6] << 1)) & 0x7F) - 255;
_m->ValTest = (_d[3] >> 6) & 0x03;
_m->U28_TEST_1 = (_d[0] >> 2) |
(_d[1] << 6) |
(_d[2] << 14) |
((_d[3] & 0x3F) << 22);
return _id;
}
이 함수는 원시 CAN 데이터를 파싱하여 구조체에 저장합니다. 각 라인은 DBC 파일의 비트 레이아웃을 정확히 반영합니다:
U8_TEST_1
: 5번째와 6번째 바이트에 걸쳐 있는 8비트를 추출합니다.U7_TEST_1
: 6번째와 7번째 바이트에서 7비트를 추출하고 255를 뺍니다 (오프셋 적용).ValTest
: 4번째 바이트의 상위 2비트를 추출합니다.U28_TEST_1
: 첫 4바이트에 걸쳐 있는 28비트를 리틀 엔디안 형식으로 추출합니다.
수신 함수에서의 사용
uint32_t testdb_Receive(testdb_rx_t* _m, const uint8_t* _d, uint32_t _id, uint8_t dlc_)
{
uint32_t recid = 0;
if (_id == 333) {
recid = Unpack_UTEST_2_testdb(&(_m->UTEST_2), _d);
}
// ... 다른 메시지 처리
return recid;
}
이 함수는 수신된 CAN 메시지의 ID를 확인하고 해당하는 언패킹 함수를 호출합니다. 결론적으로 오픈 소스로 제공되는 CODERDBC는 커뮤니티의 지속적인 개선과 확장이 가능하다는 점에서도 큰 장점을 가집니다.
관련링크
CODERDBC에 대해 더 자세히 알아보고 싶거나 직접 사용해 보고 싶다면 다음 링크를 참조하세요.
- CODERDBC 웹 애플리케이션: https://coderdbc.com/
- CODERDBC GitHub 저장소: https://github.com/astand/c-coderdbc
'Network' 카테고리의 다른 글
자동차 네트워크 CAN 캔통신 정의와 기본지식 (0) | 2025.01.03 |
---|---|
CAN TP (ISO-TP) 프로토콜의 정의와 구조 (0) | 2024.09.07 |