2026-03-03 9:56 PM
/* ============ 500 kbit/s Bit Timing Derivation ============
*
* Step 1: FDCAN Kernel Clock
* fCAN = 80 MHz (from Clock Configuration)
*
* Step 2: Prescaler
* Prescaler = 10
*
* Step 3: Time Quantum (tq)
* tq = Prescaler / fCAN
* tq = 10 / 80,000,000 Hz = 0.125 µs = 125 ns
*
* Step 4: Bit Segments (in TQ)
* Sync Segment = 1 TQ (fixed, always 1)
* Time Segment 1 = 12 TQ (Prop_Seg + Phase_Seg1)
* Time Segment 2 = 3 TQ (Phase_Seg2)
*
* Step 5: Total Time Quanta per Bit
* Total TQ = Sync + TS1 + TS2 = 1 + 12 + 3 = 16 TQ
*
* Step 6: Bit Time
* Bit Time = Total TQ × tq = 16 × 125 ns = 2000 ns = 2 µs
*
* Step 7: Nominal Bit Rate
* Bit Rate = 1 / Bit Time = 1 / 2 µs = 500 kbit/s
*
* Step 8: Sample Point
* Sample Point = (Sync + TS1) / Total TQ = (1 + 13) / 16 = 87.5%
*
*/
----------------
MX_FDCAN2_Init();
-----------------
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_MASK; /* Classic ID + mask mode */
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; /* Matching frames → RX FIFO 0 */
sFilterConfig.FilterID1 = 0x7E8; /* Expected ECU response base ID */
sFilterConfig.FilterID2 = 0x7F8; /* Mask: match 0x7E8 – 0x7EF */
if (HAL_FDCAN_ConfigFilter(&hfdcan2, &sFilterConfig) != HAL_OK) {
Error_Handler();
}
/* Reject all non-matching frames (no global accept) */
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan2, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE) != HAL_OK) {
Error_Handler();
}
if (HAL_FDCAN_Start(&hfdcan2) != HAL_OK) {
Error_Handler();
}
-----------------
static void MX_FDCAN2_Init(void) {
/* USER CODE BEGIN FDCAN2_Init 0 */
/* USER CODE END FDCAN2_Init 0 */
/* USER CODE BEGIN FDCAN2_Init 1 */
/* USER CODE END FDCAN2_Init 1 */
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 = DISABLE;
hfdcan2.Init.NominalPrescaler = 10;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 13;
hfdcan2.Init.NominalTimeSeg2 = 2;
hfdcan2.Init.DataPrescaler = 1;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 1;
hfdcan2.Init.DataTimeSeg2 = 1;
hfdcan2.Init.MessageRAMOffset = 0x000;
hfdcan2.Init.StdFiltersNbr = 1;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.RxFifo0ElmtsNbr = 32;
hfdcan2.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxFifo1ElmtsNbr = 0;
hfdcan2.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.RxBuffersNbr = 0;
hfdcan2.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan2.Init.TxEventsNbr = 0;
hfdcan2.Init.TxBuffersNbr = 0;
hfdcan2.Init.TxFifoQueueElmtsNbr = 32;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan2.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK) {
Error_Handler();
}
/* USER CODE BEGIN FDCAN2_Init 2 */
/* USER CODE END FDCAN2_Init 2 */
}
-----------------
/* This callback is triggered by TIM1 overflow every 1 second to send an OBD-II RPM request frame */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) {
if (htim->Instance == TIM1) {
FDCAN_TxHeaderTypeDef TxHeader;
uint8_t TxData[DATA_LEN] = {0};
TxHeader.Identifier = 0x7E0; // OBD-II request ID for Engine ECU, cycled through 0x7E0-0x7E7 for different ECUs, same rejection issue
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.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
TxData[0] = 0x02; // SF, 2 data bytes
TxData[1] = 0x01; // Service 01
TxData[2] = 0x0C; // PID 0C — RPM
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxHeader, TxData);
}
}
Solved! Go to Solution.
2026-03-04 2:35 AM - edited 2026-03-04 2:51 AM
Indeed you are using HSI. It’s recommended to use HSE and a crystal for CAN communication. I don’t have my PC now (i’m posting with my phone) but the disco board has already a crystal (crystal oscillator XO).
So please use it instead of HSI:
You shoud select HSE in bypass mode and set the crystal value to 25MHz in the clock view.
2026-03-03 10:07 PM
> I am able to see the CAN BUS traffic using an oscilloscope , just my request frames are rejected by car.
You need to be more specific here. What does "rejected by car" look like ?
I don't know OBD specifics, but this is basically the higher protocol transported via CAN.
Does the physical layer cause errors, or does your application violate OBD protocol ?
If the former is the case, the CAN error counters (TEC and REC) should indicate that.
2026-03-03 10:26 PM
Please see the file attached , filter ID column with 7E and select all. You will see that DLC 0 and DATA empty and CRC invalid , not ACKed and Valid 0.
TEC increased more than 127 , goes to error passive after a few milliseconds.
02 01 0C with first byte 02 means it is a request for RPM in live mode (show current data). I don't even flood the bus since my requests are periodic with 1s , and i address it to each physical address from 7E0-7E7 and 7DF(broadcasting to all ECUs)
2026-03-03 11:37 PM
> TEC increased more than 127 , goes to error passive after a few milliseconds.
Which means you almost certainly have a problem with the physical signal, either wiring, or missing/improper termination resistance.
As said, I don't know OBD, but Wikipedia states :
- ISO 15765 CAN (250 kbit/s or 500 kbit/s).
Have you tried 250kbit/s ?
2026-03-04 12:13 AM - edited 2026-03-04 12:17 AM
Hello @MR17 and welcome to the ST community,
As you are receiving well the CAN frames sent by the car, the communication is fine as well as your hardware. If your car is not accepting your frames (especially when they were acknowledged) that means the CAN IDs are dropped by the car. So we cannot help you at this stage as we are not OBD specification experts here. You need to check it again and verify the correct IDs and the data content needed for that communication.
Good luck!
2026-03-04 12:15 AM
@Ozone wrote:> TEC increased more than 127 , goes to error passive after a few milliseconds.
Which means you almost certainly have a problem with the physical signal, either wiring, or missing/improper termination resistance.
As said, I don't know OBD, but Wikipedia states :
- ISO 15765 CAN (250 kbit/s or 500 kbit/s).
Have you tried 250kbit/s ?
OBD2 Request are only for High Speed CAN. And the pins of OBD2 port are CANH pin 6 , CANH pin 14 and GND pin 5 or 4
> TEC increased more than 127 , goes to error passive after a few milliseconds.
Which means you almost certainly have a problem with the physical signal, either wiring, or missing/improper termination resistance.
It is fine , otherwise my oscilloscope would have not decoded the frames and the FDCAN present in the board would have not received the frames and logged via USART3 VCOM .
2026-03-04 12:49 AM
> It is fine , otherwise my oscilloscope would have not decoded the frames and the FDCAN present in the board would have not received the frames and logged via USART3 VCOM .
The other side (the car) seems to disagree.
And TEC / REC are going up on physical signal errors.
What you see on one end is not necessarily what the other side sees.
2026-03-04 12:56 AM
Sorry I didn't see that post:
@MR17 wrote:
Please see the file attached , filter ID column with 7E and select all. You will see that DLC 0 and DATA empty and CRC invalid , not ACKed and Valid 0.
TEC increased more than 127 , goes to error passive after a few milliseconds.
02 01 0C with first byte 02 means it is a request for RPM in live mode (show current data). I don't even flood the bus since my requests are periodic with 1s , and i address it to each physical address from 7E0-7E7 and 7DF(broadcasting to all ECUs)
So you have communication errors!
Frame not acked means, bitrate issue or hardware issue. I'm a bit surprised by this:
"I am able to receive CAN frames and able to log CAN frame frames it is just that frames sent are rejected"
What clock source are you using for FDCAN? HSI or HSE+Crystal? if HSI, please use HSE + a crystal or any other external precise source.
2026-03-04 1:39 AM
> "I am able to receive CAN frames and able to log CAN frame frames it is just that frames sent are rejected"
> What clock source are you using for FDCAN? HSI or HSE+Crystal? if HSI, please use HSE + a crystal or any other external precise source.
As I understood it, an attached CAN dongle properly receives and displays those messages. Which does not mean that the OBD counterpart does.
And, having no OBD experience either, have seen that Wikipedia lists either 250 or 500 KBit/s as possible supported bitrates.
The OP can have a mismatch here, I have seen nothing about "auto baud detection".
2026-03-04 1:45 AM - edited 2026-03-04 1:47 AM
I’m providing all the sources of issues that can face with the communication and also I cited a possible issue of a bitrate mismatch. But that doesn’t make sense if his can node is receiving well the frames from the car. That seems to be not a baudrate issue but more related to a jitter or something similar.