본문 바로가기

[TI]/TM4C

TM4C123 - CAN 통신 테스트

TM4C123 - CAN 통신 테스트




TM4C123 은 2채널의 CAN 듈이 있다. 기존  Stellaris 시리즈와 거의 유사하게 되어 있어 기존 코드 수정없이 사용가능하다.

■ CAN protocol version 2.0 part A/B
■ Bit rates up to 1 Mbps
■ 32 message objects with individual identifier masks
■ Maskable interrupt
■ Disable Automatic Retransmission mode for Time-Triggered CAN (TTCAN) applications
■ Programmable Loopback mode for self-test operation
■ Programmable FIFO mode enables storage of multiple message objects
■ Gluelessly attaches to an external CAN interface through the CANnTX and CANnRX signals



TM4C123 의 CAN통신 핀맵



기존과 조금 다른 점으로 CAN 핀맵을 리맵 할 수 있다는 것인데.. 테스트를 위해 PB4, PB5에 할당해서 테스트 하기로 했다.

CAN0RX -> PB4

CAN0TX -> PB5



EVB_DSP 보드에서 







EXP_SM EVM 보드에서






코드는 기본적으로 LM3S 시리즈의 CAN통신 예제와 동일하다. 


TM4C123 CAN 초기화 함수

기존과 조금 달라진 점은 CAN 통신 속도 설정하는 부분이 좀더 간단히 처리할 수 있도록 되어 있다.

    //포트클럭 설정

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);


    //CAN 포트 설정

    GPIOPinConfigure(GPIO_PB4_CAN0RX);

    GPIOPinConfigure(GPIO_PB5_CAN0TX);

    GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5);


    // CAN클럭 초기화

    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);


    // Initialize the CAN controller

    CANInit(CAN0_BASE);


    // CAN통신 속도 설정

    CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);



    // CAN interrupts 설정

    CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

    IntEnable(INT_CAN0);


    // Enable the CAN for operation.

    CANEnable(CAN0_BASE);



CAN 메세지 전송하기
CAN데이터를 전송하려면 먼저 CAN Message Object를 초기화하고 전송해야 한다.

tCANMsgObject g_MsgObjectRx;

//메세지 오브젝트 초기화
void CANConfigureNetwork(void)
{
    //TX용 CAN 메시제 오프젝트 초기화
    g_MsgObjectTx.ulMsgID = 0x02;   //CAN ID
    g_MsgObjectTx.ulMsgIDMask = 0;

    //인터럽트 설정
    g_MsgObjectTx.ulFlags = MSG_OBJ_TX_INT_ENABLE;

    //메세지 크기
    g_MsgObjectTx.ulMsgLen = MAX_CAN_MSG_SIZE;
    //메시지 버퍼 설정
    g_MsgObjectTx.pucMsgData = g_CanTxMsgBuffer;
}

//CAN 메세지 전송
void SendCanMsg(unsigned char MsgId, unsigned char ucEvent, unsigned char Data)
{
    //MsgId : Message Object의 번호(수신측에서는 의미없는 값이다.)
 
    g_MsgObjectTx.pucMsgData[0] = ucEvent;
    g_MsgObjectTx.pucMsgData[1] = Data;

 /*
    //필요에 따라서 설정
    g_MsgObjectTx.pucMsgData[2] = 0;
    g_MsgObjectTx.pucMsgData[3] = 0;
 
    g_MsgObjectTx.pucMsgData[4] = 0;
    g_MsgObjectTx.pucMsgData[5] = 0;
    g_MsgObjectTx.pucMsgData[6] = 0;
    g_MsgObjectTx.pucMsgData[7] = 0;
 */ 
 
    CANMessageSet(CAN0_BASE, MsgId, &g_MsgObjectTx, MSG_OBJ_TYPE_TX);
}




CAN메세지 수신하기
CAN데이터를 전송하려면 먼저 CAN Message Object를 초기화 해야 수신할 수 있다. 수신하고 싶은 ID를 msg.ulMsgID 에 정의 하고 CANMessageSet()함수로 설정 할 수 있다. 물론 message object개수(1~32)만큼 설정 가능하다.

//메세지 오브젝트 초기화
void CANConfigureNetwork(void)
{
 tCANMsgObject msg;

    //수신할 CAN ID
    msg.ulMsgID = 0x02;
    msg.ulMsgIDMask = 0;//0xFF;

    //인터럽트 사용
    msg.ulFlags = MSG_OBJ_RX_INT_ENABLE;

    //수신할 버퍼와 크기
    msg.ulMsgLen = MAX_CAN_MSG_SIZE;
    msg.pucMsgData = g_CanTxMsgBuffer;

    //수신할 message object 초기화 (message object : 1~32)
    CANMessageSet(CAN0_BASE, 1, &msg, MSG_OBJ_TYPE_RX);
}



CAN 인터럽트 핸들러

void CANHandler(void)
{
    unsigned long rx_id_status;

    //CAN 인터럽트의 상태값을 읽어온다
    rx_id_status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    
     //읽은후 지운다
    CANIntClear(CAN0_BASE, rx_id_status); 
      
 //CAN 인터럽트 처리
 if(rx_id_status)
 {
  //message object 깂을 읽어온다 - 읽어오면 지워진다
  CANMessageGet(CAN0_BASE, rx_id_status, &g_MsgObjectRx, 1);
  
  DebugPrint("[ID%02X %02X:%02x:%02x] : ", 
        rx_id_status,    //message object 번호
     g_MsgObjectRx.ulMsgID,  //수신한 CAN ID
     g_MsgObjectRx.ulMsgIDMask,
     g_MsgObjectRx.ulMsgLen 
     );

  //수신한 데이터 출력
  DebugPrint("%02x %02x %02x %02x | %02x %02x %02x %02x\r\n", 
    g_MsgObjectRx.pucMsgData[0],
    g_MsgObjectRx.pucMsgData[1],
    g_MsgObjectRx.pucMsgData[2],
    g_MsgObjectRx.pucMsgData[3],
    g_MsgObjectRx.pucMsgData[4],
    g_MsgObjectRx.pucMsgData[5],
    g_MsgObjectRx.pucMsgData[6],
    g_MsgObjectRx.pucMsgData[7]    
    ); 
 }
}




반응형