2025-09-03 7:40 AM - last edited on 2025-09-03 7:58 AM by mƎALLEm
Hi all,
I am trying to use FDCAN with Baud rate switch (500 kB / 2 MBit) activated and I want to send 64 Byte.
Processor is STM32H7A3. Project was set up with CubeMX V. 6.11.1 and HAL FW_H7 V1.11.2. Clock for FDCAN is 80 MHz.
The problem is that the system only sends with 500 kB and 8 Bytes only.
I am transmitting the data to my PC using a PEAK USB dongle (FDCAN capable with BRS) and in parallel check the messages on a scope.
I don't know, why it doesn't switch to 2 MBit and I only see 8 Bytes with 500 kBit on my scope and on PCAN-Explorer.
Here my init and transmit code sequences:
FDCAN_HandleTypeDef* phCan;
phCan = &hfdcan1;
phCan->Instance = FDCAN1;
phCan->Init.Mode = FDCAN_MODE_NORMAL;
phCan->Init.FrameFormat = FDCAN_FRAME_FD_BRS;
phCan->Init.AutoRetransmission = ENABLE;
phCan->Init.TransmitPause = DISABLE;
phCan->Init.NominalPrescaler = 10;
phCan->Init.NominalSyncJumpWidth = 1;
phCan->Init.NominalTimeSeg1 = 11;
phCan->Init.NominalTimeSeg2 = 4;
phCan->Init.DataPrescaler = 2;
phCan->Init.DataSyncJumpWidth = 1;
phCan->Init.DataTimeSeg1 = 14;
phCan->Init.DataTimeSeg2 = 5;
phCan->Init.MessageRAMOffset = 0;
phCan->Init.StdFiltersNbr = 0;
phCan->Init.ExtFiltersNbr = 0;
phCan->Init.RxFifo0ElmtsNbr = 16; // 0..64
phCan->Init.RxFifo1ElmtsNbr = 16;
phCan->Init.RxBuffersNbr = 10;
phCan->Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
phCan->Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_64;
phCan->Init.RxBufferSize = FDCAN_DATA_BYTES_64;
phCan->Init.TxEventsNbr = 0;
phCan->Init.TxBuffersNbr = 0;
phCan->Init.TxFifoQueueElmtsNbr = 16;
phCan->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
phCan->Init.TxElmtSize = FDCAN_DATA_BYTES_64;
phCan->msgRam.StandardFilterSA = 0;
phCan->msgRam.ExtendedFilterSA = 0;
phCan->msgRam.RxFIFO0SA = 0;
phCan->msgRam.RxFIFO1SA = 0;
phCan->msgRam.RxBufferSA = 0;
phCan->msgRam.TxEventFIFOSA = 0;
phCan->msgRam.TxBufferSA = 0;
phCan->msgRam.TxFIFOQSA = 0;
phCan->msgRam.TTMemorySA = 0;
phCan->msgRam.EndAddress = 0;
phCan->ErrorCode = 0;
halErr = HAL_FDCAN_Init(phCan);
halErr = HAL_FDCAN_Start(phCan);
----------------------------------
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.FDFormat = FDCAN_FRAME_FD_BRS;
TxHeader.BitRateSwitch = FDCAN_BRS_ON;
TxHeader.TxEventFifoControl = FDCAN_STORE_TX_EVENTS;//FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
TxHeader.Identifier = 0x55;
TxHeader.DataLength = FDCAN_DLC_BYTES_64;
halErr = HAL_FDCAN_AddMessageToTxFifoQ(phfdcan, &TxHeader, TxData); // TxData = 64 Bytes
Is there anything missing or wrong?
Thank you for any support or hints.
BR GS
Post edited by the ST moderator to follow the community rule especially for the code sharing.
Solved! Go to Solution.
2025-09-05 3:52 AM
Another thing the sample point at the data phase is around 50%-60% no more and it tends to be in the middle of the bit contrarily to the nominal bit time. I suggest you to use Kvaser bit time calculator tool: https://kvaser.com/support/calculators/can-fd-bit-timing-calculator/
2025-09-05 4:46 AM
Ok. Thank you for this info. I will recalculate the bit timing settings.
My customer told me, that they use 65% for both normal and data bit time.
BR GS
2025-09-08 2:04 AM
I have often seen, that the sampling point is rather at 80%.
This will depend on the accumulated delays due to the hardware bus structure, mainly due to capacitance.
What are the TDC settings? Although TDC is probably not needed at 2 Mbps.
2025-09-08 2:13 AM
The sampling point is around 80-87% in the arbitration phase. It seems not the case in the data phase. He needs to use Kvaser tool to confirm. I never had more than 60% in data phase with Kvaser tool.
2025-09-08 2:17 AM
Can the Kvaser tool mimic a heavier bus load, so that other sampling points can be tested / make sense?
2025-09-08 2:22 AM
Kvaser gives you the option to provide the characteristics of each node connected to the bus. Based on that it gives the all needed parameters.
"mimic a heavier bus load" -> I don't think so.
2025-09-08 2:50 AM
TDC Setting is implemented as proposed by mEALLEm:
/**
* Configure and enable Tx Delay Compensation, required for BRS mode.
* TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
* TdcFilter default recommended value: 0
*/
if (HAL_FDCAN_ConfigTxDelayCompensation(phCan, (phCan->Init.DataPrescaler * phCan->Init.DataTimeSeg1), 0U) != HAL_OK)
{
MyErrorHandler(E_CAN_DIV, halErr);
}
if (HAL_FDCAN_EnableTxDelayCompensation(phCan) != HAL_OK)
{
MyErrorHandler(E_CAN_DIV, halErr);
}
2025-09-08 6:10 AM
In the Kvaser Tool you can select the sample point by yourself, so it is oviously up to you to select the sample point.
I get results for any sample point between 20 and 90 %.
If I want to use the proposed values for the Bit-Timing calculated by the Kvaser Tool, did I get it right, that if the
Kvaser Tool says e.g.: _seg1 = 25, _-seg2 = 14, sjw = 14, Prescaler = 1 then I directly enter these values into the init configuration:
DataPrescaler = 1;
DataSyncJumpWidth = 14;
DataTimeSeg1 = 25;
DataTimeSeg2 = 14;
Correct?
I am asking because in the manual there is defined on page 2409:
... for the data bit time
– tq = (FDCAN_DBTP.DBRP[4:0] + 1) * tfdcan_tq_ck
– tSyncSeg = 1 tq
– tBS1 = tq * (FDCAN_DBTP.DTSEG1[4:0] + 1)
– tBS2 = tq * (FDCAN_DBTP.DTSEG2[3:0] + 1)
This is a bit confusing...
Just want to go sure I enter the correct values for the bittiming registers
2025-09-08 7:03 AM - edited 2025-09-08 7:16 AM
@GS1 wrote:
I am asking because in the manual there is defined on page 2409:
... for the data bit time
– tq = (FDCAN_DBTP.DBRP[4:0] + 1) * tfdcan_tq_ck
– tSyncSeg = 1 tq
– tBS1 = tq * (FDCAN_DBTP.DTSEG1[4:0] + 1)
– tBS2 = tq * (FDCAN_DBTP.DTSEG2[3:0] + 1)
Ignore the the equation in the reference manual.
In the HAL, the value 1 in the formula above is substructed from the timings in the HAL:
if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
{
hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
(((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos) | \
(((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos) | \
(((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
}
So what you did is correct. Set the same values as Kvaser when using HAL or CubeMx. Add 1 when you do a direct access to the registers.
2025-09-10 5:23 AM
Hi all helpers,
I got the FDCAN Bus with BRS working properly now.
The actual fixes were:
1) HAL_FDCAN_ConfigTxDelayCompensation / HAL_FDCAN_EnableTxDelayCompensation (were missing)
2) TxHeader.FDFormat = FDCAN_FD_CAN; (was initialized with a wrong value)
3) My fault: A wrong initialisation for the DataTimeSeg1/2 parameters which were not set correctly in my special Bitrate config method. I have constructed a method for different bitrates as a parameter. I need that to set different bitrates for normal CAN and FDCAN according to user setup. And these have not been handled correctly.
Thank you once more for your assistance, which in the end helped to get the FDCAN Bus working as expected.
Have a successful week!
BR GS