ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C 미니프로그램에서 CAN 신호를 다루기
    design 2026. 3. 19. 16:08

    시작하기 전에

    C 미니프로그램에서 CAN 메시지 송수신하기 :: hsl's tsmaster 사용기에서 "메시지" 수준에서 데이터를 다뤘다. '"신호" 수준에서 데이터를 다룰 수 있는가?' 궁금했다. 해봤다. 된다. 이 방법을 설명한다. 

     

     

    개요

    • 프로젝트 설계
    • dbc 임포트
    • 미니프로그램
      • On CAN Rx
      • 코드에서 dbc의 메시지/신호 사용하는 방법
      • 코드
    • 나머지 설정
    • 힌트를 얻은 곳
    • 실행 결과

     

     

    프로젝트 설계

    • C 미니프로그램에서 CAN 메시지 송수신하기 :: hsl's tsmaster 사용기와 동일한 하드웨어 설정이다.
    • 메시지/신호들이 정의된 dbc를 임포트한다. 내가 작성해서 사용 중인 venue_esc.dbc를 사용한다.
    • 대상 메시지와 신호를 선정한다. 나는 ESP 메시지의 ESP_counter 신호를 대상으로 정했다. 
    • 트랜스밋창에서 ESP 메시지를 전송한다. 
    • 미니프로그램에서 ESP 메시지를 수신하면 아래 동작을 하도록 한다.
      • 메시지가 채널 2에서 수신된 경우 실행한다.
      • 메시지의 데이터를 dbc에 정의된 구조에 따라 신호들로 파싱한다.
      • ESP_counter 신호에  + 1한다.
      • ESP 메시지를 복사하여 송신할 메시지를 만든다. 송신할 메시지의 데이터는 위에서 수정된 데이터이다.
      • 송신할 메시지의 아이디를 변경한다. 그렇지 않으면 ESP 메시지와 동일한 메시지 아이디로 송신된다.
    • 미니프로그램 작동을 Trace 창에서 확인한다.
      • 송신과 수신 메시지를 구분하기 위해서
        • 채널 1번과 채널 2번용 트레이스창을 각각 생성한다.
        • 각 트레이스창에 채널 필터를 적용한다.

     

     

    dbc 임포트

    • dbc 파일을 TSMaster 창에 드래그&드롭한다. CAN Database 창이 열린다. dbc가 Channel 1에 연결되어 있다.
    • venue_esc.dbc에는 ESP(0x220) 메시지가 있다. 그 안에는 4 bit 길이의 ESP_counter 신호가 있다. 
    • 이 신호를 대상으로 읽기/쓰기를 해본다.

     

     

    미니프로그램

    On CAN Rx

    • On CAN Rx 에서 마우스 우클릭으로 Add On Rx - CAN Message를 선택한 후, Id의 드롭다운리스트에서 0x220=ESP 선택한다. 나는 함수 이름에 넣을 문구로 ESP를 입력했다.

     

    • void on_can_rx_ ESP (const TCAN* ACAN) 함수의 뼈대가 만들어졌다.

    코드에서 dbc의 메시지/신호 사용하는 방법

    • 미니프로그램에서 ESP 메시지와 신호들을 사용하기 위해서, Properties 탭의 Database Symbols에서 "venue_esc.pdbc"를 체크하여 포함한다. (pdbc 파일은 dbc 파일을 TSMaster가 변환한 파일이다. TSMaster는 dbc 파일을 직접 사용하지 않고, pdbc 파일을 사용하는 것 같다.)

    • Functions 탭으로 가면 venue_esc.dbc에 정의된 메시지/신호들이 포함된 것을 볼 수 있다. 코드에서 메시지를 사용하고 싶으면, 메시지를 마우스 우클릭하고 Insert into script를 하면 된다. 
    • TESP_1 (_1은 '채널 1'이라는 의미이다.) 이라는 타입으로 ESP_1 변수를 선언한다. ESP_1 변수를 사용하기 전에 ESP_1.init() 문으로 초기화를 해야 한다.
    • ESP_1.FCAN = *ACAN 라는 한 줄의 코드로 CAN 메시지를 ESP_1 메시지의 구조에 따라 파싱할 수 있다. ACANvoid on_can_rx_ESP (const TCAN* ACAN)의 인자이다. 즉, 수신된 메시지다.  
    • *ACAN = ESP_1.FCAN 라는 한 줄의 코드로 ESP_1 변수를 CAN 메시지에 할당할 수 있다. ACAN 은  메시지를 전송하는 com.transmit_can_async(ACAN) 의 인자로 사용될 수 있다. 

    • 신호를 사용하고 싶으면, 신호를 마우스 우클릭하고 Insert into script를 하면 된다. 변수의 신호에 해당하는 부분은 "메시지.신호"로 형식으로 사용할 수 있다. ESP_1.ESP_counter는 ESP_1 메시지 형식의 변수에서 ESP_counter 부분이다. 

    코드

    • 코드를 입력한다. 코드의 작용은 커멘트로 설명하였다.

     

    더보기
    // venue_esc.dbc에는ESP 메시지가 정의되어 있다.
    // ESP 메시지에는 ESP_counter 신호가 있다.
    // ESP 메시지를 수신하면, ESP_counter 신호에 + 1을 하고
    // ESP 메시지의 아이디(= 0x220)에 + 0x100한 메시지에 (= 0x320)
    // 변경된 데이터를 담아 송신한다.
    
    // 수신 채널이 2번일 경우에만 실행한다.
    if (ACAN->FIdxChn != CH2) return; 
    
    // 수신한 ESP 메시지를 담을 변수 my_ESP_1을 선언한다.
    // 변수 이름은 자유롭게 정하면 된다. 
    // ESP 메시지는 TESP_1 형식의 변수로 선언된다. 
    // TESP로 하면 될 것 같은데 _1이 붙어있다. _1은 
    // 채널 1에 할당된 dbc의 정의에 따른다는 의미이다.
    TESP_1 my_ESP_1;
    
    // 메시지 송신에 사용할 변수를 선언한다. 
    TCAN m_tx;
    
    // my_ESP_1 변수를 사용하기 전에 초기화(init) 해야한다.
    my_ESP_1.init(); 
    
    // 수신한 ACAN 메시지를 my_ESP_1 메시지의 FCAN에 할당하여
    // ESP 메시지의 구조에 따라 파싱한다. 
    // 파싱이 코드 한 줄로 간단하다.
    my_ESP_1.FCAN = *ACAN; 
    
    // ESP_counter 신호에 + 1 한다.
    my_ESP_1.ESP_counter = my_ESP_1.ESP_counter + 1;
    
    // 송신에 사용할 m_tx에 my_ESP_1 메시지를 할당한다.
    m_tx = my_ESP_1.FCAN;
    
    // [중요] 바로 위에서 m_tx 메시지의 채널과 아이디가
    // my_ESP_1 메시지의 채널과 아이디로 변경되었다.
    // m_tx 메시지 채널과 아이디를 바꾸고자 한다면,
    // 위 실행문 다음에 실행되도록 해야 한다.
    m_tx.FIdxChn = 1; // 채널 2번
    m_tx.FIdentifier = (ACAN->FIdentifier + 0x100);
    
    // System Message 창에 출력한다. 
    // log("0x%03x  0x%03x",  ACAN->FIdentifier, m_tx.FIdentifier);
    // log("0x%02x  0x%02x",  ACAN->FData[7], m_tx.FData[7]);
    
    // m_tx 메시지를 송신한다.
    if (0 != com.transmit_can_async(&m_tx)){
        // 송신에 실패하면 System Messages 창에 ERROR를 출력한다.
        log("ERROR: Tx 0x%03x", m_tx.FIdentifier);
    }
    
    return;

     

     

    나머지 설정

    트랜스밋창

    • 트랜스밋창을 연다.
    • dbc에서 메시지를 추가한다. 그렇게 하기 위해 트랜스밋창 상단의 첫번째 버튼을 클릭한다.

    • CAN Database 창이 열리면 ESP 메시지를 선택한다. 

    • ESP 메시지를 선택하고, Signals 탭에 나열된 신호들의 값을 변경한다. 나는 아래 그림과 같이 변경하였다. 변경의 목적은 데이터가 모두 0x00으로 채워지지 않도록 하기 위해서다.

    트레이스창들

     

     

    힌트를 얻은 곳

    • 위에서 설명한 Insert into script에서 변수 사용법의 힌트를 얻었다.

     

     

    실행 결과

    • 실행 결과는 아래 비디오와 같다. 
    • 미니프로그램을 실행한다. 
    • Start 버튼을 클릭하여 버스를 연결한다. 
    • 트랜스밋창에서 ESP(0x220) 메시지를 전송한다.
    • 채널 1을 표시하는 위쪽 트레이스창에서 ESP(0x220) 메시지가 송신(Tx)되는 것을 확인한다.
    • 채널 2를 표시하는 아래쪽 트레이스창에서 ESP(0x220) 메시지가 수신(Rx)되는 것을 확인한다.
    • 아래쪽 트레이스창에서 0x320 메시지가 송신되는 것을 확인한다.
    • 위쪽 트레이스창에서 0x320 메시지가 수신되는 것을 확인한다.  
    • 0x320 메시지의 ESP_counter 부분이 업데이트되는 것을 확인한다.
    • https://www.youtube.com/watch?v=NLXnZ8gtDaY

     

     

     

    결론

    • TSMaster의 C 미니프로램을 이용하여 메시지를 수신하고, 신호를 변경하고, 변경된 신호가 포함된 데이터를 새 메시지에 실어서 송신하는 예제를 작성하였다.
    • 생각보다 쉽다.