Simultaneous CAN FD and UDS Reception using PCAN-UDS API

A free API for the communication with control devices according to UDS (ISO 14229-1)
Post Reply
AnnYeh
Posts: 2
Joined: Fri 29. May 2026, 06:07

Simultaneous CAN FD and UDS Reception using PCAN-UDS API

Post by AnnYeh » Fri 29. May 2026, 07:53

If I want my PCAN adapter to receive both UDS (ISO-TP) packets and standard CAN frames simultaneously on the same channel, what is the correct way to initialize the channel?
Specifically, since we are working with CAN FD, should I use UDSApi.InitializeFD_2013 for the initialization? If so, will there be any conflicts if I call both PCANBasic.ReadFD() and UDSApi.Read_2013() on this same channel?

K.Wagner
Software Development
Software Development
Posts: 1089
Joined: Wed 22. Sep 2010, 13:36

Re: Simultaneous CAN FD and UDS Reception using PCAN-UDS API

Post by K.Wagner » Fri 29. May 2026, 08:39

Hello,

yes, it is possible to receive ISO-TP/UDS messages and CAN classic frames from a UDS initialized channel, simultaneously. This use case is fully covered by the existing PCAN-UDS 2.x examples, specifically samples 13 and 14 (13_server_uds_and_can / 14_client_uds_and_can). They demonstrate exactly what you're looking for: reading both UDS requests and plain CAN frames simultaneously on the same initialized UDS channel.

Some notes for you:
  • Use UDS_InitializeFD_2013 for CAN FD – and only that. Do not call PCANBasic.Initialize separately. PCAN-UDS internally initializes PCAN-ISO-TP and PCAN-Basic for you.
  • Do not use PCANBasic.ReadFD() on a UDS-initialized channel. Once the channel is owned by PCAN-ISO-TP, calling PCANBasic.ReadFD() in parallel will cause race conditions – messages will be consumed by one API or the other, not both. Instead, use CanTpApi.Read_2016() with the PCANTP_MSGTYPE_CAN filter to receive plain CAN frames through the same channel, conflict-free.
  • Samples 13/14 show this pattern cleanly using two separate threads – one for UDS via PCAN-UDS API, one for CAN frames via PCAN-ISO-TP API. That's the recommended approach.
Best regards,
Keneth

AnnYeh
Posts: 2
Joined: Fri 29. May 2026, 06:07

Re: Simultaneous CAN FD and UDS Reception using PCAN-UDS API

Post by AnnYeh » Fri 29. May 2026, 12:11

Hello,

Thank you for your reply.
I followed your instructions to initialize PCAN and used CanTpApi.Read_2016, but the return value I got was PCANTP_STATUS_NO_MESSAGE.

As an additional note: I can confirm that the incoming data is being received successfully and is fully visible in PCAN-View. This suggests that the hardware connection, wiring, and baud rate are all configured correctly. However, the API still fails to catch the messages in my application.

Below is my code. Could you please take a look and help me check if I missed any initialization steps, network mappings, or filtering configurations?

Code: Select all


  private bool PCAN_InitializeFD()
  {
      // CAN FD
      string fdSetting = "f_clock=80000000,nom_brp=2,nom_tseg1=63,nom_tseg2=16,nom_sjw=16,data_brp=2,data_tseg1=15,data_tseg2=4,data_sjw=4";

      // PCAN_Channel_Number is not Found
      if (m_PcanHandle == 0)
      {
          MessageBox.Show("Please scan and find a valid PCAN channel first!");
          return false;
      }

      try
      {
          Debug.WriteLine($"Initializing PCAN Handle: 0x{m_PcanHandle:X2}");

          //  InitializeFD_2013
          uds_status sts = UDSApi.InitializeFD_2013((cantp_handle)m_PcanHandle, fdSetting);

          if (sts != uds_status.PUDS_STATUS_OK)
          {
              MessageBox.Show("InitializeFD_2013 failed: ");
              //沒 release 

              Uninitialize();
              PCAN_InitializeFD();
              MessageBox.Show("PCAN Initialized Successfully!");
              return true;
          }
          else
          {
              UInt32 isotp_param;
              cantp_status status;
              isotp_param = 0;
              status = CanTpApi.SetValue_2016((cantp_handle)m_PcanHandle, cantp_parameter.PCANTP_PARAMETER_FILTER_CAN_ID, ref isotp_param, sizeof(UInt32));
              Debug.WriteLine("SetValue_2016: "+ status);

              Debug.WriteLine("PCAN Initialized Successfully!");
              return true;
          }
      }
      catch (Exception ex)
      {
          MessageBox.Show("Init Error: " + ex.Message);
          return false;
      }
  }

        private bool Add_UDS_TXMapping() // Tester(0x7A0) → ZCU (0x7B0)
        {
            uds_status status;
            myTXMapping = new uds_mapping();

            // --- Mapping  ---
            myTXMapping.can_id = 0x7A0;          
            myTXMapping.can_id_flow_ctrl = 0x7B0;  

            myTXMapping.can_msgtype = msgType;    //  Standard | FD | BRS

            // 11-bit Normal 
            myTXMapping.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
            //myTXMapping.nai.target_type = (cantp_isotp_addressing)cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;
            myTXMapping.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            myTXMapping.nai.extension_addr = 0;
            myTXMapping.nai.source_addr = 0xF1; // Tester
            myTXMapping.nai.target_addr = 0x01; // ZCU

            status = UDSApi.AddMapping_2013((cantp_handle)m_PcanHandle, ref myTXMapping);

            if (UDSApi.StatusIsOk_2013(status))
            {
                Debug.WriteLine("UDS myTXMapping for ZCU added successfully!");
                return true;
            }
            else
            {
                Debug.WriteLine("UDS myTXMapping failed: " + status);
                return false;
            }
        }


        private bool InitializeUdsConfig()
        { 
            config.can_id = 0x7A0; //ATP
           //config.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
            config.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_FD | cantp_can_msgtype.PCANTP_CAN_MSGTYPE_BRS;
            config.type = uds_msgtype.PUDS_MSGTYPE_USDT; //based on ISO-TP

            config.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
            config.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

            config.nai.extension_addr = 0;
            
            return true;
        }


  public byte[] ReadMonitorData()
  {
      // 1. 宣告 C# Read_2016 所需的 out 變數
      cantp_msg rxMsg;
      cantp_status status;
      cantp_msg tx_msg;

      UInt64 rxTimestamp;
      cantp_status readStatus = CanTpApi.Read_2016(
          (cantp_handle)m_PcanHandle,
          out rxMsg,
          out rxTimestamp,
          cantp_msgtype.PCANTP_MSGTYPE_CAN
      );

      // Debug.WriteLine($"[ReadMonitorData]_進來ReadMonitorData");
      Debug.WriteLine("Status: " + readStatus);
      // 3. 判斷讀取狀態是否成功
      if (readStatus == cantp_status.PCANTP_STATUS_OK)
      {
          Debug.WriteLine($"[收到 UDS 封包] CAN ID: 0x{rxMsg.can_info.can_id:X}");
          // 4. 判斷這是不是一個標準的 RAW CAN 或 CANFD 封包
          if (rxMsg.type == cantp_msgtype.PCANTP_MSGTYPE_CAN || rxMsg.type == cantp_msgtype.PCANTP_MSGTYPE_CANFD)
          {
              Debug.WriteLine($"[收到非 UDS 封包] CAN ID: 0x{rxMsg.can_info.can_id:X}");

              // 從描述資訊拿到正確的資料長度
              int dataLength = rxMsg.can_info.dlc;
              byte[] resultData = new byte[dataLength];

              // 5. 檢查指標是否有效
              if (rxMsg.Msgdata != IntPtr.Zero)
              {
                  try
                  {
                      // 【核心修正】不透過屬性轉結構體,直接從記憶體指標複製資料
                      // 參數說明:(來源記憶體指標, 目的陣列, 目的陣列起始索引, 要複製的長度)
                      Marshal.Copy(rxMsg.Msgdata, resultData, 0, dataLength);

                      return resultData;
                  }
                  catch (Exception ex)
                  {
                      Debug.WriteLine($"記憶體複製失敗: {ex.Message}");
                  }
              }
          }
      }
      else if (readStatus == cantp_status.PCANTP_STATUS_NO_MESSAGE)
      {
          // 緩衝區目前沒資料
      }

      return null;
  }

Image

K.Wagner
Software Development
Software Development
Posts: 1089
Joined: Wed 22. Sep 2010, 13:36

Re: Simultaneous CAN FD and UDS Reception using PCAN-UDS API

Post by K.Wagner » Fri 29. May 2026, 13:17

Hello again,

please use the examples without modification and check how communication is done. Note that there are 2 examples, one server and one client. Let the server run in a channel, and debug the client in another, then you will see the communication (ISO-TP and UDS).
You should go to code your own solution only when you have done this and understand how it works.

As information, there is another approach. You can also configure UDS to read UUDT frames (unacknowledged unsegmented data transfer) - in other words, CAN plain data. Then you can read everything through UDS directly (UDS_Read2016) - the message type tells you what kind of message it is. The downside here is that you need to define additional CAN ID filtering. All information is in the documentation, also an example in page 775. In the project samples you find 11/12 samples made in a similar way (server/client), if you want to test this approach.
Best regards,
Keneth

Post Reply