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-19 3:21 AM
So finally found out that the ECU diagnostics in my vehicle are done over KLine protocol instead of CAN protocol. The procedure which I did was completely fine. Just took this long to finally find it. Thanks for the help anyways! For anyone wondering.
accepting @mƎALLEm’s answer as it addresses an important point about jitter and stable crystal oscillator.