cancel
Showing results for 
Search instead for 
Did you mean: 

How to trigger CAN Callback (STM32L452) ?

BZERR.1
Associate

I'm currently trying to get a message from another can device and I can't figure out why my callback isn't triggering.

I can transmit a message without any problem however I can't receive any. I am using vector CANalyzer to check my bus.

I was trying to make something that looks like a ping, when i transmit, if the stm32 get the message, it transmit something on the bus. This is just to check my ability to communicate before going further in my development.

If I uncoment the lines in my filter config, I can read message by polling but not by interrupt.

Here is how I configure my CAN :

void CAN_Config(void)
 
{
 
   CAN_FilterTypeDef sFilterConfig;
 
 
   sFilterConfig.FilterBank = 0;
 
   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
 
   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
 
   //sFilterConfig.FilterIdHigh = 0x320 << 5;          // Ici, 320 est l'adresse de la carte. Il peux être différent pour chaque carte.
 
   sFilterConfig.FilterIdHigh = 0;
 
   sFilterConfig.FilterIdLow = 0;
 
   //sFilterConfig.FilterMaskIdHigh = 0xFFF << 5;      // Le masque peux servir à accepter une plage d'adresse au lieu d'une adresse unique.
 
   sFilterConfig.FilterMaskIdHigh = 0;
 
   sFilterConfig.FilterMaskIdLow = 0;
 
   sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
 
   sFilterConfig.FilterActivation = ENABLE;
 
   sFilterConfig.SlaveStartFilterBank = 14;
 
 
   HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); // Active le mode interruption
 
 
   TxHeader.StdId = 0x030;     // Détermine l'adresse du périphérique au quel la trame est destiné.
 
   // Si plusieurs périphériques sur le bus comprennent cette adresse dans leur filtre, ils recevront tous la trame.
 
   TxHeader.ExtId = 0x00;      // Adresse étendue, non utilisée dans note cas
 
   TxHeader.RTR = CAN_RTR_DATA; // Précise que la trame contient des données
 
   TxHeader.IDE = CAN_ID_STD;  // Précise que la trame est de type Standard
 
   TxHeader.DLC = 2;           // Précise le nombre d'octets de données que la trame transporte ( De 0 à 8 )
 
   TxHeader.TransmitGlobalTime = DISABLE;
 
   /*
 
   RxHeader.StdId = 0x030;     // Détermine l'adresse du périphérique au quel la trame est destiné.
 
   // Si plusieurs périphériques sur le bus comprennent cette adresse dans leur filtre, ils recevront tous la trame.
 
   RxHeader.ExtId = 0x00;      // Adresse étendue, non utilisée dans note cas
 
   RxHeader.RTR = CAN_RTR_DATA; // Précise que la trame contient des données
 
   RxHeader.IDE = CAN_ID_STD;  // Précise que la trame est de type Standard
 
   RxHeader.DLC = 2;           // Précise le nombre d'octets de données que la trame transporte ( De 0 à 8 )
 
   */
 
   //TxData[0] = 0x55; // Vous pouvez changer toutes les valeurs de Txdata[0] à Txdata[TxHeader.DLC - 1] (TxHeader.DLC étant défini ci dessus)
 
 
 
   HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);     // Configure le filtre comme ci-dessus
 
 
   HAL_CAN_Start(&hcan1);                                            // Démarre le périphérique CAN
 
 
}

How it's initiated :

static void MX_CAN1_Init(void)
 
{
 
 
   /* USER CODE BEGIN CAN1_Init 0 */
 
 
   /* USER CODE END CAN1_Init 0 */
 
 
   /* USER CODE BEGIN CAN1_Init 1 */
 
 
   /* USER CODE END CAN1_Init 1 */
 
   hcan1.Instance = CAN1;
 
   hcan1.Init.Prescaler = 20;
 
   hcan1.Init.Mode = CAN_MODE_NORMAL;
 
   hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
 
   hcan1.Init.TimeSeg1 = CAN_BS1_3TQ;
 
   hcan1.Init.TimeSeg2 = CAN_BS2_4TQ;
 
   hcan1.Init.TimeTriggeredMode = DISABLE;
 
   hcan1.Init.AutoBusOff = DISABLE;
 
   hcan1.Init.AutoWakeUp = DISABLE;
 
   hcan1.Init.AutoRetransmission = DISABLE;
 
   hcan1.Init.ReceiveFifoLocked = DISABLE;
 
   hcan1.Init.TransmitFifoPriority = DISABLE;
 
   if (HAL_CAN_Init(&hcan1) != HAL_OK)
 
   {
 
      Error_Handler();
 
   }
 
   /* USER CODE BEGIN CAN1_Init 2 */
 
 
   /* USER CODE END CAN1_Init 2 */
 
 
}

My callback function that I want to be called whenever I have a message with id 320

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
 
{
 
 
   uint8_t csend[] = {0x22,0x1e,0x13,0x14,0x15,0x16,0x17,0x18}; // Tx Buffer
 
 
   HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData); //Receive CAN bus message to canRX buffer
 
   CAN_Transmit(0x100,8,csend);
 
}
 
```
 
I guess the link to use the callback is made by this function :
 
```
 
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)
 
{
 
 HAL_CAN_StateTypeDef state = hcan->State;
 
 
 /* Check function parameters */
 
 assert_param(IS_CAN_IT(ActiveITs));
 
 
 if ((state == HAL_CAN_STATE_READY) ||
 
     (state == HAL_CAN_STATE_LISTENING))
 
 {
 
   /* Enable the selected interrupts */
 
   __HAL_CAN_ENABLE_IT(hcan, ActiveITs);
 
 
   /* Return function status */
 
   return HAL_OK;
 
 }
 
 else
 
 {
 
   /* Update error code */
 
   hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
 
 
   return HAL_ERROR;
 
 }
 
}

The stm32 HAL library describes HAL_CAN_RxFifo0MsgPendingCallback as follows :

/**
 
 * @brief Rx FIFO 0 message pending callback.
 
 * @param hcan pointer to a CAN_HandleTypeDef structure that contains
 
 *        the configuration information for the specified CAN.
 
 * @retval None
 
 */
 
__weak void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
 
{
 
 /* Prevent unused argument(s) compilation warning */
 
 UNUSED(hcan);
 
 
 /* NOTE : This function Should not be modified, when the callback is needed,
 
           the HAL_CAN_RxFifo0MsgPendingCallback could be implemented in the
 
           user file
 
  */
 
}

Thanks

1 REPLY 1
KnarfB
Principal III

Check the return codes (status) of all functions. Guess: you call HAL_CAN_ActivateNotification too early and it returns error. Debug-step though the code, you'll find it.