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를 초기화하고 전송해야 한다.
//메세지 오브젝트 초기화
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 인터럽트 핸들러
{
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]
);
}
}