cancel
Showing results for 
Search instead for 
Did you mean: 

How to differentiate which CANBUS a message is received on using STM32F4?

WTetl.2
Associate II

I have an STM32F403ZH Nucleo board and it's connected to three separate CAN channels. I would like to be able to receive identical messages on any channel (same identifier, baud rate, etc) and have the microcontroller be able to determine which one it came from so it can handle it differently. This would allow my three identical devices to not have to be reprogrammed to send messages with different identifiers.

I've been looking through the reference manual and I don't think it's possible. The 3 different CAN controllers all send the same interrupt to the main controller. No trace of which CAN controller sent the interrupt or received the message is stored when the message is sent to the FIFO, or in the mailbox when the main controller receives the message from the FIFO. I could differentiate between two channels by having them output into different FIFOs, but not three. If anybody knows a way then I'd be happy to hear it. Thank you.

1 ACCEPTED SOLUTION

Accepted Solutions
Karl Yamashita
Lead III

You need to compare the CAN instance

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == hcan1.Instance)
	{
		if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can1_header, can1_data) != HAL_OK)
		{
			// error handler
		}
	}
	else if(hcan->Instance == hcan2.Instance)
	{
		if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can2_header, can2_data) != HAL_OK)
		{
			// error handler
		}
	}
}

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.

View solution in original post

3 REPLIES 3
Karl Yamashita
Lead III

You need to compare the CAN instance

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance == hcan1.Instance)
	{
		if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can1_header, can1_data) != HAL_OK)
		{
			// error handler
		}
	}
	else if(hcan->Instance == hcan2.Instance)
	{
		if(HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &can2_header, can2_data) != HAL_OK)
		{
			// error handler
		}
	}
}

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.
JPeac.1
Senior

At the start of the CAN RXFIFO interrupt service routine read the interrupt vector from SCB->ICSR. This will uniquely identify which CAN bus is being processed.

I don't use the HAL or Cube. I have a reentrant RXFIFO handler which services all buses and FIFOs. I use the ICSR to determine which CAN peripheral and FIFO is in use and append the information to the incoming CAN message before queueing it to be passed to the CANopen protocol stack.

Determining the bus is necessary for some CANopen 4 implementations that support redundant buses and flying bus masters.

Jack Peacock

Excellent, thank you!