2025-08-29 3:21 PM - last edited on 2025-09-12 2:47 AM by Andrew Neil
We are developing a product that needs the ability to run 3 separate CAN interfaces connected to 3 separate CAN buses. I have the NUCLEO-F413ZH and I can successfully initialize and start CAN1, CAN2, and CAN3 and transmit from each of them in a single application, but I only get RX interrupts on CAN3 when all 3 interfaces are initialized and started. Additionally, if I only initialize and start CAN1 or CAN3 in my application, I can transmit and receive from them, but not CAN2.
Pages 1076-1077 of the part datasheet/reference manual (RM0430) lists dual and single CAN peripheral configurations:
First question: is it possible to run all three CAN interfaces simultaneously and receive messages from each of them?
CAN2 doesn't have direct access to SRAM, so I think if I want to use CAN2 for receiving, I also need to enable CAN1. Is that correct?
I don't understand what is meant by the master/slave relationship between CAN1 and CAN2. It sounds like messages received on CAN2 need to "route" through CAN1 to get to SRAM, but I'm not sure. How should CAN1 and CAN 2 be configured so that I can receive messages on either interface?
Solved! Go to Solution.
2025-08-29 5:16 PM
When you configure the filters, you'd typically split the filters (28) in half and assign to accordingly to CAN1 and CAN2.
void CAN_SetFilter(CAN_MsgStruct *msg)
{
static CAN_FilterTypeDef sFilterConfig;
if(msg->hcan == &hcan1)
{
sFilterConfig.FilterBank = 0;
#if defined(CAN2)
sFilterConfig.SlaveStartFilterBank = 14;
#endif
}
#if defined(CAN2)
else if(msg->hcan == &hcan2)
{
sFilterConfig.FilterBank = 14;
sFilterConfig.SlaveStartFilterBank = 14;
}
#endif
#if defined(CAN3)
else if(msg->hcan == &hcan3)
{
sFilterConfig.FilterBank = 0;
}
#endif
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
if(HAL_CAN_ConfigFilter(msg->hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler(); // Error_Handler should never be called, so we won't worry about handling these errors.
}
if(HAL_CAN_Start(msg->hcan) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(msg->hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK)
{
Error_Handler();
}
}
2025-08-29 5:16 PM
When you configure the filters, you'd typically split the filters (28) in half and assign to accordingly to CAN1 and CAN2.
void CAN_SetFilter(CAN_MsgStruct *msg)
{
static CAN_FilterTypeDef sFilterConfig;
if(msg->hcan == &hcan1)
{
sFilterConfig.FilterBank = 0;
#if defined(CAN2)
sFilterConfig.SlaveStartFilterBank = 14;
#endif
}
#if defined(CAN2)
else if(msg->hcan == &hcan2)
{
sFilterConfig.FilterBank = 14;
sFilterConfig.SlaveStartFilterBank = 14;
}
#endif
#if defined(CAN3)
else if(msg->hcan == &hcan3)
{
sFilterConfig.FilterBank = 0;
}
#endif
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
if(HAL_CAN_ConfigFilter(msg->hcan, &sFilterConfig) != HAL_OK)
{
Error_Handler(); // Error_Handler should never be called, so we won't worry about handling these errors.
}
if(HAL_CAN_Start(msg->hcan) != HAL_OK)
{
Error_Handler();
}
if (HAL_CAN_ActivateNotification(msg->hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY) != HAL_OK)
{
Error_Handler();
}
}
2025-08-30 5:38 AM - edited 2025-08-30 5:56 AM
Hello,
Please read this article: STM32 in dual CAN configuration: bxCAN Filter bank explanation and relation with CAN2 Start Bank parameter
You can use all the CAN instances at the same time and indepedently. But you need to enable the APB clock of CAN1 when you need to use CAN2.
CAN3 is independent from CAN1/CAN2 from architecture standpoint.
2025-09-03 10:24 AM
Thank you, I got it working after reviewing your code. I was incorrectly setting the FilterBank to 0 for the CAN2 filter, and it should have instead been set to the SlaveStartFilterBank value for CAN1's filter (or higher). After fixing that I can now transmit and receive from all 3 CAN interfaces within the same application.