cancel
Showing results for 
Search instead for 
Did you mean: 

OBD2 request frames rejection issues

MR17
Associate II
I tried doing an OBD2 request via Car's OBD2 port.

I am able to see the CAN BUS traffic using an oscilloscope , just my request frames are rejected by car. I am using STM32h735G-DK development board to send OBD2 requests. It consists of an inbuilt FDCAN transceiver.

Settings are fine (removed termination resistor as car already has two), baudrate is 500kbps  with 87.5% sample point. I am using the following code to send OBD2 request frames:

I am able to receive CAN frames and able to log CAN frame frames it is just that frames sent are rejected. What am i doing wrong here?

FDCAN Code excerpt:
 
/* ============ 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);
  }
}
20 REPLIES 20

 

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.