物联网学习--导航 www.iotstu.com

can控制器 uds诊断完整代码(c写的keil项目)遵循iso sae J1939标准(stm32 N32 系列MCU可用)

可以帮忙调试,QQ:778292363

(adsbygoogle = window.adsbygoogle || []).push({});

Single Frame(SF)- 单帧;First Frame (FF)-第一帧;Consecutive Frame (CF)-连续帧;Flow Control (FC)-流控帧;N_PDU type-网络层协议控制单元类型;N_PCI-网络层协议控制信息;SF_DL-单帧 数据长度;FF_DL-首帧数据长度;SN-连续帧序列号;FS-流控状态;BS-块大小;STmin-连续帧最小时间间隔。

‌‌UDS(Unified Diagnostic Services,统一诊断服务)是一种用于汽车行业的标准化诊断协议,基于‌CAN总线进行通信。UDS服务是诊断服务的规范化标准,规定了读取DTC(故障码)的指令、读诊断数据流的指令等。它允许维修人员使用诊断设备通过CAN总线与汽车电子控制单元(‌ECU)进行通信,执行各种诊断任务,如读取故障码、控制ECU的功能、以及更新ECU的软件等。‌

整个项目完整代码已经在前装车载设备上使用:

/***************************************************************************//**      \author              \mail               \version       0.03 - CANoe Test Passed      \date          2024-09-24      \description   uds network code, base on ISO 15765  *******************************************************************************/  #include "network_layer_private.h"  #include "network_layer.h"  #include "uds_api.h"  /*******************************************************************************      Type Definition  *******************************************************************************/    /*******************************************************************************      Global Varaibles  *******************************************************************************/  static network_layer_st nwl_st = NWL_IDLE;    static bool_t g_wait_cf = FALSE;  static bool_t g_wait_fc = FALSE;    static uint32_t nt_timer[TIMER_CNT] = {0};    static uint8_t g_rfc_stmin = 0;    /* received flowcontrol SeparationTime */  static uint8_t g_rfc_bs = 0;       /* received flowcontrol block size */    static uint8_t g_xcf_bc = 0;       /* transmit consecutive frame block counter */  static uint8_t g_xcf_sn = 0;       /* transmit consecutive frame SequenceNumber */  static uint8_t g_rcf_bc = 0;       /* received frame block counter */  static uint8_t g_rcf_sn = 0;       /* received consecutive frame SequenceNumber */    /* transmit buffer */  static uint8_t remain_buf[UDS_FF_DL_MAX];  static uint16_t remain_len = 0;  static uint16_t remain_pos = 0;    /* recieve buffer */  static uint8_t recv_buf[UDS_FF_DL_MAX];  static uint16_t recv_len = 0;  static uint16_t recv_fdl = 0;  /* frame data len */      //OS_EVENT *UdsMutex;    /*******************************************************************************      Function  declaration  *******************************************************************************/  static void  send_flowcontrol (uint8_t flow_st);    //static indication_func uds_indication = NULL;  //static confirm_func uds_confirm = NULL;    static nt_usdata_t N_USData = {NULL, NULL, NULL};  /*******************************************************************************      Function  Definition - common  *******************************************************************************/    /**   * nt_timer_start - start network timer   *   * void :   *   * returns:   *     void   */  static void  nt_timer_start (uint8_t num)  {  	if (num >= TIMER_CNT) return;    	if (num == TIMER_N_CR)          nt_timer[TIMER_N_CR] = TIMEOUT_N_CR;  	if (num == TIMER_N_BS)  	    nt_timer[TIMER_N_BS] = TIMEOUT_N_BS;      if (num == TIMER_STmin)          nt_timer[TIMER_STmin] = g_rfc_stmin;  }    static void  nt_timer_start_wv (uint8_t num, uint32_t value)  {  	if (num >= TIMER_CNT) return;    	if (num == TIMER_N_CR)          nt_timer[TIMER_N_CR] = value;  	if (num == TIMER_N_BS)  	    nt_timer[TIMER_N_BS] = value;      if (num == TIMER_STmin)          nt_timer[TIMER_STmin] = value;  }    static void  nt_timer_stop (uint8_t num)  {  	if (num >= TIMER_CNT) return;        nt_timer[num] = 0;  }    /**   * nt_timer_run - run a network timer, should be invoked per 1ms   *   * void :   *   * returns:   *     0 - timer is not running, 1 - timer is running, -1 - a timeout occur   */  static int  nt_timer_run (uint8_t num)  {  	if (num >= TIMER_CNT) return 0;        if (nt_timer[num] == 0)  	{          return 0;  	}  	else if (nt_timer[num] == 1)  	{  		nt_timer[num] = 0;  	    return -1;  	}  	else  	{  	    /* if (nt_timer[num] > 1) */  		nt_timer[num]--;  	    return 1;  	}    }    /**   * nt_timer_chk - check a network timer and stop it   *   * num :   *   * returns:   *     0 - timer is not running, 1 - timer is running,   */  static int  nt_timer_chk (uint8_t num)  {  	if (num >= TIMER_CNT) return 0;    	if (nt_timer[num] > 0)      {          nt_timer[num] = 0; /* stop timer */  	    return 1;      }  	else      {          nt_timer[num] = 0; /* stop timer */  		return 0;      }  }      /**   * clear_network - clear network status   *   * void :   *   * returns:   *     void   */  static void  clear_network (void)  {      uint8_t num;      nwl_st = NWL_IDLE;      g_wait_cf = FALSE;      g_wait_fc = FALSE;      g_xcf_bc = 0;      g_xcf_sn = 0;      g_rcf_bc = 0;      g_rcf_sn = 0;        for (num = 0; num < TIMER_CNT; num++)          nt_timer_stop (num);  }    /*******************************************************************************      Function  Definition - recieve  *******************************************************************************/  /**   * recv_singleframe - recieved a single frame from CAN   *   * @frame_buf : uds can frame data buffer   * @frame_dlc : uds can frame length   *   * returns:   *     void   */  static void  recv_singleframe (uint8_t frame_buf[], uint8_t frame_dlc)  {      uint16_t i, uds_dlc;  //	uint8_t service_id;        uds_dlc = NT_GET_SF_DL (frame_buf[0]);    //    service_id = frame_buf[1];        /************************************/    #ifdef UDS_CAN_ID_STD      if (uds_dlc > 7 || uds_dlc == 0)          return;  #else      if (uds_dlc > 6 || uds_dlc == 0)          return;  #endif        recv_fdl = uds_dlc;      for (i = 0; i < frame_dlc - 1; i++)          recv_buf[i] = frame_buf[1+i];      recv_len = frame_dlc - 1;        N_USData.indication (recv_buf, recv_fdl, N_OK);  }  /**   * recv_firstframe - recieved a firt frame from CAN   *   * service : L_Data.indication (FF)   * @frame_buf : uds can frame data buffer   * @frame_dlc : uds can frame length   *   * returns:   *     0 - recv a right frame, other - err    */  static int  recv_firstframe (uint8_t frame_buf[], uint8_t frame_dlc)  {      uint16_t i;  //    uint8_t service_id;      uint16_t uds_dlc;        uds_dlc = ((uint16_t)(frame_buf[0]&0x0f)) << 8;      uds_dlc |= frame_buf[1];    //    service_id = frame_buf[2];        /************************************/    #ifdef UDS_CAN_ID_STD      if (uds_dlc < 8)          return -1;  #else      if (uds_dlc < 7)          return -1;  #endif      /**       * if FF_DL is greater than the available receiver buffer size       * abort the message reception and send       * an FC N_PDU with Overflow.       */      if (uds_dlc >= UDS_FF_DL_MAX) {          send_flowcontrol (FS_OVFLW);          return -2;      }        recv_fdl = uds_dlc;      for (i = 0; i < frame_dlc - 2; i++)          recv_buf[i] = frame_buf[2+i];      recv_len = frame_dlc - 2;        /**       * after received first frame,       * send flowcontrol frame and wait consecutive frame,       */      send_flowcontrol (FS_CTS);      g_rcf_bc = 0;      g_wait_cf = TRUE;      nt_timer_start(TIMER_N_CR);      /* claer the consecutive frane0 sn */      g_rcf_sn = 0;        N_USData.ffindication (uds_dlc);        return 1;  }    /**   * recv_consecutiveframe - recieved a consecutive frame from CAN   *   * service: L_Data.indication (CF)   * @frame_buf : uds can frame data buffer   * @frame_dlc : uds can frame length   *   * returns:   *     0 - recv end, 1 - recv continue, other - err   */  static int  recv_consecutiveframe (uint8_t frame_buf[], uint8_t frame_dlc)  {      uint8_t cf_sn;  	uint16_t i;      cf_sn = NT_GET_CF_SN (frame_buf[0]);        /* if N_Cr timeout, Abort message transmission and issue N_TIMEOUT_Cr */      if(nt_timer_chk (TIMER_N_CR) <= 0) return -1;        g_rcf_sn++;      if (g_rcf_sn > 0x0f)          g_rcf_sn = 0;      if (g_rcf_sn != cf_sn) {          N_USData.indication (recv_buf, recv_len, N_WRONG_SN);          return -2;      }        for(i = 0; i < UDS_CF_DL_COM; i++)      {          recv_buf[recv_len+i] = frame_buf[1+i];       }      recv_len += UDS_CF_DL_COM;        if (recv_len >= recv_fdl)      {          g_wait_cf = FALSE;          N_USData.indication (recv_buf, recv_fdl, N_OK);          return 0;      }      else      {          if (NT_XMIT_FC_BS > 0)          {              g_rcf_bc++;              if (g_rcf_bc >= NT_XMIT_FC_BS)              {                  /**                   * after NT_XMIT_FC_BS consecutive frames,                   * send flowcontrol frame and wait consecutive frame,                   */                  send_flowcontrol (FS_CTS);                  g_rcf_bc = 0;              }          }                 g_wait_cf = TRUE;          nt_timer_start(TIMER_N_CR);          return 1;      }  }    /**   * recv_flowcontrolframe - process uds flowc control frame   *   * service: L_Data.indication (FC)   * @frame_buf : uds can frame data buffer   * @frame_dlc : uds can frame length   *   * returns:   *     0 - recv CTS, 1 - recv WT, other - err   */  static int  recv_flowcontrolframe (uint8_t frame_buf[], uint8_t frame_dlc)  {      uint8_t fc_fs;        fc_fs = NT_GET_FC_FS (frame_buf[0]);        /**       * if N_Bs timeout,        * Abort message transmission and issue N_TIMEOUT_Bs,       * if not timeout, stop the timer.       */      if(nt_timer_chk (TIMER_N_BS) <= 0) return -1;        /**      * Got from CANoe Test:      * After the First frame is received the Tester sends a functional      * adressed Flow control. ECU must abort sending of the response      */      //if (g_tatype == N_TATYPE_FUNCTIONAL) return -1;        g_wait_fc = FALSE;      if (fc_fs >= FS_RESERVED) {          N_USData.confirm (N_INVALID_FS);          return -2;      }        if (fc_fs == FS_OVFLW) {          N_USData.confirm (N_BUFFER_OVFLW);          return -3;      }        if (fc_fs == FS_WT) {          g_wait_fc = TRUE;          nt_timer_start (TIMER_N_BS);          return 1;      }        /**        * get the fc block size and stmin       */      g_rfc_bs = frame_buf[1];  	if (frame_buf[2] <= 0x7f)  	    g_rfc_stmin = frame_buf[2]+1;  	else  	    g_rfc_stmin = 0x7f; /* 127 ms */        /* start to transmit consecutive frame */      g_xcf_bc = 0;      nt_timer_start_wv (TIMER_STmin, 1);        return 0;  }    /*******************************************************************************      Function  Definition - send  *******************************************************************************/    /**   * send_flowcontrol - send flowcontrol frame   *   * service: L_Data.confirm (FC)   * @flow_st : flow status   *   * returns:   *     void   */  static void  send_flowcontrol (uint8_t flow_st)  {      uint8_t send_buf[UDS_VALID_FRAME_LEN] = {0};  		memset(send_buf, 0xcc, UDS_VALID_FRAME_LEN);      send_buf[0] = NT_SET_PCI_TYPE_FC (flow_st);      send_buf[1] = NT_XMIT_FC_BS;      send_buf[2] = NT_XMIT_FC_STMIN;      ZTai_UDS_Send (send_buf, UDS_VALID_FRAME_LEN);    }    /**   * send_singleframe - send a single frame msg   *   * @msg_buf : uds msg data buffer   * @msg_dlc : uds msg length   *   * returns:   *     void   */  static void  send_singleframe (uint8_t msg_buf[], uint16_t msg_dlc)  {  	uint16_t i;      uint8_t send_buf[UDS_VALID_FRAME_LEN] = {0};  		memset(send_buf, 0xcc, UDS_VALID_FRAME_LEN);    	if (msg_dlc == 0 || msg_dlc > UDS_SF_DL_MAX) return;        send_buf[0] = NT_SET_PCI_TYPE_SF ((uint8_t)msg_dlc);  	for (i = 0; i < msg_dlc; i++)          send_buf[1+i] = msg_buf[i];        ZTai_UDS_Send (send_buf, UDS_VALID_FRAME_LEN);    }      /**   * send_firstframe - send a first frame data   *   * service : L_Data.confirm (FF)   * @msg_buf : uds msg data buffer   * @msg_dlc : uds msg length   *   * returns:   *     int   */  static int  send_firstframe (uint8_t msg_buf[], uint16_t msg_dlc)  {  	uint16_t i;      uint8_t send_buf[UDS_VALID_FRAME_LEN] = {0};  		memset(send_buf, 0xcc, UDS_VALID_FRAME_LEN);    	if (msg_dlc < UDS_FF_DL_MIN || msg_dlc > UDS_FF_DL_MAX) return 0;        send_buf[0] = NT_SET_PCI_TYPE_FF ((uint8_t)(msg_dlc >> 8));  	send_buf[1] = (uint8_t)(msg_dlc & 0x00ff);  	for (i = 0; i < UDS_VALID_FRAME_LEN-2; i++)          send_buf[2+i] = msg_buf[i];        ZTai_UDS_Send (send_buf, UDS_VALID_FRAME_LEN);        /**       * start N_Bs and wait for a fc.       */      g_wait_fc = TRUE;      nt_timer_start (TIMER_N_BS);        	return UDS_VALID_FRAME_LEN-2;  }      /**   * send_consecutiveframe - send consecutive frame data   *   * service : L_Data.confirm (CF)   * @msg_buf : uds msg data buffer   * @msg_dlc : uds msg length   *   * returns:   *     int   */  static int  send_consecutiveframe (uint8_t msg_buf[], uint16_t msg_dlc, uint8_t frame_sn)  {  	uint16_t i;      uint8_t send_buf[UDS_VALID_FRAME_LEN] = {0};  		memset(send_buf, 0xcc, UDS_VALID_FRAME_LEN);        send_buf[0] = NT_SET_PCI_TYPE_CF (frame_sn);  	for (i = 0; i < msg_dlc && i < UDS_CF_DL_COM; i++)          send_buf[1+i] = msg_buf[i];  	for (; i < UDS_CF_DL_COM; i++)          send_buf[1+i] = 0;        ZTai_UDS_Send (send_buf, UDS_VALID_FRAME_LEN);        if (msg_dlc > UDS_CF_DL_COM)  	    return UDS_CF_DL_COM;  	else  	    return msg_dlc;  }  /**   * send_multipleframe - send a multiple frame msg   *   * @msg_buf : uds msg data buffer   * @msg_dlc : uds msg length   *   * returns:   *     void   */  static void  send_multipleframe (uint8_t msg_buf[], uint16_t msg_dlc)  {  	uint16_t i;  	uint8_t send_len;    	if (msg_dlc < UDS_FF_DL_MIN || msg_dlc > UDS_FF_DL_MAX) return;        for (i = 0; i < msg_dlc; i++)  	    remain_buf[i] = msg_buf[i];        g_xcf_sn = 0;      send_len = send_firstframe (msg_buf, msg_dlc);        remain_pos = send_len;  	remain_len = msg_dlc - send_len;  }  /*******************************************************************************      Function  Definition - external API  *******************************************************************************/    /**   * network_main - network main task, should be schedule every one ms   *   * @void   *   * returns:   *     void   */  extern void  network_main (void)  {      uint8_t send_len;  //    uint8_t err;      if (nt_timer_run (TIMER_N_CR) < 0)      {          clear_network ();  	    N_USData.indication (recv_buf, recv_len, N_TIMEOUT_Cr);      }      if (nt_timer_run (TIMER_N_BS) < 0)      {          clear_network ();          N_USData.confirm (N_TIMEOUT_Bs);      }    	if (nt_timer_run (TIMER_STmin) < 0)  	{          g_xcf_sn++;  		if (g_xcf_sn > 0x0f)  		    g_xcf_sn = 0;   //       OSMutexPend(UdsMutex,0,&err);  		send_len = send_consecutiveframe (&remain_buf[remain_pos], remain_len, g_xcf_sn);  		remain_pos += send_len;  		remain_len -= send_len;            if (remain_len > 0)          {              if (g_rfc_bs > 0)              {                  g_xcf_bc++;                  if (g_xcf_bc < g_rfc_bs)                  {                      nt_timer_start (TIMER_STmin);                  }                  else                  {                      /**                       * start N_Bs and wait for a fc.                       */                      g_wait_fc = TRUE;                      nt_timer_start (TIMER_N_BS);                  }              }              else              {                  nt_timer_start (TIMER_STmin);              }          }          else          {              clear_network ();          }   //       OSMutexPost(UdsMutex);  	}  }  /**   * network_recv_frame - recieved uds network can frame   *   * @func_addr : 0 - physical addr, 1 - functional addr   * @frame_buf : uds can frame data buffer   * @frame_dlc : uds can frame length   *   * returns:   *     void   */  extern void  network_recv_frame (uint8_t func_addr, uint8_t frame_buf[], uint8_t frame_dlc)  {  //    uint8_t err;      uint8_t pci_type; /* protocol control information type */          /**       * The reception of a CAN frame with a DLC value       * smaller than expected shall be ignored by the        * network layer without any further action       */      if(frame_dlc != UDS_VALID_FRAME_LEN) return;        if (func_addr == 0)          g_tatype = N_TATYPE_PHYSICAL;      else          g_tatype = N_TATYPE_FUNCTIONAL;     //   OSMutexPend(UdsMutex,0,&err);      pci_type = NT_GET_PCI_TYPE (frame_buf[0]);      switch(pci_type)      {          case PCI_SF:              if (nwl_st == NWL_RECV || nwl_st == NWL_IDLE)              {                  clear_network ();                  if (nwl_st == NWL_RECV)                      N_USData.indication (recv_buf, recv_len, N_UNEXP_PDU);                  recv_singleframe (frame_buf, frame_dlc);              }              break;          case PCI_FF:              if (nwl_st == NWL_RECV || nwl_st == NWL_IDLE)              {                  clear_network ();                  if (nwl_st == NWL_RECV)                      N_USData.indication (recv_buf, recv_len, N_UNEXP_PDU);                    if (recv_firstframe (frame_buf, frame_dlc) > 0)                      nwl_st = NWL_RECV;                  else                      nwl_st = NWL_IDLE;              }              break;          case PCI_CF:              if (nwl_st == NWL_RECV && g_wait_cf == TRUE)              {                  if (recv_consecutiveframe (frame_buf, frame_dlc) <= 0)                  {                      clear_network ();                      nwl_st = NWL_IDLE;                  }              }              break;          case PCI_FC:              if (nwl_st == NWL_XMIT && g_wait_fc == TRUE)                  if (recv_flowcontrolframe (frame_buf, frame_dlc) < 0)                  {                      clear_network ();                      nwl_st = NWL_IDLE;                  }              break;          default:              break;      }  //    OSMutexPost(UdsMutex);  }    /**   * network_send_udsmsg - send a uds msg by can   *   * @msg_buf : uds msg data buffer   * @msg_dlc : uds msg length   *   * returns:   *     void   */  extern void  network_send_udsmsg (uint8_t msg_buf[], uint16_t msg_dlc)  {    	if (msg_dlc == 0 || msg_dlc > UDS_FF_DL_MAX) return;    	if (msg_dlc <= UDS_SF_DL_MAX)      {  	    send_singleframe (msg_buf, msg_dlc);      }  	else      {          nwl_st = NWL_XMIT;  	    send_multipleframe (msg_buf, msg_dlc);      }  }    /**   * network_reg_usdata - reg usdata Function   *   * @usdata : uds msg data Function struct   *   * returns:   *     0 - ok, other - err   */  extern int  network_reg_usdata (nt_usdata_t usdata)  {  //    uint8_t err;      if (usdata.ffindication == NULL || usdata.indication == NULL || usdata.confirm == NULL) return -1;        N_USData = usdata;     //   UdsMutex = OSMutexCreate(5, &err);      return 0;  }  /****************EOF****************/



微信扫码关注

更新实时通知

(adsbygoogle = window.adsbygoogle || []).push({});

作者:admin 分类:nice文章 浏览: