Skip to main content
Graduate
December 10, 2025
Solved

FDCAN on STM32C0: transmitting every 100ms, receiver sees frames only every ~497ms

  • December 10, 2025
  • 6 replies
  • 295 views

Post edited by ST moderator to be inline with the community rules for the code sharing. In next time please use </> button to paste your code and a linker script content. Please read this post: How to insert source code.

i, I am using STM32C092CCT6 with FDCAN.
I transmit one CAN frame every 100 ms (even tried 50 ms).
But on the receiver side, I always receive frames only every ~497 ms.

It looks like something is delaying or buffering the frames.

What I want to know:
Which FDCAN settings could cause the frames to appear only every ~497 ms?

My problem summary:

  • Tx interval configured: 100 ms → Rx sees ~497 ms

  • Tx interval configured: 50 ms → Rx still ~497 ms

  • So the transmit timing is not coming out correctly.

Request:
Please check if anything is wrong with my FDCAN configuration (below).

/**
* @brief FDCAN1 Initialization Function
* None
* @retval None
*/
static void MX_FDCAN1_Init(void)
{

/* USER CODE BEGIN FDCAN1_Init 0 */

/* USER CODE END FDCAN1_Init 0 */

/* USER CODE BEGIN FDCAN1_Init 1 */

/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 16;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 58;
hfdcan1.Init.NominalTimeSeg2 = 1;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.StdFiltersNbr = 0;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */

/* USER CODE END FDCAN1_Init 2 */

}
    This topic has been closed for replies.
    Best answer by mƎALLEm

    "The timer interrupt is working properly. It triggers every 1 ms, and I am counting 100 ms before setting the flag and transmitting the CAN frame."

    -> How are you sure?

    Do the test without the timer, use:

    HAL_Delay(100);

     

     

    6 replies

    Technical Moderator
    December 10, 2025

    Hello,

    First, in next time, please use </> button to share your code.

    Second, how did you conclude "the frames appear every ~497 ms?"

    + You didn't tell which one is the receiver and which one is the transmitter, how many nodes are availeble on the CAN bus?? and the code above corresponds to which one: receiver or transmitter?

     

    anuj18apAuthor
    Graduate
    December 10, 2025

    As the transmitter, I am using FDCAN1 on the STM32C092CCT6 controller. On the receiver side, for testing purposes, I am using a Korlan USB-CAN Converter.

    I concluded that the frames appear every ~497 ms by checking the timestamp difference of the received CAN frames. On the receiver side, I used the canutils command: candump -t d can0. This command prints the time interval between consecutive CAN frames, and it consistently reports about 0.497 seconds between frames.

    The code I shared corresponds to the STM32 transmitter. There is only one transmitter (STM32) and one receiver (Korlan USB-CAN) connected on the bus.

    Explorer
    December 10, 2025

    Show us a recording of the physical bus signals done with a scope.

    > There is only one transmitter (STM32) and one receiver (Korlan USB-CAN) connected on the bus.

    If this CAN-USB dongle is in silent mode (listener only), the setup will not work at all.
    The STM32 device will quickly reach the "error passive" mode, and after a delay, re-enable transmissions.
    Which would explain the "long" delays.

    Technical Moderator
    December 10, 2025

    @Ozone wrote:

    Show us a recording of the physical bus signals done with a scope.


    +1

     

    @Ozone wrote:

    If this CAN-USB dongle is in silent mode (listener only), the setup will not work at all.


    Except if there is another CAN node on that CAN bus that acknowledges the received frames ;)

    anuj18apAuthor
    Graduate
    December 10, 2025

    It is not in listener-only mode. The same Korlan USB-CAN device works normally with another controller on the same setup, and I have already tested it with other STM32 series as well, where it works fine. So the dongle is able to acknowledge frames and is not operating as a silent listener.

    anuj18apAuthor
    Graduate
    December 10, 2025

    This is how I am transmitting the CAN frames. In the timer interrupt, which runs every 1 ms, I increment a counter and set a flag every 100 ms:

    can_temp_Counter++;
    if (can_temp_Counter >= 100) {
    can_temp_Counter = 0;
    txMessage = true;
    }

    Then in the main loop I check this flag and send the CAN frame:

    if (txMessage) {
    txMessage = false;
    uint8_t txData[8] = "DEADDEAD";
    txHeader.Identifier = 0x00A;
    txHeader.IdType = FDCAN_STANDARD_ID;
    txHeader.TxFrameType = FDCAN_DATA_FRAME;
    txHeader.DataLength = FDCAN_DLC_BYTES_8;
    txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    txHeader.BitRateSwitch = FDCAN_BRS_OFF;
    txHeader.FDFormat = FDCAN_CLASSIC_CAN;
    txHeader.MessageMarker = 0;
    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData);
    }
    Explorer
    December 10, 2025

    > Then in the main loop I check this flag and send the CAN frame: ...

    You can't "send a CAN frame".
    You can only put it into the mbox / FIFO / queue, and the CAN peripheral transmits it once the bus is free.
    And a transmission only succeeds when another node actively acknowledges it.

    Thus, for understanding why you don't get the expected result, you need to know what is going on on the CAN bus.

    anuj18apAuthor
    Graduate
    December 10, 2025

    .

    anuj18apAuthor
    Graduate
    December 10, 2025

    The timer interrupt is working properly. It is triggering every 1 ms, and I am counting 100 ms before setting the flag and transmitting the CAN frame. So the transmit function is definitely being called every 100 ms, but on the receiver side I still see approximately 497 ms between frames.

    Is there any FDCAN configuration that could cause this delay? I have already tried using HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, 5, 0U); in the CAN initialization, but it did not change the result.

    void can_bus_init()
    {
     /* Configure reception filter to Rx FIFO 0 */
     FDCAN_FilterTypeDef sFilterConfig;
     sFilterConfig.IdType = FDCAN_STANDARD_ID;
     sFilterConfig.FilterIndex = 0U;
     sFilterConfig.FilterType = FDCAN_FILTER_MASK;
     sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
     sFilterConfig.FilterID1 = 0x008;
     sFilterConfig.FilterID2 = 0x7FF;
     if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
     {
     Error_Handler();
     }
     
     
     sFilterConfig.IdType = FDCAN_STANDARD_ID;
     sFilterConfig.FilterIndex = 1U;
     sFilterConfig.FilterType = FDCAN_FILTER_MASK;
     sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
     sFilterConfig.FilterID1 = 0x009;
     sFilterConfig.FilterID2 = 0x7FF;
     if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
     {
     Error_Handler();
     }
     
     sFilterConfig.IdType = FDCAN_STANDARD_ID;
     sFilterConfig.FilterIndex = 2U;
     sFilterConfig.FilterType = FDCAN_FILTER_MASK;
     sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
     sFilterConfig.FilterID1 = 0x00A;
     sFilterConfig.FilterID2 = 0x7FF;
     if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
     {
     Error_Handler();
     }
     
     /**
     * Configure global filter:
     * - Filter all remote frames with STD and EXT ID
     * - Reject non matching frames with STD ID and EXT ID
     */
     if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,
     FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0,
     FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE))
     {
     Error_Handler();
     }
     
     HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, 5, 0U);
     
     
     if (HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1) != HAL_OK)
     {
     Error_Handler();
     }
    
     /* Activate Rx FIFO 0 new message notification */
    // if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0U) != HAL_OK)
    // {
    // Error_Handler();
    // }
     
     /* Activate the Tx FiFo Callback */
     HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_FIFO_EMPTY, 0U);
     
     /* Start FDCAN controller */
     if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
     {
     Error_Handler();
     }
     
    }

     

    mƎALLEmAnswer
    Technical Moderator
    December 10, 2025

    "The timer interrupt is working properly. It triggers every 1 ms, and I am counting 100 ms before setting the flag and transmitting the CAN frame."

    -> How are you sure?

    Do the test without the timer, use:

    HAL_Delay(100);