2025-09-12 11:17 AM - last edited on 2025-09-17 5:49 AM by mƎALLEm
Post edited by ST moderator to be inline with the community rules especially with the code sharing. In next time please use </> button to paste your code. Please read this post: How to insert source code.
Hi everyone,
I am working on Classic CAN communication using the STM32H745I-Discovery board with FDCAN2.
My target CAN configuration is 500 Kbps nominal baud rate with a 16 MHz clock.
Below is my initialization code:
static void MX_FDCAN2_Init(void)
{
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = ENABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = ENABLE;
// Timing config: 500 Kbps @ 16 MHz
hfdcan2.Init.NominalPrescaler = 1;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 23;
hfdcan2.Init.NominalTimeSeg2 = 8;
hfdcan2.Init.DataPrescaler = 1;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 1;
hfdcan2.Init.DataTimeSeg2 = 1;
hfdcan2.Init.MessageRAMOffset = 0;
hfdcan2.Init.StdFiltersNbr = 1;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.RxFifo0ElmtsNbr = 1;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.TxFifoQueueElmtsNbr = 1;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK) Error_Handler();
// Configure filter (accept all standard IDs)
FDCAN_FilterTypeDef filter;
filter.IdType = FDCAN_STANDARD_ID;
filter.FilterIndex = 0;
filter.FilterType = FDCAN_FILTER_MASK;
filter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
filter.FilterID1 = 0x000;
filter.FilterID2 = 0x7FF;
HAL_FDCAN_ConfigFilter(&hfdcan2, &filter);
HAL_FDCAN_Start(&hfdcan2);
// Tx header
txHeader.Identifier = 0x123;
txHeader.IdType = FDCAN_STANDARD_ID;
txHeader.TxFrameType = FDCAN_DATA_FRAME;
txHeader.DataLength = FDCAN_DLC_BYTES_8;
txHeader.BitRateSwitch = FDCAN_BRS_OFF;
txHeader.FDFormat = FDCAN_CLASSIC_CAN;
txHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
txHeader.MessageMarker = 0;
}
And the send function:
HAL_StatusTypeDef CAN_Send(uint8_t* data)
{
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &txHeader, data) == HAL_OK)
{
return HAL_OK;
}
else
{
return HAL_ERROR;
}
}
Issue:
The first few CAN frames transmit successfully.
After that, the TXFIFO becomes full and no further frames are sent.
Sometimes it transmits several messages before stopping, sometimes only one or two.
What I tried so far:
Increased TxFifoQueueElmtsNbr (tried more than 1).
Verified hardware connections and ensured 120Ω termination resistor is present.
Tested the receiver side (looped with another working board), and confirmed reception is fine there.
Tried with both AutoRetransmission enabled/disabled.
Verified the 500 Kbps baud rate configuration with 16 MHz clock.
Still, the issue persists.
Any guidance or working examples would be very helpful.
Thanks!
Solved! Go to Solution.
2025-09-23 8:43 AM - edited 2025-09-23 8:51 AM
Hello,
I tested your project with a little modification and there is no issue. I just connected another CAN node which is a NUCLEO-F767 board (CAN2.0) + a transceiver, and the latter is receiving the CAN frames from STM32H745I-DISCO without issues.
These are the frames send each 100ms:
This screenshot spots one frame:
A screenshot for IAR of the receiving CAN frame (F767 side) showing the Rx content changing in live (only data 0 and data 7 are changing):
Attached the projects that I used for the test.
Now, I'm pretty sure it's not a software issue and you have a hardware issue. Either with the transceiver or the wiring or something else. Maybe you swapped CAN_H and CAN_L? need to check.
Hope that helps.
2025-09-12 11:44 AM
Are you queuing your CAN messages? Because if you send a bunch of messages and the Tx buffer is full, then you lose those messages. By using a queue, you can send those messages once the Tx buffer is available.
Also, use the </> to post code so that it's formatted and readable.
2025-09-13 1:08 PM
Hi,
Thanks for your reply.
Right now I’m only using HAL_FDCAN_AddMessageToTxFifoQ() directly, so when the hardware Tx FIFO gets full I lose messages. I understand now that I should add a software queue on top and retry sending when space becomes available.
However, in my case I’m transmitting only one CAN frame every 1 second. Since a CAN frame takes just a few hundred microseconds on the bus, the Tx FIFO should normally be free by the time the next frame is sent, correct?
2025-09-13 1:58 PM
What I tried so far:
Tested the receiver side (looped with another working board), and confirmed reception is fine there.
It's unclear what is happening. So, is this other working board continuously working and your main board is transmitting without getting full? What is the other node that you're trying to transmit to that is causing your main board to get full?
2025-09-13 11:09 PM
I’m using an Arduino Nano on the receiver side. I’ve tested the Nano as the receiver with different STM32 MCU board, and it is receiving the data without any errors
2025-09-16 11:48 PM
After start fdcan, the interrupt should be start
2025-09-17 5:48 AM
What is the clock source of your FDCAN? Did you set HSE as main clock source for FDCAN?
2025-09-18 6:07 AM
I was using HSI as the main clock source for FDCAN. I also tried switching to HSE as the main clock source, but the issue still persists.
2025-09-18 6:10 AM
I haven’t enabled any interrupts there. Do I still need to mention it?
2025-09-18 6:19 AM - edited 2025-09-18 7:34 AM
In Normal mode you should use HSE with an external crystal as soon you are connected to another CAN node.