2017-04-03 08:47 AM
I'm trying to get the STM32F4 Discovery board to transmit and receive CAN frames.
I've already got it to work with polling, now I'm trying to get the transmit and receive interrupts working.
The transmit interrupt works flawlessly, however, the receive interrupt isn't working.
Everytime I try to send a can frame to the STM32F4, it freezes in the
HAL_CAN_RxCpltCallback function, leaving the led on.
Here is the code:
CAN configuration and interrupts priority:
void
HAL_CAN_MspInit(CAN_HandleTypeDef
* hcan){
GPIO_InitTypeDef
GPIO_InitStruct;
if
(hcan->Instance
==CAN1){
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_CAN1_CLK_ENABLE();
/**CAN1 GPIO Configuration
PB8 ------> CAN1_RX
PB9 ------> CAN1_TX
*/
GPIO_InitStruct.
Pin
= GPIO_PIN_8|GPIO_PIN_9;GPIO_InitStruct.
Mode
= GPIO_MODE_AF_PP;GPIO_InitStruct.
Pull
= GPIO_NOPULL;GPIO_InitStruct.
Speed
= GPIO_SPEED_FREQ_VERY_HIGH;GPIO_InitStruct.
Alternate
= GPIO_AF9_CAN1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt
init
*/HAL_NVIC_SetPriority(
CAN1_TX_IRQn
, 0, 2);HAL_NVIC_EnableIRQ(
CAN1_TX_IRQn
);HAL_NVIC_SetPriority(
CAN1_RX0_IRQn
, 0, 0);HAL_NVIC_EnableIRQ(
CAN1_RX0_IRQn
);/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
main function:
MX_GPIO_Init();
static
CanTxMsgTypeDef
TxMessage1;
static
CanRxMsgTypeDef
RxMessage1;/*##-1- Configure the CAN peripheral #######################################*/CanHandle1.
Instance
= CAN1;CanHandle1.
pTxMsg
= &TxMessage1;CanHandle1.
pRxMsg
= &RxMessage1;CAN_FilterConfTypeDef
sFilterConfig1;
/*##-1- Configure the CAN peripheral #######################################*/
CanHandle1.
Init
.TTCM
=DISABLE
;CanHandle1.
Init
.ABOM
=DISABLE
;CanHandle1.
Init
.AWUM
=DISABLE
;CanHandle1.
Init
.NART
=DISABLE
;CanHandle1.
Init
.RFLM
=DISABLE
;CanHandle1.
Init
.TXFP
=DISABLE
;CanHandle1.
Init
.Mode
= CAN_MODE_NORMAL;CanHandle1.
Init
.SJW
= CAN_SJW_3TQ;CanHandle1.
Init
.BS1
= CAN_BS1_4TQ;CanHandle1.
Init
.BS2
= CAN_BS2_3TQ;CanHandle1.
Init
.Prescaler
= 4;
if
(HAL_CAN_Init(&CanHandle1) !=HAL_OK
){
/* Initialization Error */
Error_Handler();
}
/*##-2- Configure the CAN Filter ###########################################*/
sFilterConfig1.
FilterNumber
= 1;sFilterConfig1.
FilterMode
= CAN_FILTERMODE_IDMASK;sFilterConfig1.
FilterScale
= CAN_FILTERSCALE_32BIT;sFilterConfig1.
FilterIdHigh
= 0x0000;sFilterConfig1.
FilterIdLow
= 0x0000;sFilterConfig1.
FilterMaskIdHigh
= 0x0000;sFilterConfig1.
FilterMaskIdLow
= 0x0000;sFilterConfig1.
FilterFIFOAssignment
= 0;sFilterConfig1.
FilterActivation
= 1;sFilterConfig1.
BankNumber
= 0;
if
(HAL_CAN_ConfigFilter(&CanHandle1, &sFilterConfig1) !=HAL_OK
){
Error_Handler();
}
if
(HAL_CAN_Receive_IT(&CanHandle1, CAN_FIFO0) !=HAL_OK
){
Error_Handler();
}
i=0;
// Infinite loop
while
(1){
if
(HAL_CAN_Transmit_IT(&CanHandle1) !=HAL_OK
){
/* Transmission Error */
Error_Handler();
}
HAL_Delay(200);
}
}
Receive interrupt callback:
void
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef
* CanHandle){HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15,
GPIO_PIN_SET
);HAL_Delay(30);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15,
GPIO_PIN_RESET
);}
Transmit nterrupt callback:
void
HAL_CAN_TxCpltCallback(CAN_HandleTypeDef
* CanHandle){HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14,
GPIO_PIN_SET
);HAL_Delay(30);
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14,
GPIO_PIN_RESET
);}
2017-04-03 04:25 PM
Hi,
running any blocking code like HAL_Delay, is likely to be your problem.
if you want to see the pulse on the scope, just use a loop bu make sure it is not removed by the compiler.
I just send blocks to the Can Tx systems without interrupts, but I use interrupts on the RX side so that I don't miss any.
I dump the Rx frame into a table of frames with 64 entries, then the foreground just looks to see if the frame buffer is empty.
ie. if ( ! canRxMsgTableEMPTY){//process Can Rx frame}
I use these to initialise the interrupts
__HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP1);
__HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP0);the interrupt;
void CEC_CAN_IRQHandler(void)
{ /* USER CODE BEGIN CEC_CAN_IRQn 0 */ CAN_IRQFlag = true; // not needed, just used to show interrupt occurred checkCanRxFifos(); // clear the data before HAL sees it/* USER CODE END CEC_CAN_IRQn 0 */
HAL_CAN_IRQHandler(&hcan); // nothing to process now. /* USER CODE BEGIN CEC_CAN_IRQn 1 *//* USER CODE END CEC_CAN_IRQn 1 */
}the Rx function;
void checkCanRxFifos(void){
int readCanBytecount; char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1; if(canFifo1FullFlag){ { readCanBytecount = (CAN->sFIFOMailBox[1].RDTR &0x0f); canFifoBuf.d32[0] = CAN->sFIFOMailBox[1].RDLR; canFifoBuf.d32[1] = CAN->sFIFOMailBox[1].RDHR; canRxMsgID [canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21; CAN->RF1R |= CAN_RF1R_RFOM1; // release FIFOcanRxMsgLength [canRxMsgIN] = readCanBytecount;
canRxMsgBottomWord[canRxMsgIN] = canFifoBuf.d32[0]; canRxMsgTopWord [canRxMsgIN] = canFifoBuf.d32[1]; ++ canRxMsgIN &= 0x3F; // 64 entries only canRxMsgTableEMPTY = false; if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;}
CAN->IER |= CAN_IER_FMPIE1; // (11) Set FIFO1 message pending IT enable }char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;
if(canFifo0FullFlag){ { readCanBytecount = (CAN->sFIFOMailBox[0].RDTR &0x0f); canFifoBuf.d32[0] = CAN->sFIFOMailBox[0].RDLR; canFifoBuf.d32[1] = CAN->sFIFOMailBox[0].RDHR; uint32_t canRxmsgID = CAN->sFIFOMailBox[0].RIR >> 21; CAN->RF0R |= CAN_RF0R_RFOM0; // release FIFOif ( canRxMsgTableFULL){
canRxMsgTableOverflow = true; // now dump new frame... }else{ canRxMsgID [canRxMsgIN] = canRxmsgID; canRxMsgLength [canRxMsgIN] = readCanBytecount; canRxMsgBottomWord[canRxMsgIN] = canFifoBuf.d32[0]; canRxMsgTopWord [canRxMsgIN] = canFifoBuf.d32[1]; ++ canRxMsgIN &= 0x3F; // 64 entries only canRxMsgTableEMPTY = false; if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true; } } CAN->IER |= CAN_IER_FMPIE0; // (11) Set FIFO1 message pending IT enable }}