본문 바로가기
Embedded SW/Embedded SW Introduction

CAN 구현 및 동작 수행 4편 (ECU 2개를 이용한 Tx, Rx)

by 방구석 임베디드 2022. 9. 14.
반응형

이제 두개의 ECU를 이용하여 Tx, Rx를 한번 해보도록 하겠습니다.

참고로 이글은 CAN 관련하여 연재하여 글을 쓰고 있습니다.

아래 글들을 미리 읽고 오시면 좋을 것 같습니다.

 

1) CAN이란 무엇인가?

https://embeddedchallenge.tistory.com/57

2) CAN의 CAN Controller/Transceiver 전압 레벨 (High Speed CAN)

https://embeddedchallenge.tistory.com/59

3) CAN 정보전달 방식

https://embeddedchallenge.tistory.com/60

4) CAN Frame 분석

https://embeddedchallenge.tistory.com/61

5) CAN Arbitration

https://embeddedchallenge.tistory.com/62

6) CAN 구현 및 동작 수행 1편 (TC275 MCU 예제코드 포팅)

https://embeddedchallenge.tistory.com/450

7) CAN 구현 및 동작 수행 3편 (CAN 초기화 코드 분석)

https://embeddedchallenge.tistory.com/452

 

그러면 이제 다시 시작해 보도록 하겠습니다.

아래 글에서 만든 CAN 초기화 코드를 조금 수정해 보도록 하겠습니다.

7) CAN 구현 및 동작 수행 3편 (CAN 초기화 코드 분석)
https://embeddedchallenge.tistory.com/452

불필요한 구조체는 제거하였고

Object에 값을 쉽게 넣을 수 있도록

전역변수를 배열로 변경하였습니다.

또한 Tx와 Rx를 구분하여 코드를 만들었습니다.

/***********************************************************************/
/*Define*/ 
/***********************************************************************/
#define ECU1_TX_OBJ_NUM     10u
#define ECU1_RX_OBJ_NUM     10u

/***********************************************************************/
/*Typedef*/ 
/***********************************************************************/
typedef struct
{
    IfxMultican_Can        CanEcu1;          
    IfxMultican_Can_Node   CanEcu1Node;   
    IfxMultican_Can_MsgObj CanEcu1MsgTxObj[ECU1_TX_OBJ_NUM]; 
    IfxMultican_Can_MsgObj CanEcu1MsgRxObj[ECU1_RX_OBJ_NUM]; 
} Ecu1Can;

또한 초기화 코드를 아래와 같이 수정하였습니다.

void Driver_Can_Init(void)
{
    /* create module config */
    IfxMultican_Can_Config canConfig;
    IfxMultican_Can_initModuleConfig(&canConfig, &MODULE_CAN);
    
    /* initialize module */
    IfxMultican_Can_initModule(&stEcu1Can.CanEcu1, &canConfig);

    /* create CAN node config */
    IfxMultican_Can_NodeConfig canNodeConfig;
    IfxMultican_Can_Node_initConfig(&canNodeConfig, &stEcu1Can.CanEcu1);

    canNodeConfig.baudrate = 500000UL;     /*500kbps*/
    canNodeConfig.nodeId    = (IfxMultican_NodeId)((int)IfxMultican_NodeId_0);
    canNodeConfig.rxPin     = &IfxMultican_RXD0B_P20_7_IN;
    canNodeConfig.rxPinMode = IfxPort_InputMode_pullUp;
    canNodeConfig.txPin     = &IfxMultican_TXD0_P20_8_OUT;
    canNodeConfig.txPinMode = IfxPort_OutputMode_pushPull;

    IfxMultican_Can_Node_init(&stEcu1Can.CanEcu1Node, &canNodeConfig);
   
    /* create message object config */
    IfxMultican_Can_MsgObjConfig canMsgObjConfig;
    IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &stEcu1Can.CanEcu1Node);

    canMsgObjConfig.msgObjId              = 0;
    canMsgObjConfig.messageId             = 0x100;
    canMsgObjConfig.acceptanceMask        = 0x7FFFFFFFUL;
    canMsgObjConfig.frame                 = IfxMultican_Frame_transmit;
    canMsgObjConfig.control.messageLen    = IfxMultican_DataLengthCode_8;
    canMsgObjConfig.control.extendedFrame = FALSE;
    canMsgObjConfig.control.matchingId    = TRUE;

    /* initialize message object */
    IfxMultican_Can_MsgObj_init(&stEcu1Can.CanEcu1MsgTxObj[0], &canMsgObjConfig);
}

뭐 크게 변경한것은 아니고요

변수이름만 조금 바뀌었네요 ㅎㅎ

또한 오브젝트를 설정하는 부분을 나누었는데요

Create message object config 라는 부분을 함수로 만들어서

Tx와 Rx 등록이 쉽게 이루어질수 있도록 코드 변경을 해보겠습니다.

void Driver_Can_Init(void)
{
    /* create module config */
    IfxMultican_Can_Config canConfig;
    IfxMultican_Can_initModuleConfig(&canConfig, &MODULE_CAN);
    
    /* initialize module */
    IfxMultican_Can_initModule(&stEcu1Can.CanEcu1, &canConfig);

    /* create CAN node config */
    IfxMultican_Can_NodeConfig canNodeConfig;
    IfxMultican_Can_Node_initConfig(&canNodeConfig, &stEcu1Can.CanEcu1);

    canNodeConfig.baudrate = 500000UL;     /*500kbps*/
    canNodeConfig.nodeId    = (IfxMultican_NodeId)((int)IfxMultican_NodeId_0);
    canNodeConfig.rxPin     = &IfxMultican_RXD0B_P20_7_IN;
    canNodeConfig.rxPinMode = IfxPort_InputMode_pullUp;
    canNodeConfig.txPin     = &IfxMultican_TXD0_P20_8_OUT;
    canNodeConfig.txPinMode = IfxPort_OutputMode_pushPull;

    IfxMultican_Can_Node_init(&stEcu1Can.CanEcu1Node, &canNodeConfig);

    /*Object Enrollment*/
    Driver_Can_EnrollObject(0u, 0x100, IfxMultican_Frame_transmit,  IfxMultican_DataLengthCode_8, FALSE, &stEcu1Can.CanEcu1MsgTxObj[0]);
    Driver_Can_EnrollObject(1u, 0x101, IfxMultican_Frame_transmit,  IfxMultican_DataLengthCode_8, FALSE, &stEcu1Can.CanEcu1MsgTxObj[1]);
    Driver_Can_EnrollObject(2u, 0x102, IfxMultican_Frame_transmit,  IfxMultican_DataLengthCode_8, FALSE, &stEcu1Can.CanEcu1MsgTxObj[2]);
}


static void Driver_Can_EnrollObject(int32_t msgObjId,  uint32_t msgId, uint8_t frameType, uint8_t msgDlc,  uint32_t extendedFrame, IfxMultican_Can_MsgObj* pArrObjNum)
{
    /* create message object config */
    IfxMultican_Can_MsgObjConfig canMsgObjConfig;
    IfxMultican_Can_MsgObj_initConfig(&canMsgObjConfig, &stEcu1Can.CanEcu1Node);

    canMsgObjConfig.msgObjId              = msgObjId;
    canMsgObjConfig.messageId             = msgId;
    canMsgObjConfig.frame                 = frameType;
    canMsgObjConfig.control.messageLen    = msgDlc;
    canMsgObjConfig.control.extendedFrame = extendedFrame;
    canMsgObjConfig.acceptanceMask        = 0x7FFFFFFFUL;
    canMsgObjConfig.control.matchingId    = TRUE;

    /* initialize message object */
    IfxMultican_Can_MsgObj_init(pArrObjNum, &canMsgObjConfig);
}

이렇게 등록을 하면 Tx와 Rx 등록이 편하게 등록할수가 있습니다.

코드도 조금더 깨끗해 지고요.

지금 저는 3개의 Tx 오브젝트를 할당하였습니다.

 

이제 물리적으로 TC275보드 2개를 이용하여 CAN을 연결하고

ECU2에서 0x200 ID로 10ms마다 CAN을 Tx해보도록 하겠습니다.

그리고 계측 포인트는 아래 그림에서 빨강색 박스를 친 부분을 계측해 보도록 하겠습니다.

ECU2은 0x200메세지를 ECU1에게 전달해 주고

저는 지금 ECU1의 빨강 박스의 부분을 계측하고 있는 것입니다.

지금 ECU1의 Tx라인에서 내려간것이 보이시나요?

ECU1은 지금 Rx항목으로 0x200 ID를 등록하지 않았습니다.

하지만 ECU1은 정상적인 CAN Rx를 수신하였기 때문에

자동적으로 Ack부분을 Low로 내려주고 있는것을 볼 수 있습니다.

만일 아무도 ECU1을 CAN Node에서 제거하면

아무도 Ack를 내려줄수 있는 ECU가 없기 때문에

ECU2는 10ms 간격보다 더 훨씬빠르게

약 50us 안되서 계속 동일한 메시지를 Tx합니다.

 

그러면 ECU1에서 자동적으로 Ack를 내려주기는 하였지만

아직 0x200의 ID가 왔을때

이 메세지의 데이터 정보를 획득하도록 설정하지는 않았기 때문에

데이터는 그냥 흘려버립니다.

 

이제, 미리 오브젝트 Rx설정을 하여 

0x200메시지가 왔을때 이 데이터를 가지고 올수 있도록

Rx 설정을 한번 해보도록 하겠습니다.

반응형

댓글