ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • dbc 파일에서 바이트 오더와 스타트 비트 위치와 LSB
    tip 2025. 8. 27. 09:13

    시작하기 전에

    • dbc 파일을 xlsx 파일로 변환하는 파이썬 스크립트를 작성했다. (블로그 작성 예정이다.)
    • xlsx 파일을 dbc 파일로 변환하는 파이썬 스크립트를 작성했다. xlsx2dbc :: hsl's tsmaster 사용기
    • cantools( CAN BUS tools — cantools 39.4.3.dev10+gcc02988 documentation)라는 파이썬 모듈을 이용했다.
    • cantools의 메시지 내 신호 시작 "위치"(start bit. 스타트 비트)를 지정하는 방법과 dbc 파일에서의 방법이 바이트 오더 (byte order)가
      • Intel (little endian)인 경우, 동일하다.
      • Motorola (big endian)인 경우, 다르다.
    • 이를 고려하여 스타트 비트를 변환을 해야 한다. 이것을 설명한다.

    cantools로 dbc를 xlsx로 변환한다면, 신호 시작 위치인 start bit의 변환을 고려해야 한다.

     

     

    개요

    • 신호 위치를 정하는데 필요한 요소: 바이트 오더, 스타트 비트, 길이
    • dbc의 신호 위치 지정법
    • cantools의 신호 위치 지정법
    • dbc에서 cantools로 신호 위치 변환 방법
    • cantools에서 dbc로 신호 위치 변환 방법 

     

     

    신호 위치를 정하는데 필요한 요소: 바이트 오더, 스타트 비트, 길이

    • 신호의 위치를 정하는데 바이트 오더, 스타트 비트, 길이 3 가지 요소가 필요하다. 길이는 직관적으로 이해할 수 있다. 바이트 오더와 스타트 비트를 설명한다.
    • 아래 그림은 CAN 데이터 영역의 바이트 위치와 비트 위치를 표시한 그림이다.
    Byte:       0        1        2        3        4        5        6        7
           +--------+--------+--------+--------+--------+--------+--------+--------+--- - -
           |        |        |        |        |        |        |        |        |
           +--------+--------+--------+--------+--------+--------+--------+--------+--- - -
    Bit:    7      0 15     8 23    16 31    24 39    32 47    40 55    48 63    56

    출처: CAN BUS tools — cantools 39.4.3.dev10+gcc02988 documentation

    • 바이트 오더에는 Intel (little endian) 방식과 Motorola (big endian) 방식이 있다. (CANdb++에서 Intel 혹은 Motorola를 선택하도록 되어있다. 그래서 little endian, big endian 대신 Intel, Motorola라고 했다. 앞으로 혼용하겠다.) 
    • Big endian 방식으로 스타트 비트가 2이고 길이가 5 비트인 신호를 데이터 영역에 표시하면 아래 그림과 같다.
    Byte:       0        1        2        3
           +--------+--------+--------+--- - -
           |    |432|10|     |        |
           +--------+--------+--------+--- - -
    Bit:    7      0 15     8 23    16 31
    • 위 그림에서 0으로 표시된 위치가 가장 낮은 자리(LSB: Least Significant Bit)이고, 4로 표시된 위치가 가장 높은 자리(MSB: Most Significant Bit)이다.
    • big endian의 경우, MSB가 스타트 비트인 것을 알 수 있다. 43210을 자리 위치 표시가 아니라 10진수로 생각하면, 4만을 먼저 전송하고, 3천, 2백, 1십, 0의 순서로 전송한다고 할 수 있다. 그래서 MSB의 4만이 스타트 수(비트)가 된다.  
    • 만일 위 5 비트 자리에 0b1_0011이라는 이진수가 있다면, 그 값은 10 진수로 19가 된다. (자리 수를 한 눈에 알 수 있도록 4번째 자리에 _ (underscore)를 넣어 띄어썼다.) 
    4  3  2  1  0    <- 자리
    1  0  0  1  1    <- 각 자리의 값
    |  |  |  |  |
    |  |  |  |  +--  1 --> 2^0 * 1 = 1 * 1 = 1
    |  |  |  +-----  1 --> 2^1 * 1 = 2 * 1 = 2
    |  |  +--------  0 --> 2^2 * 0 = 4 * 0 = 0
    |  +-----------  0 --> 2^3 * 0 = 8 * 0 = 0
    +--------------  1 --> 2^4 * 1 = 16 * 1 = 16
    
    1 + 2 + 0 + 0 + 16 = 19

     

    • Little endian 방식으로 스타트 비트(little endian의 경우, LSB가 스타트 비트이다.)가 2이고 길이가 9 비트인 신호를 데이터 영역에 표시하면 아래 그림과 같다.
    Byte:       0        1        2        3
           +--------+--------+--------+--- - -
           |543210| |    |876|        |
           +--------+--------+--------+--- - -
    Bit:    7      0 15     8 23    16 31
    • 위 그림에서 0으로 표시된 위치가 가장 낮은 자리(LSB: Least Significant Bit)이고, 8로 표시된 위치가 가장 높은 자리(MSB: Most Significant Bit)이다. 
    • big endian과 비교하여, 신호가 바이트 경계를 넘는 경우 표시 방법이 다르다. 
    • little endian의 경우, LSB가 스타트 비트인 것을 알 수 있다. 876543210을 자리 위치 표시가 아니라 10진수로 생각하면, 0을 먼저 전송하고, 1십, 2백, 3천, 4만, ... 의 순서로 전송한다고 할 수 있다. 그래서 LSB의 0이 스타트 수(비트)가 된다.  
    • 만일 위 9 비트 자리에 0b0_0001_0011이라는 이진수가 있다면, 그 값은 10 진수로 19가 된다. 
    8  7  6  5  4  3  2  1  0    <- 자리
    0  0  0  0  1  0  0  1  1    <- 각 자리의 값
    |  |  |  |  |  |  |  |  | 
    |  |  |  |  |  |  |  |  +--  1 --> 2^0 * 1 = 1 * 1 = 1
    |  |  |  |  |  |  |  +-----  1 --> 2^1 * 1 = 2 * 1 = 2
    |  |  |  |  |  |  +--------  0 --> 2^2 * 0 = 4 * 0 = 0
    |  |  |  |  |  +-----------  0 --> 2^3 * 0 = 8 * 0 = 0
    |  |  |  |  +--------------  1 --> 2^4 * 1 = 16 * 1 = 16
    |  |  |  +-----------------  0 --> 2^5 * 1 = 32 * 0 = 0  
    |  |  +--------------------  0 --> 2^6 * 1 = 64 * 0 = 0  
    |  +-----------------------  0 --> 2^7 * 1 = 128 * 0 = 0  
    +--------------------------  0 --> 2^8 * 1 = 256 * 0 = 0  
    
    1 + 2 + 0 + 0 + 16 + 0 + 0 + 0 + 0 = 19
    • 위에서 설명한 스타트 비트의 정의는 big/little endian의 정의에 따른다.
    • 포인트는 스타트 비트, 길이, 바이트 오더 3 가지를 알면 데이터 영역의 어디에 신호가 위치하는 지 알 수 있다는 것이다. 

     

     

    dbc의 신호 위치 지정법

    • dbc에서는 바이트 오더에 무관하게 "LSB" 위치를 스타트 비트로 한다. 
    • CANdb++에서 Motorola (big endian) 방법으로 13 비트 길이의 신호를 메시지에 추가한다면, (기존에 신호들이 있다고 가정한다.) CANdb++는 디폴트로 아래 그림과 같이 신호의 위치를 정한다.

    파란색 화살표는 그림에 추가한 것이다. big endian은 큰 자리수에서 작은 자리수로 읽는다고 생각하면 된다.

    • 이때 dbc의 신호 위치 지정은 아래와 같이 스타트 비트가 35이다. LSB 위치이다.

    dbc에서 Startbit는 Big Endian(Motorola)의 경우에도 LSB 위치이다.

     

    • CANdb++에서 Intel (little endian) 방법으로 13 비트 길이의 신호를 메시지에 추가한다면, (기존에 신호들이 있다고 가정한다.) CANdb++는 디폴트로 아래 그림과 같이 신호의 위치를 정한다.

    파란색 화살표는 그림에 추가한 것이다. little endian은 작은 자리수에서 큰 자리수로 읽는다고 생각하면 된다.

    • 이때 dbc의 신호 위치 지정은 아래와 같이 스타트 비트가 24이다. LSB 위치이다.

    dbc에서 Startbit는 Byte Order와 무관하게 LSB 위치이다.

     

     

    cantools의 신호 위치 지정법

    • cantools는 스타트 비트를 endian 정의에서 사용하는 스타트 비트 정의를 적용한다. 즉, dbc와 다르다.

     

     

    dbc에서 cantools로 신호 위치 변환 방법

    • dbc에서 cantools로 스타트 비트를 변환하려면,
      • little endian이면, 그대로 사용한다.
      • big endian이면, 위에 설명한 대로 변환을 해야 한다.
    • 이는 코드로는 아래와 같이 된다. claude ai가 짠 코드를 내 용도에 맞게 바꿨다. ChatGPT 4.1가 짠 코드는 오답이 발생한다. 
    def convert_msb_of_big_endian_to_lsb_of_big_endian(signal):
        '''
        cantools는 byte_order가
            big_endian인 경우, signal.start에는 MSB의 위치가 저장된다.
            little_endian인 경우, signal.start에는 LSB의 위치가 저장된다.
        dbc는 byte_order와 무관하게 signal.start에는 LSB의 위치가 저장된다.

        cantools에서 dbc를 db로 읽을 때, 위 변환이 이미 이뤄진다.
        xlsx에는 dbc의 형식이 사용된다.
        db를 xlsx로 변환할 때, 위 변환을 한다.
        '''

        if signal.byte_order == 'big_endian':
            start_bit_msb = int(signal.start)
            start_bit_lsb = start_bit_msb + 7 - 2 * (start_bit_msb % 8)
            start_bit_lsb += int(signal.length) - 1
            start_bit_lsb += 7 - 2 * (start_bit_lsb % 8)
            return start_bit_lsb
        else:
            return signal.start

     

     

    cantools에서 dbc로 신호 위치 변환 방법 

    • 위 변환의 역변환이다.
    • 코드로는 아래와 같이 된다. claude ai가 짠 코드를 내 용도에 맞게 바꿨다. ChatGPT 4.1가 짠 코드는 오답이 발생한다. 
    def convert_lsb_of_big_endian_to_msb_of_big_endian(start_bit_lsb, byte_order, length):
        '''
        cantools는 byte_order가
            big_endian인 경우, signal.start에는 MSB의 위치가 저장된다.
            little_endian인 경우, signal.start에는 LSB의 위치가 저장된다.
        dbc는 byte_order와 무관하게 signal.start에는 LSB의 위치가 저장된다.

        xlsx에는 dbc의 형식이 사용된다.
        xlsx를 db로 읽을 때, 신호의 byte_order가 big_endian이라면, start_bit에 저장된 LSB 위치를 MSB 위치로 변환한다.
        '''

        if byte_order == 'big_endian':
            start_bit_msb = start_bit_lsb + 7 - 2 * (start_bit_lsb % 8)
            start_bit_msb -= int(length) - 1
            start_bit_msb += 7 - 2 * (start_bit_msb % 8)
            return start_bit_msb
        else:
            return start_bit_lsb
     

     

     

     

    결론

    • dbc의 스타트 비트 정의는 big/little endian의 스타트 비트 정의와 다르다.
    • 파이썬의 cantools 모듈을 이용하여 dbc를 xlsx로 변환을 하는 과정은 dbc에서 cantools 변환, cantools에서 xlsx 변환하는 두 번의 변환으로 구성된다.
    • dbc에서 cantools로 변환할 때 스타트 비트 변환은 cantools에서 자동으로 이뤄진다.
    • dbc와 xlsx에 동일한 스타트 비트 정의를 적용한다면 (그렇게 안 하는 것은 사용자에게 더 복잡한 일이다.), cantools에서 xlsx로 변환할 때, 스타트 비트 변환을 해줘야 한다.
    • xlsx를 dbc로 변환할 때도 xlsx에서 cantools로 변환할 때, 스타트 비트 변환을 해줘야 한다.   

     

     

    목차 :: hsl's tsmaster 사용기    

    xlsx2dbc :: hsl's tsmaster 사용기    

    dbc 파일 인코딩 (encoding) :: hsl's tsmaster 사용기    

    'tip' 카테고리의 다른 글

    dbc2xlsx  (3) 2025.08.29
    dbc 파일 인코딩 (encoding)  (3) 2025.08.26
    xlsx2dbc  (1) 2025.08.22
    YouTube: 미니프로그램에서 엑셀 파일 다루는 방법  (0) 2025.08.19
    라이선스 업데이트  (3) 2025.07.10