衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CanIf發送邏輯CanIf_Transmit機制及CanIf發送配置解析

冬至子 ? 來源:汽車電子過山車 ? 作者:歡樂皮皮峰 ? 2023-07-17 15:51 ? 次閱讀

一.前言:

整個的AUTOSAR的CAN通信模塊的層次如圖:

圖片

通信模塊可以大致分為三大功能:數據發送功能,數據接收功能,狀態切換和管理功能。

我們的系列按照這樣的功能排序和自底向上的模塊排序,每次只介紹其中的一個模塊的其中一個功能的實現,所以在每篇文章中對于模塊不會事無巨細的介紹所有它所具備的功能,而是選擇性的介紹三大功能中的其中一個。BSW往上的所有模塊示例,為最大程度了解其設計思路以及避免侵權風險,將會采用遵循AUTOSAR架構的非商業代碼作為示例,其部分細節不保證完全遵循AUTOSAR最新的標準,不保證所有功能的具備,敬請理解。

二.Canif模塊及其發送函數CanIf_Transmit

在上節的文章中介紹了CAN模塊的發送底層邏輯,Can_Write函數的介紹。Can_Write函數已經對CAN驅動進行了抽象。抽象為了HOH供上層使用。而它的上層就是CanIf層.在CanIf模塊中,主要實現的功能如下:

1.傳輸請求(Transmit request)

傳輸請求功能的實現主體函數是CanIf_Transmit,這個函數內部調用Can_Write進行報文的發送

2.傳輸確認(Transmit confirmation)

傳輸確認功能的實現主體函數是CanIf_TxConfirmation,這個函數在CAN發送完成后被調用,作用是調用更上層的發送確認回調函數通知更上層的各個模塊對應的PDU已發送成功。

3.接收提示(Reception indication)

傳輸確認功能的實現主體函數是CanIf_RxIndication,這個函數在CAN發送完成后被調用,作用是調用更上層的發送確認回調函數通知更上層的各個模塊對應的PDU已發送成功。

4.CAN控制器模式切換(Controller mode control)

controller模式切換的功能實現主體函數是CanIf_SetControllerMode,涉及到模式切換的功能后面專題詳解

5.PDU模式切換(PDU mode control)

PDU模式切換的功能實現主體函數是CanIf_SetPduMode,涉及到模式切換的功能后面專題詳解

整個CanIf模塊實現的基本函數如下:

1.jpg

本文側重介紹CanIf模塊的發送功能。CanIf的報文發送功能由CanIf_Transmit函數實現,此函數原型如下:

Std_ReturnType CanIf_Transmit(PduIdType CanTxPduId,
                        const PduInfoType *PduInfoPtr)

此函數會調用MCAL的Can模塊中的Can_Write函數進行報文的發送。在上節介紹Can_Write函數的時候,說過其傳入的參數是以下:

  1. HOH
  2. CAN id:報文ID
  3. length:報文長度
  4. sdu:報文數據
  5. swPduHandle :tx_confirm的ID

而CanIf層的傳入參數變為了:

  1. CanTxPduId,
  2. PduInfoPtr這個參數包括了SduDataPtr和SduLength

所以CanTxPduId對Can_Write函數所需的HOH,CAN ID,swPduHandle做了抽象。我們基本也可以推斷出CanIf的TxPDU所需要配置的主要內容了。

三.Canif模塊的發送配置解析

以下例子用于說明CanIf層的tx配置。

Canif涉及到發送報文的主要配置結構體如下:

const CanIf_InitConfigType CanIfInitConfig =
{
  .CanIfConfigSet = 0, 
  .CanIfNumberOfCanRxPduIds = sizeof(CanIfRxPduConfigData)/sizeof(CanIf_RxPduConfigType),
  .CanIfNumberOfCanTXPduIds = sizeof(CanIfTxPduConfigData)/sizeof(CanIf_TxPduConfigType),
  .CanIfNumberOfDynamicCanTXPduIds = 0, 


  // Containers
  .CanIfHohConfigPtr = CanIfHohConfigData,
  .CanIfRxPduConfigPtr = CanIfRxPduConfigData,
  .CanIfTxPduConfigPtr = CanIfTxPduConfigData,
};

我們以下主要關注:

1.HOH的配置結構體CanIfHohConfigData,

2.發送PDU配置結構體CanIfTxPduConfigData

1.HOH的配置結構體CanIfHohConfigData,

對于HOH的配置結構體CanIfHohConfigData的結構如下:

const CanIf_InitHohConfigType CanIfHohConfigData[] = {


  {
        #if(CANIF_CONTROL_CAN_DRIVER ==STD_ON)
    .CanConfigSet = &CanConfigSetData,
    #endif
    .CanIfHrhConfig = CanIfHrhConfigData_Hoh_1,
      .CanIfHthConfig = CanIfHthConfigData_Hoh_1,
  },
};

其中配置了發送的HTH和接收的HRH。對于發送的HTH配置如下:

const CanIf_HthConfigType CanIfHthConfigData_Hoh_1[] =
{
  {
  .CanIfHthType = CAN_BASIC,
  .CanIfCanControllerIdRef = CANIF_Channel_1,
  .CanIfHthIdSymRef = HOH_3_UDSTX_Node,
  },
  {
    .CanIfHthType = CAN_BASIC,
    .CanIfCanControllerIdRef = CANIF_Channel_1,
    .CanIfHthIdSymRef = HOH_3_NMTX_Node,
  },
  {
  .CanIfHthType = CAN_BASIC,
  .CanIfCanControllerIdRef = CANIF_Channel_1,
  .CanIfHthIdSymRef = HOH_3_XCPTX_Node,
  },
  {
    .CanIfHthType = CAN_BASIC,
    .CanIfCanControllerIdRef = CANIF_Channel_1,
    .CanIfHthIdSymRef = HOH_3_EcuTestNode_CanCluster,
  },
};

主要就是引用了上節文章例子中介紹的CAN模塊配置的四個HOH。

2.發送PDU配置結構體數組CanIfTxPduConfigData

這個結構體數組有所有的發送PDU配置,每個PDU都是一個結構體成員,其中的一個成員配置示例如下:

const CanIf_TxPduConfigType CanIfTxPduConfigData[] = {
 {
  .CanIfTxConfrimPduId = CANTP_PDU_ID_UDS_PHYS_TX,
  .CanIfCanTxPduIdCanId = 0x7ea,
  .CanIfCanTxPduIdDlc = 8,
  .CanIfCanTxPduType = CANIF_PDU_TYPE_STATIC,
#if ( CANIF_READTXPDU_NOTIFY_STATUS_API == STD_ON )
  .CanIfReadTxPduNotifyStatus = false,
#endif
  .CanIfTxPduIdCanIdType = CANIF_CAN_ID_TYPE_11,
  .CanIfUserTxConfirmation = CanTp_TxConfirmation,
  .CanIfCanTxPduHthRef = &CanIfHthConfigData_Hoh_1[0],
  .PduIdRef = NULL,
  },
  .....
  }

關鍵的參數解釋如下:

  • CanIfTxConfrimPduId :用于為swPduHandle 復值,向對應的TxConfirm函數傳入參數。
  • CanIfCanTxPduIdCanId:對應PDU的報文ID
  • CanIfCanTxPduIdDlc:對應PDU的報文長度
  • CanIfUserTxConfirmation:發送確認回調函數
  • CanIfCanTxPduHthRef:發送此PDU要使用的HOH

類似上節的結尾說到的抽象。這些配置元素打包成一個結構體數組元素,

CanIf_Transmit需要傳入的CanTxPduId,即代表這個配置結構體數組的數組下標。用來索引到其抽象的對象屬性。說起來比較枯燥,以下是CanIf_Transmit的實現函數:

Std_ReturnType CanIf_Transmit(PduIdType CanTxPduId,
    const PduInfoType *PduInfoPtr)
{
  Can_PduType canPdu;
  const CanIf_TxPduConfigType *txEntry;
  CanIf_ControllerModeType csMode;
  CanIf_ChannelGetModeType pduMode;


  VALIDATE(CanIf_Global.initRun, CANIF_TRANSMIT_ID, CANIF_E_UNINIT );
  VALIDATE((PduInfoPtr != 0), CANIF_TRANSMIT_ID, CANIF_E_PARAM_POINTER );


  // Get the controller from L-PDU handle
  txEntry = CanIf_FindTxPduEntry(CanTxPduId);


  if (txEntry == 0)
  {
    VALIDATE(FALSE, CANIF_TRANSMIT_ID, CANIF_E_INVALID_TXPDUID);
    return E_NOT_OK;
  }


  CanIf_Arc_ChannelIdType channel = txEntry- >CanIfCanTxPduHthRef- >CanIfCanControllerIdRef;


  // Get and verify the controller mode
  if (CanIf_GetControllerMode(channel, &csMode) == E_NOT_OK){
    return E_NOT_OK;
  }


  if (csMode != CANIF_CS_STARTED){  // CANIF_161
    return E_NOT_OK;
  }


  // Get and verify the PDU channel mode control
  if (CanIf_GetPduMode(channel, &pduMode) == E_NOT_OK){
    return E_NOT_OK;
  }


  if ((pduMode != CANIF_GET_TX_ONLINE) && (pduMode != CANIF_GET_ONLINE)){
    return E_NOT_OK;
  }


  canPdu.id = txEntry- >CanIfCanTxPduIdCanId;
  canPdu.length = PduInfoPtr- >SduLength;
  canPdu.sdu = PduInfoPtr- >SduDataPtr;
  canPdu.swPduHandle = CanTxPduId;


  Can_ReturnType rVal = Can_Write(txEntry- >CanIfCanTxPduHthRef- >CanIfHthIdSymRef, &canPdu);


  if (rVal == CAN_NOT_OK){
    return E_NOT_OK;
  }
  if (rVal == CAN_BUSY)  // CANIF 082, CANIF 161
  {
    // Tx buffering not supported so just return.
    return E_NOT_OK;
  }

  return E_OK;
}

注意到其中CanIf_Transmit的傳入參數CanTxPduId的使用方式:

txEntry = CanIf_FindTxPduEntry(CanTxPduId);

CanIf_FindTxPduEntry的函數原型如下

static const CanIf_TxPduConfigType * CanIf_FindTxPduEntry(PduIdType id)
{
  if (id >= CanIf_ConfigPtr- >InitConfig- >CanIfNumberOfCanTXPduIds) {
    return NULL;
  } else {
    return &CanIf_ConfigPtr- >InitConfig- >CanIfTxPduConfigPtr[id];
  }
}

就是以CanIf_Transmit的傳入參數CanTxPduId為下標,找到對應的CanIfTxPduConfigData的數組成員。并獲取其屬性,對Can_Write函數的傳入參數進行配置。調用Can_Write函數進行發送。

四.發送確認函數:CanIf_TxConfirmation

CanIf_TxConfirmation是由Can模塊底層驅動在PDU傳輸完成后調用的。之前講到Can_Write函數的其中一個傳入參數:swPduHandle是用來在底層標記傳輸的PDU ID,在更新MessageBuffer前記住PDU對應的swPduHandle參數,在對應的PDU發出去后,底層驅動函數調用CanIf_TxConfirmation傳入swPduHandle。

而我們的CanIf_TxConfirmation實現如下:

void CanIf_TxConfirmation(PduIdType canTxPduId)
{
  VALIDATE_NO_RV(CanIf_Global.initRun, CANIF_TXCONFIRMATION_ID, CANIF_E_UNINIT)
  VALIDATE_NO_RV(canTxPduId < CanIf_ConfigPtr- >InitConfig- >CanIfNumberOfCanTXPduIds, CANIF_TXCONFIRMATION_ID, CANIF_E_PARAM_LPDU);


  const CanIf_TxPduConfigType* entry =
    &CanIf_ConfigPtr- >InitConfig- >CanIfTxPduConfigPtr[canTxPduId];


      if (entry- >CanIfUserTxConfirmation != NULL)
      {
        CanIf_ChannelGetModeType mode;
        CanIf_GetPduMode(entry- >CanIfCanTxPduHthRef- >CanIfCanControllerIdRef, &mode);
        if ((mode == CANIF_GET_TX_ONLINE) || (mode == CANIF_GET_ONLINE)
            || (mode == CANIF_GET_OFFLINE_ACTIVE) || (mode == CANIF_GET_OFFLINE_ACTIVE_RX_ONLINE) )
        {
          entry- >CanIfUserTxConfirmation(entry- >CanIfTxPduId);  /* CANIF053 */
        }
      }
      return;
}

在這個函數中,會直接向上文CanIfTxPduConfigData配置的CanIfUserTxConfirmation中傳入swPduHandle。

而在CanIf_Transmit中,swPduHandle又是由CanIfTxPduConfigData配置的CanIfTxConfrimPduId決定的。所以CanIfTxConfrimPduId會作為參數傳入對應的CanIfUserTxConfirmation。

這期的介紹就到這,本期介紹了CanIf主要實現的功能,主要函數,主要的發送配置以及CanIf_Transmit,CanIf_TxConfirmation的機制,可以了解CanIf做了更進一步的抽象,將HOH進一步抽象為了PDU。各個AUTOSAR架構的代碼實現并不一致,文中所有的函數實現和配置思路僅作參考。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • CAN通信
    +關注

    關注

    5

    文章

    94

    瀏覽量

    17943
  • 接收機
    +關注

    關注

    8

    文章

    1184

    瀏覽量

    53637
  • AUTOSAR
    +關注

    關注

    10

    文章

    363

    瀏覽量

    21781
  • PDU
    PDU
    +關注

    關注

    0

    文章

    94

    瀏覽量

    17033
  • CAN控制器
    +關注

    關注

    3

    文章

    74

    瀏覽量

    15103
收藏 人收藏

    評論

    相關推薦

    ZYNQ進階:PL端UART 發送設計案例

    主要是uart發送模塊的編碼講述,uart發送模塊設計主要分為波特率控制計數邏輯和按位發送邏輯,其具體編碼如下所示: 波特率控制計數
    的頭像 發表于 11-25 17:26 ?3656次閱讀
    ZYNQ進階:PL端UART <b class='flag-5'>發送</b>設計案例

    cubemx配置的串口中斷發送HAL_UART_Transmit_IT不行

    為何HAL_UART_Transmit發送,改成HAL_UART_Transmit_IT就不行了cube配置的stm32f407系統其他代碼均一樣while(HAL_OK
    發表于 12-10 08:39

    請問怎么用HAL_UART_Transmit發送數值型數據?

    如何用HAL_UART_Transmit 發送數值型數據?我看例程,都是發送字符型數據的uint8_t TxData[10]= "01234abcde"
    發表于 02-19 07:40

    AUTOSAR_MCAL_CAN_IM.pdf提示找不到 config/CanIf.xdm怎么解決?

    在 AUTOSAR_MCAL_CAN_IM.pdf 文件中聲明還需要 CanIf 插件來實現 CAN 插件。但是,當我嘗試在 Tresos 上添加 CanIf 模塊時,它給出了一個錯誤,提示找不到
    發表于 03-30 08:48

    在EB tresos 23.0.0中配置模塊時出錯怎么解決?

    在EB tresos 23.0.0中配置模塊時出錯模塊“CanIf_TS_T40D2M10I3R0”(在插件“CanIf_TS_T40D2M10I3R0”中定義)定義了無法找到的模式文件
    發表于 04-11 09:06

    Verilog實現UART之二:發送模塊

    波特率的16倍,因此對clk16x計數到16時,發送D0;計數到32時,發送D1……依此類推; 2.發送模塊代碼: module tx_module( inputclk16x,/*transm
    發表于 02-09 09:48 ?792次閱讀
    Verilog實現UART之二:<b class='flag-5'>發送</b>模塊

    發送隊列長度功率控制

    無線多跳網絡具有信道時變性強、拓撲動態變化等特點,需要簡單高效的功率控制機制。發射功率影響數據發送速率,而基于發送隊列長度的功率控制機制存在可行解。為此,結合無線多跳網絡中間節點需要協
    發表于 03-20 15:07 ?0次下載
    <b class='flag-5'>發送</b>隊列長度功率控制

    如何讓接收端知道發送端將要發送的字節流長度?

    tcp會將數據量較小,且發送時間間隔較短的數據一起打包發送,那么這里所講的時間較短是相比網絡延遲來說的。比如我們兩次發送間隔為0.00001s,那么網絡延遲為0.001s,這個時候兩次的數據就會打包
    的頭像 發表于 08-19 09:33 ?1610次閱讀
    如何讓接收端知道<b class='flag-5'>發送</b>端將要<b class='flag-5'>發送</b>的字節流長度?

    基于CAN總線進行網絡管理與Transceiver的關系梳理

    Transceiver1145在初始化或者handler程序中檢查喚醒源,判斷到上電或者CAN總線干擾事件時會通知EcuM有喚醒事件,之后EcuM通過CanIf模塊調用CanTrcv_CheckWakeup檢查喚醒源。
    發表于 08-23 11:19 ?3139次閱讀
    基于CAN總線進行網絡管理與Transceiver的關系梳理

    AUTOSAR通信之CanIf模塊簡介1

    CAN接口模塊(下文簡“CanIf”)位于底層CAN驅動(CanDrv)、CAN收發器(CanTrcv)和上層通信服務層(CanSm、CanNm)、CAN傳輸協議(CanTp)、PDU路由器(PduR)之間。它表示上層通信層的CAN驅動程序服務接口。
    的頭像 發表于 02-13 14:29 ?4229次閱讀
    AUTOSAR通信之<b class='flag-5'>CanIf</b>模塊簡介1

    AUTOSAR通信之CanIf模塊簡介2

    CAN接口模塊(下文簡“CanIf”)位于底層CAN驅動(CanDrv)、CAN收發器(CanTrcv)和上層通信服務層(CanSm、CanNm)、CAN傳輸協議(CanTp)、PDU路由器(PduR)之間。它表示上層通信層的CAN驅動程序服務接口。
    的頭像 發表于 02-13 14:29 ?2592次閱讀
    AUTOSAR通信之<b class='flag-5'>CanIf</b>模塊簡介2

    AUTOSAR通信之CanIf模塊簡介3

    CAN接口模塊(下文簡“CanIf”)位于底層CAN驅動(CanDrv)、CAN收發器(CanTrcv)和上層通信服務層(CanSm、CanNm)、CAN傳輸協議(CanTp)、PDU路由器(PduR)之間。它表示上層通信層的CAN驅動程序服務接口。
    的頭像 發表于 02-13 14:29 ?3648次閱讀
    AUTOSAR通信之<b class='flag-5'>CanIf</b>模塊簡介3

    EthIf模塊的主要作用是什么?Ethif的常見函數接口有哪些呢?

    正如我們了解的CanIf模塊一樣,作為CAN收發器,CAN控制器的統一上層ECU抽象,能夠讓我們實現CanIf上層的應用模塊與底層硬件解耦,大大增加了軟件的可移植性。
    的頭像 發表于 03-23 11:27 ?1633次閱讀

    PduR模塊的發送機制 PduR這個模塊對什么進行了抽象呢?

    前兩期,我們講了CAN模塊的發送邏輯,Canif模塊的發送邏輯發送確認
    的頭像 發表于 07-17 15:54 ?3317次閱讀
    PduR模塊的<b class='flag-5'>發送機制</b> PduR這個模塊對什么進行了抽象呢?

    云途正式發布量產版本AUTOSAR MCAL驅動軟件和配置工具

    云途MCAL軟件包RTM v1.1.0包含了YTM32B1ME05 和YTM32B1MD1兩個系列車規MCU的片上外設模塊的驅動程序代碼和MCAL驅動模塊所需的相應樁模塊(stub module)的示例代碼,如Det、Dem、CanIf、LinIf、EcuC和EcuM等。
    的頭像 發表于 07-19 15:29 ?2837次閱讀
    云途正式發布量產版本AUTOSAR MCAL驅動軟件和<b class='flag-5'>配置</b>工具
    百家乐注册彩金| 珠江太阳城广场| 绥阳县| 网上的百家乐官网怎么才能| 联合百家乐的玩法技巧和规则| 湘阴县| 百家乐规则技法| 德州扑克与梭哈| 五张百家乐官网的玩法技巧和规则| 中骏百家乐的玩法技巧和规则| 百家乐官网怎么开户| 圣淘沙百家乐现金网| 尊博| 百家乐不能视频| 晓游棋牌官方下载| 神话百家乐官网的玩法技巧和规则| 永利高官网| 百家乐官网游戏单机牌| 威尼斯人娱乐城动态| 百家乐官网园百利宫娱乐城信誉好...| 澳门百家乐娱乐场开户注册| 网上百家乐官网骗人吗| 百家乐真人游戏娱乐场| 百家乐官网怎打能赢| 百家乐公式论坛| 香港六合彩网址大全| 百家乐官网必胜方法如果你还想继续不看可能后悔一生 | 百家乐下注技术| 开远市| 百家乐007| 百家乐官网游戏打水方法| 金彩百家乐的玩法技巧和规则| 百家乐官网包赢| 全讯网xb112| 百家乐官网打格式| 德州扑克入门| 百家乐官网那里最好| 开16个赌场敛财| 网上百家乐娱乐网| 百家乐官网赌博现金网平台排名| 大发888游戏平台hg dafa 888 gw 大发888游戏平台dafa 888 gw |