[myUSB] STM32 EVM CAN Interrupt Test
STM32 (myUSB EVM)보드와 LM3S5732 EVM보드를 이용하여 CAN통신 테스트를 해 보았다. CAN인터럽트를 이용하여 데이터를 수신하도록 했다.
지난번에 폴링으로 테스트 하긴 했는데... 새롭게 하려니 또 시간이 많이 소비되는것 같다. 서로 다른 보드의 환경설정 하는데 시간이 많이 걸렸다. 정리만 잘 해두었어도 시간을 많이 줄일 수 있었는데... 다시한번 정리해 보도록 한다.
모터 제어 확장 보드의 LM3S5732에서 SW7를 누르면 CAN데이터가 전송되도록 했다.
STM32 CAN인터럽트
인터럽트 소스는 여러가지 있지만 가장 많이 사용하게 될 소스는 CAN_RF0R, CAN_RF1R 이다. CAN 데이터가 Mailbox에 정상적으로 저장되면 이벤트를 발생하게 된다.
물론 초기화시에 CAN->IER 레지스터에 CAN_RF0R_FMP0로 사용 여부를 설정해야 된다.
ST에서 제공하는 함수로 CAN_ITConfig()를 사용하면 쉽게 설정 가능하다.
/* CAN FIFO0 message pending interrupt enable */
CAN_ITConfig(CAN_IT_FMP0, ENABLE);
/******************* Bit definition for CAN_RF0R register *******************/
#define CAN_RF0R_FMP0 ((u8)0x03) /* FIFO 0 Message Pending */
#define CAN_RF0R_FULL0 ((u8)0x08) /* FIFO 0 Full */
#define CAN_RF0R_FOVR0 ((u8)0x10) /* FIFO 0 Overrun */
#define CAN_RF0R_RFOM0 ((u8)0x20) /* Release FIFO 0 Output Mailbox */
#define CAN_IT_FMP0 ((u32)0x00000002) /* FIFO 0 message pending */
USB와 CAN을 동시에 사용할 경우 인터럽트 소스를 구분할 필요가 있는데 FIFO pending를 알아내려면 ST제공 예제의 CAN_GetITStatus() 함수 에서는 추가가 되어 있이 않아서 추가했다.
[stm32f10x_can.c]
소스코드
//-----------------------------------------------------------------------------
int main(void)
{
unsigned char flag_sw1 = 0;
//System Init
SystemInit();
//LED Init
Led1Init();
Led1On();
Led2Init();
Led2Off();
Sw1Init();
//Serial Init
DebugInit(BAUD_115200);
DebugPrint("STM32 CAN Test Program..\r\n");
//CAN Init
CAN_initial();
while (1)
{
if(gFlagCanInt)
{
DebugPrint("[ID %02X:%02x:%02x] : ",
g_MsgObjectRx.StdId, //수신한 CAN ID
g_MsgObjectRx.IDE,
g_MsgObjectRx.DLC
);
//수신한 데이터 출력
DebugPrint("%02x %02x %02x %02x | %02x %02x %02x %02x\r\n",
g_MsgObjectRx.Data[0],
g_MsgObjectRx.Data[1],
g_MsgObjectRx.Data[2],
g_MsgObjectRx.Data[3],
g_MsgObjectRx.Data[4],
g_MsgObjectRx.Data[5],
g_MsgObjectRx.Data[6],
g_MsgObjectRx.Data[7]
);
gFlagCanInt = 0;
}
:
}
테스트 결과 시리얼포트 출력 화면
CAN통신 보레이트 설정
#ifdef CAM_BAUD_125KB
CAN_InitStructure.CAN_Prescaler = 16;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_250KB
CAN_InitStructure.CAN_Prescaler = 8;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_500KB
CAN_InitStructure.CAN_Prescaler = 4;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_1000KB
CAN_InitStructure.CAN_Prescaler = 2;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
STM32 (myUSB EVM)보드와 LM3S5732 EVM보드를 이용하여 CAN통신 테스트를 해 보았다. CAN인터럽트를 이용하여 데이터를 수신하도록 했다.
지난번에 폴링으로 테스트 하긴 했는데... 새롭게 하려니 또 시간이 많이 소비되는것 같다. 서로 다른 보드의 환경설정 하는데 시간이 많이 걸렸다. 정리만 잘 해두었어도 시간을 많이 줄일 수 있었는데... 다시한번 정리해 보도록 한다.
모터 제어 확장 보드의 LM3S5732에서 SW7를 누르면 CAN데이터가 전송되도록 했다.
STM32 CAN인터럽트
인터럽트 소스는 여러가지 있지만 가장 많이 사용하게 될 소스는 CAN_RF0R, CAN_RF1R 이다. CAN 데이터가 Mailbox에 정상적으로 저장되면 이벤트를 발생하게 된다.
물론 초기화시에 CAN->IER 레지스터에 CAN_RF0R_FMP0로 사용 여부를 설정해야 된다.
ST에서 제공하는 함수로 CAN_ITConfig()를 사용하면 쉽게 설정 가능하다.
/* CAN FIFO0 message pending interrupt enable */
CAN_ITConfig(CAN_IT_FMP0, ENABLE);
/******************* Bit definition for CAN_RF0R register *******************/
#define CAN_RF0R_FMP0 ((u8)0x03) /* FIFO 0 Message Pending */
#define CAN_RF0R_FULL0 ((u8)0x08) /* FIFO 0 Full */
#define CAN_RF0R_FOVR0 ((u8)0x10) /* FIFO 0 Overrun */
#define CAN_RF0R_RFOM0 ((u8)0x20) /* Release FIFO 0 Output Mailbox */
#define CAN_IT_FMP0 ((u32)0x00000002) /* FIFO 0 message pending */
USB와 CAN을 동시에 사용할 경우 인터럽트 소스를 구분할 필요가 있는데 FIFO pending를 알아내려면 ST제공 예제의 CAN_GetITStatus() 함수 에서는 추가가 되어 있이 않아서 추가했다.
[stm32f10x_can.c]
ITStatus CAN_GetITStatus(u32 CAN_IT)
{
:
case CAN_IT_FMP0:
pendingbitstatus = CheckITStatus(CAN->RF0R, CAN_RF0R_FMP0);
break;
default :
pendingbitstatus = RESET;
break;
}
pendingbitstatus = CheckITStatus(CAN->RF0R, CAN_RF0R_FMP0);
break;
default :
pendingbitstatus = RESET;
break;
}
소스코드
//CAN Interrupt
void USB_LP_CAN_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN_IT_FMP0) == SET)
{
CAN_Receive(CAN_FIFO0, &gRxMessage);
gFlagCanInt = 1;
void USB_LP_CAN_RX0_IRQHandler(void)
{
if(CAN_GetITStatus(CAN_IT_FMP0) == SET)
{
CAN_Receive(CAN_FIFO0, &gRxMessage);
gFlagCanInt = 1;
}
}
}
//-----------------------------------------------------------------------------
int main(void)
{
unsigned char flag_sw1 = 0;
//System Init
SystemInit();
//LED Init
Led1Init();
Led1On();
Led2Init();
Led2Off();
Sw1Init();
//Serial Init
DebugInit(BAUD_115200);
DebugPrint("STM32 CAN Test Program..\r\n");
//CAN Init
CAN_initial();
while (1)
{
if(gFlagCanInt)
{
DebugPrint("[ID %02X:%02x:%02x] : ",
g_MsgObjectRx.StdId, //수신한 CAN ID
g_MsgObjectRx.IDE,
g_MsgObjectRx.DLC
);
//수신한 데이터 출력
DebugPrint("%02x %02x %02x %02x | %02x %02x %02x %02x\r\n",
g_MsgObjectRx.Data[0],
g_MsgObjectRx.Data[1],
g_MsgObjectRx.Data[2],
g_MsgObjectRx.Data[3],
g_MsgObjectRx.Data[4],
g_MsgObjectRx.Data[5],
g_MsgObjectRx.Data[6],
g_MsgObjectRx.Data[7]
);
gFlagCanInt = 0;
}
:
}
테스트 결과 시리얼포트 출력 화면
STM32 CAN Test Program..
[ID 04:00:08] : 01 09 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0a 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0b 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0c 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0d 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0e 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0f 00 00 | 00 00 00 00
[ID 04:00:08] : 01 10 00 00 | 00 00 00 00
[ID 04:00:08] : 01 09 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0a 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0b 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0c 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0d 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0e 00 00 | 00 00 00 00
[ID 04:00:08] : 01 0f 00 00 | 00 00 00 00
[ID 04:00:08] : 01 10 00 00 | 00 00 00 00
CAN통신 보레이트 설정
#ifdef CAM_BAUD_125KB
CAN_InitStructure.CAN_Prescaler = 16;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_250KB
CAN_InitStructure.CAN_Prescaler = 8;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_500KB
CAN_InitStructure.CAN_Prescaler = 4;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
#ifdef CAM_BAUD_1000KB
CAN_InitStructure.CAN_Prescaler = 2;
CAN_InitStructure.CAN_BS1 = 8;
CAN_InitStructure.CAN_BS2 = 7;
#endif
반응형