1. 程式人生 > 其它 >【STM32H7教程】第91章 STM32H7的FDCAN匯流排基礎知識和HAL庫API

【STM32H7教程】第91章 STM32H7的FDCAN匯流排基礎知識和HAL庫API

完整教程下載地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980

第91章 STM32H7的FDCAN匯流排基礎知識和HAL庫API

本章節為大家講解FDCAN的基礎知識和對應的HAL庫API。CAN FD中的FD含義就是flexible data,靈活資料通訊,且波特率可以和仲裁階段波特率不同

91.1 初學者重要提示

91.2 FDCAN基礎知識

91.3 FDCAN的HAL庫用法

91.4 FDCAN原始檔stm32h7xx_hal_fdcan.c

91.5 總結

91.1 初學者重要提示

  1. FDCAN基礎知識點可以看第90章,已經進行了詳細說明
  2. 特別推薦瑞薩的CAN入門中英文手冊,做的非常好:http://www.armbbs.cn/forum.php?mod=viewthread&tid=14546

91.2 FDCAN基礎知識

FDCAN的基礎知識在本教程的第90章進行了非常詳細的說明。我們這裡將本章用到的幾個知識點再做個說明,詳情推薦看第90章。

91.2.1 CAN FD協議介紹

STM32H7的CAN FD符合ISO 11898-12015標準。STM32器件上的FDCAN的功能如下所示:

(1)符合CAN協議2.0版A,B和ISO 11898-1:2015,-4。

(2)可訪問的10 KB RAM記憶體,最多可分配2560個字。

(3)改進了接收過濾。

(4)兩個可配置的接收FIFO。

(5)多達64個專用接收緩衝區。

(6)接收高優先順序訊息時的單獨信令。

(7)多達32個專用傳送緩衝區。

(8)可配置的傳送FIFO和傳送佇列。

(9)可配置的傳送事件FIFO。

(10)時鐘校準單元。

(11)收發器延遲補償。

下圖說明了FDCAN框圖。

通過這個框圖要了解到以下資訊:

(1)CANFD1和CANFD2共用一個RAM空間。

(2)每個CANFD都有自己的核心。

(3)CAN核心實現協議控制和收發移位暫存器。

(4)Tx handler控制訊息從CAN訊息RAM到CAN核心。

(5)Rx handler控制CAN核心到CAN訊息RAM。

91.2.2 CAN FD特性

(1)相容經典CAN,可以遵循ISO 11898-1做資料收發。

(2)提升錯誤檢測,支援高達CRC 21位的校驗和。

(3)訊息優先順序。

(4)保證延遲時間。

(5)配置靈活性。

(6)具有時間同步的組播接收。

(7)系統範圍內的資料一致性,每條訊息最多64個位元組。

(8)多主機。

(9)錯誤檢測和訊號。

(10)區分節點的臨時錯誤和永久性故障以及自動關閉缺陷節點。

91.2.3 CAN FD格式

第一個仲裁階段(The first arbitration phase)是一條訊息,其中包含:

(1)幀開始(SOF)。

(2)ID號和其他位,指示訊息的目的(提供或請求資料),以及速度和格式配置(CAN或CAN-FD)。

資料傳輸階段(The data transmission phase)包括:

(1)資料長度程式碼(DLC),指示訊息包含多少資料位元組。

(2)使用者希望傳送的資料。

(3)檢查迴圈冗餘序列(CRC)。

(4)顯性位。

第二個仲裁階段(The second arbitration phase)包含:

(1)總線上其他節點發送的確認(ACK)的接收器(如果至少有一個接收器成功收到訊息)

(2)幀尾(EOF),在IFS期間不傳輸任何訊息:目標是將當前幀與下一幀分開。

注意:對於29bit識別符號幀,當新增18bit標識到第1個仲裁階段的IDE bit之後與標準CAN FD是類似的。

91.2.4 CAN FD相比CAN2.0的提升

CAN-FD的開發可以滿足需要更高頻寬的通訊網路需求。每幀最多具有64個位元組的CAN-FD以及將位元率提高到最大的可能性,使資料階段要快8倍,在第二個仲裁階段要恢復到正常的位元率。通過以下方式確保資料傳輸的完整性:

(1)17級多項式對最大16位元組的有效載荷進行CRC。

(2)21級多項式對16到64位元組之間的有效載荷進行校驗。

標準幀和CAN FD的區別:

識別符號後,CAN 2.0和CAN-FD具有不同的作用:

(1)CAN 2.0傳送RTR位以精確確定幀型別:資料幀(RTR為主要)或遠端幀(RTR)是隱性的)。

(2)由於CAN-FD僅支援資料幀,因此始終傳送佔優勢的RRS(保留)。

IDE位保持在相同位置,並以相同的動作來區分基本格式(11位識別符號)。請注意,在擴充套件格式的情況下,IDE位以顯性或隱性方式傳輸(29位識別符號)。

與CAN 2.0相比,在CAN-FD幀中,在控制欄位中添加了三個新位:

(1)擴充套件資料長度(EDL)位:隱性表示幀為CAN-FD,否則該位為顯性(稱為R0)在CAN 2.0幀中。

(2)位元率切換(BRS):指示是否啟用兩個位元率(例如,當資料階段位以不同的位元率傳輸到仲裁階段)。

(3)錯誤狀態指示器(ESI):指示節點處於錯誤活動模式還是錯誤被動模式。

控制欄位的最後一部分是資料長度程式碼(DLC),它具有相同的位置和相同的長度(4位),用於CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小變化(下表中的詳細資訊)。 CAN-FD擴充套件幀允許單個訊息中傳送64個數據位元組,而CAN 2.0有效負載資料最多可以傳送8個位元組。

通過增加有效載荷資料的資料欄位來改善網路頻寬,因為需要更少的包處理。 同時,通過為CRC新增更多位來增強訊息完整性:

(1)如果有效載荷資料最多為16個位元組,則CRC以17位編碼。

(2)如果有效載荷資料大於20(16)個位元組,則CRC以21位編碼。

另外,為了確保CAN-FD幀的魯棒性,填充位機制支援CRC欄位。下表總結了CAN-FD和CAN 2.0之間的主要區別。 提供的主要功能與CAN 2.0相比,CAN FD的改進之處在於資料有效負載的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位來確保。

91.3 FDCAN匯流排的HAL庫用法

91.3.1 FDCAN匯流排結構體FDCAN_GlobalTypeDef

FD CAN匯流排相關的暫存器是通過HAL庫中的結構體FDCAN_GlobalTypeDef定義,在stm32h743xx.h中可以找到這個型別定義:

typedef struct
{
  __IO uint32_t CREL;   
  __IO uint32_t ENDN;        
  __IO uint32_t RESERVED1;    
  __IO uint32_t DBTP;        
  __IO uint32_t TEST;        
  __IO uint32_t RWD;         
  __IO uint32_t CCCR;         
  __IO uint32_t NBTP;         
  __IO uint32_t TSCC;         
  __IO uint32_t TSCV;         
  __IO uint32_t TOCC;         
  __IO uint32_t TOCV;         
  __IO uint32_t RESERVED2[4];
  __IO uint32_t ECR;          
  __IO uint32_t PSR;          
  __IO uint32_t TDCR;         
  __IO uint32_t RESERVED3;    
  __IO uint32_t IR;           
  __IO uint32_t IE;           
  __IO uint32_t ILS;         
  __IO uint32_t ILE;         
  __IO uint32_t RESERVED4[8];
  __IO uint32_t GFC;          
  __IO uint32_t SIDFC;       
  __IO uint32_t XIDFC;       
  __IO uint32_t RESERVED5;   
  __IO uint32_t XIDAM;       
  __IO uint32_t HPMS;        
  __IO uint32_t NDAT1;       
  __IO uint32_t NDAT2;       
  __IO uint32_t RXF0C;        
  __IO uint32_t RXF0S;       
  __IO uint32_t RXF0A;       
  __IO uint32_t RXBC;       
  __IO uint32_t RXF1C;       
  __IO uint32_t RXF1S;       
  __IO uint32_t RXF1A;       
  __IO uint32_t RXESC;        
  __IO uint32_t TXBC;         
  __IO uint32_t TXFQS;        
  __IO uint32_t TXESC;        
  __IO uint32_t TXBRP;        
  __IO uint32_t TXBAR;       
  __IO uint32_t TXBCR;        
  __IO uint32_t TXBTO;        
  __IO uint32_t TXBCF;       
  __IO uint32_t TXBTIE;      
  __IO uint32_t TXBCIE;       
  __IO uint32_t RESERVED6[2]; 
  __IO uint32_t TXEFC;        
  __IO uint32_t TXEFS;        
  __IO uint32_t TXEFA;        
  __IO uint32_t RESERVED7;   
} FDCAN_GlobalTypeDef;

這個結構體的成員名稱和排列次序和CPU的暫存器是一 一對應的。

__IO表示volatile, 這是標準C語言中的一個修飾字,表示這個變數是非易失性的,編譯器不要將其優化掉。core_m7.h 檔案定義了這個巨集:

#define     __O     volatile             /*!< Defines 'write only' permissions */
#define     __IO    volatile             /*!< Defines 'read / write' permissions */

下面我們看下FDCAN的定義,在stm32h743xx.h檔案。

#define PERIPH_BASE           (0x40000000UL) 
#define D2_APB1PERIPH_BASE     PERIPH_BASE

#define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)
#define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)
#define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)

#define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展開這個巨集,(FDCAN_GlobalTypeDef *)0x4000A000
#define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
#define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)

我們訪問FDCAN1的CCCR暫存器可以採用這種形式:FDCAN1->CCCR = 0。

91.3.2 FDCAN匯流排時間觸發結構體TTCAN_TypeDef

FDCAN匯流排時間觸發相關的暫存器是通過HAL庫中的結構體TTCAN_TypeDef定義,在stm32h743xx.h中可以找到這個型別定義:

typedef struct
{
  __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */
  __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */
  __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */
  __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */
  __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */
  __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */
  __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
  __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
  __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
  __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
  __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */
  __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
  __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
  __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */
  __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
  __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
  __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */
  __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
  __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */
} TTCAN_TypeDef;

91.3.3 FDCAN匯流排初始化結構體FDCAN_InitTypeDef

下面是FDCAN匯流排的初始化結構體:

typedef struct
{
  uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.
                                              This parameter can be a value of @ref FDCAN_frame_format     */

  uint32_t Mode;                         /*!< Specifies the FDCAN mode.
                                              This parameter can be a value of @ref FDCAN_operating_mode   */

  FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.
                                              This parameter can be set to ENABLE or DISABLE               */

  FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.
                                              This parameter can be set to ENABLE or DISABLE               */

  FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.
                                              This parameter can be set to ENABLE or DISABLE               */

  uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is
                                              divided for generating the nominal bit time quanta.
                                              This parameter must be a number between 1 and 512            */

  uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
                                              hardware is allowed to lengthen or shorten a bit to perform
                                              resynchronization.
                                              This parameter must be a number between 1 and 128            */

  uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
                                              This parameter must be a number between 2 and 256            */

  uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.
                                              This parameter must be a number between 2 and 128            */

  uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is
                                              divided for generating the data bit time quanta.
                                              This parameter must be a number between 1 and 32             */

  uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN
                                              hardware is allowed to lengthen or shorten a data bit to
                                              perform resynchronization.
                                              This parameter must be a number between 1 and 16             */

  uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.
                                              This parameter must be a number between 1 and 32             */

  uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.
                                              This parameter must be a number between 1 and 16             */

  uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.
                                              This parameter must be a number between 0 and 2560           */

  uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.
                                              This parameter must be a number between 0 and 128            */

  uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.
                                              This parameter must be a number between 0 and 64             */

  uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
                                              This parameter must be a number between 0 and 64             */

  uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
                                              This parameter can be a value of @ref FDCAN_data_field_size  */

  uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
                                              This parameter must be a number between 0 and 64             */

  uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
                                              This parameter can be a value of @ref FDCAN_data_field_size  */

  uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.
                                              This parameter must be a number between 0 and 64             */

  uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.
                                              This parameter can be a value of @ref FDCAN_data_field_size  */

  uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.
                                              This parameter must be a number between 0 and 32             */

  uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.
                                              This parameter must be a number between 0 and 32             */

  uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
                                              This parameter must be a number between 0 and 32             */

  uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.
                                              This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */

  uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.
                                              This parameter can be a value of @ref FDCAN_data_field_size  */

} FDCAN_InitTypeDef;

下面將結構體成員逐一做個說明:

  • FrameFormat

用於設定CAN幀格式。

#define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 經典CAN模式 */
#define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不帶可變波特率 */
#define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN帶可變波特率 */
  • Mode

用於設定CAN操作模式。

#define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
#define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */
#define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 匯流排監測模式              */
#define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 內部環回模式              */
#define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部環回模式             */
  • AutoRetransmission

使能自動重傳模式。

使能ENABLE或者禁止DISABLE。

  • TransmitPause

使能或者禁止傳輸暫停特性。ENABLE使能或者DISABLE禁止。

  • ProtocolException

使能或者禁止協議異常管理。ENABLE表示使能,DISABLE表示禁止。

  • NominalPrescaler

用於CAN FD仲裁階段分頻設定,產生標稱位時間量,引數範圍1-512。

  • NominalSyncJumpWidth

設定FD CAN仲裁階段最大支援的時間量來加長或者縮短一個bit來實現再同步,引數範圍1-128。

  • NominalTimeSeg1

設定仲裁階段Bit Segment 1的時間量,範圍2 – 256。

  • NominalTimeSeg2

設定仲裁階段Bit Segment 2的時間量,範圍2 – 128。

  • DataPrescaler

用於CAN FD資料階段分頻設定,範圍1-32。

  • DataSyncJumpWidth

設定FD CAN資料階段最大支援的時間量來加長或者縮短一個bit來實現資料再同步,引數範圍1-16。

  • DataTimeSeg1

設定資料階段Data Bit Segment 1的時間量,範圍1 – 32。

  • DataTimeSeg2

設定資料階段Data Bit Segment 2的時間量,範圍1 – 16。

  • MessageRAMOffset

設定訊息RAM起始地址,範圍0到2560。

  • StdFiltersNbr

標準ID過濾個數,範圍0到128。

  • ExtFiltersNbr

擴充套件ID過濾個數,範圍0到64。

  • RxFifo0ElmtsNbr

RX FIFO0元素個數,範圍0到64。

  • RxFifo0ElmtSize

RX FIFO0每個元素中資料大小,支援引數如下:

#define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
#define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
#define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
#define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
#define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
#define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
#define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
#define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
  • RxFifo1ElmtsNbr

RX FIFO1個數,範圍0到64。

  • RxFifo1ElmtSize

RX FIFO1每個元素中資料大小,支援引數如下:

#define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
#define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
#define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
#define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
#define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
#define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
#define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
#define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
  • RxBuffersNbr

設定Rx Buffer元素個數,範圍0 - 64:

  • RxBuffersSize

設定Rx Buffer元素中每個資料大小,範圍0 - 64:

#define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
#define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
#define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
#define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
#define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
#define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
#define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
#define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
  • TxEventsNbr

Tx Event FIFO元素個數,範圍0到32。

  • TxBuffersNbr

設定專用的Tx Buffer元素個數,範圍0到32。

  • TxFifoQueueElmtsNbr

設定用於Tx FIFO/Queue的Tx Buffers個數。範圍0到32。

  • TxFifoQueueMode

設定FIFO模式或者QUEUE佇列模式。

#define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
#define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
  • TxElmtSize

設定Tx Element中的資料域大小。支援引數如下:

#define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
#define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
#define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
#define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
#define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
#define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
#define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
#define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */

91.3.4 FDCAN匯流排訊息RAM地址FDCAN_MsgRamAddressTypeDef

下面是訊息RAM結構體:

typedef struct
{
  uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.
                                  This parameter must be a 32-bit word address      */

  uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.
                                  This parameter must be a 32-bit word address      */

} FDCAN_MsgRamAddressTypeDef;

下面將結構體成員逐一做個說明:

  • StandardFilterSA

設定標準過濾器起始地址,必須是32bit地址。

  • ExtendedFilterSA

設定擴充套件過濾器起始地址,必須是32bit地址。

  • RxFIFO0SA

設定RX FIFO 0起始地址,必須是32bit地址。

  • RxFIFO1SA

設定RX FIFO 1起始地址,必須是32bit地址。

  • RxBufferSA

設定RX Buffer起始地址,必須是32bit地址。

  • TxEventFIFOSA

設定Tx Event FIFO起始地址,必須是32bit地址。

  • TTMemorySA

設定觸發記憶體起始地址,必須是32bit地址。

  • EndAddress

設定申請RAM空間的結束地址,必須是32bit地址。

91.3.5 FDCAN匯流排過濾結構體FDCAN_FilterTypeDef

下面是過濾結構體:

typedef struct
{
  uint32_t IdType;           /*!< Specifies the identifier type.
                                  This parameter can be a value of @ref FDCAN_id_type       */

  uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.
                                  This parameter must be a number between:
                                   - 0 and 127, if IdType is FDCAN_STANDARD_ID
                                   - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */

  uint32_t FilterType;       /*!< Specifies the filter type.
                                  This parameter can be a value of @ref FDCAN_filter_type.
                                  The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted
                                  only when IdType is FDCAN_EXTENDED_ID.
                                  This parameter is ignored if FilterConfig is set to
                                  FDCAN_FILTER_TO_RXBUFFER                                  */

  uint32_t FilterConfig;     /*!< Specifies the filter configuration.
                                  This parameter can be a value of @ref FDCAN_filter_config */

  uint32_t FilterID1;        /*!< Specifies the filter identification 1.
                                  This parameter must be a number between:
                                   - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                   - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */

  uint32_t FilterID2;        /*!< Specifies the filter identification 2.
                                  This parameter is ignored if FilterConfig is set to
                                  FDCAN_FILTER_TO_RXBUFFER.
                                  This parameter must be a number between:
                                   - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                   - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */

  uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
                                  matching message will be stored.
                                  This parameter must be a number between 0 and 63.
                                  This parameter is ignored if FilterConfig is different
                                  from FDCAN_FILTER_TO_RXBUFFER                             */

  uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
                                  calibration messages.
                                  This parameter is ignored if FilterConfig is different
                                  from FDCAN_FILTER_TO_RXBUFFER.
                                  This parameter can be:
                                   - 0 : ordinary message
                                   - 1 : calibration message                                */

} FDCAN_FilterTypeDef;
  • IdType

用於設定標準ID和擴充套件ID。

#define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 標準ID */
#define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 擴充套件ID */
  • FilterIndex

用於過濾索引,如果是標準ID,範圍0到127。如果是擴充套件ID,範圍0到64。

  • FilterType

用於設定過濾型別。如果成員FilterConfig設定為FDCAN_FILTER_TO_RXBUFFER,本引數將不起作用。

#define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 範圍過濾從FilterID1 到 FilterID2  */
#define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 專用ID過濾,FilterID1 或者FilterID2  */

/*!< 精度遮蔽過濾,FilterID1 = filter, FilterID2 = mask */
#define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U) 

/*!< 僅ID擴充套件模式支援此引數,範圍從FilterID1 到 FilterID2, EIDM mask not applied */
#define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
  • FilterConfig

用於設定過濾型別。

#define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止過濾
#define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果過濾匹配,將資料儲存到Rx FIFO 0
#define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果過濾匹配,將資料儲存到Rx FIFO 1
#define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果過濾匹配,拒絕此ID
#define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果過濾匹配,設定高優先順序
#define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果過濾匹配,設定高優先順序並儲存到FIFO 0
#define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果過濾匹配,設定高優先順序並儲存到FIFO 1
#define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果過濾匹配,儲存到Rx Buffer,並忽略FilterType
配置
  • FilterID1

用於設定過濾ID1。如果ID型別是FDCAN_STANDARD_ID,範圍0到0x7FF。如果ID型別是FDCAN_EXTENDED_ID,範圍是0 到0x1FFFFFFF。

  • FilterID2

用於設定過濾ID2。如果FilterConfig設定為FDCAN_FILTER_TO_RXBUFFER,此引數不起作用。如果ID型別是FDCAN_STANDARD_ID,範圍0到0x7FF。如果ID型別是FDCAN_EXTENDED_ID,範圍是0 到0x1FFFFFFF。

  • RxBufferIndex

匹配訊息儲存到Rx buffer中的索引。引數範圍0到63。如果FilterConfig設定為FDCAN_FILTER_TO_RXBUFFER,此引數不起作用。

  • IsCalibrationMsg

用於設定是否配置校準訊息。如果FilterConfig設定為FDCAN_FILTER_TO_RXBUFFER,此引數不起作用。

0 : 表示正常訊息。

1 : 標誌校準訊息。

91.3.6 FDCAN匯流排訊息傳送結構體FDCAN_TxHeaderTypeDef

下面是CAN FD傳送訊息結構體:

typedef struct
{
  uint32_t Identifier;          /*!< Specifies the identifier.
                                     This parameter must be a number between:
                                      - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                      - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */

  uint32_t IdType;              /*!< Specifies the identifier type for the message that will be
                                     transmitted.
                                     This parameter can be a value of @ref FDCAN_id_type               */

  uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.
                                     This parameter can be a value of @ref FDCAN_frame_type            */

  uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
                                      This parameter can be a value of @ref FDCAN_data_length_code     */

  uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.
                                     This parameter can be a value of @ref FDCAN_error_state_indicator */

  uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
                                     bit rate switching.
                                     This parameter can be a value of @ref FDCAN_bit_rate_switching    */

  uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or
                                     FD format.
                                     This parameter can be a value of @ref FDCAN_format                */

  uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.
                                     This parameter can be a value of @ref FDCAN_EFC                   */

  uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO
                                     element for identification of Tx message status.
                                     This parameter must be a number between 0 and 0xFF                */

} FDCAN_TxHeaderTypeDef;
  • Identifier

用於設定ID,如果IdType是標準FDCAN_STANDARD_ID,範圍0到0x7FF,如果IdType是FDCAN_EXTENDED_ID擴充套件ID,範圍0到0x1FFFFFFF。

  • IdType

用於設定標準ID或者擴充套件ID。

#define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 標準ID */
#define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 擴充套件ID */
  • TxFrameType

用於設定幀型別,資料幀或遙控幀。

#define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 資料幀 */
#define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遙控幀 */
  • DataLength

用於設定資料長度。

#define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */
#define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
#define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
#define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
#define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
#define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
#define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
#define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
#define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
#define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
#define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
#define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
#define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
#define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
#define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */
#define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
  • ErrorStateIndicator

用於設定錯誤狀態指示:

#define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 傳輸節點 error active  */
#define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 傳輸節點error passive */
  • BitRateSwitch

用於設定傳送是否波特率可變。

#define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN幀傳送/接收不帶波特率可變 */
#define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN幀傳送/接收帶波特率可變 */
  • FDFormat

用於設定傳送幀是經典格式還是CANFD格式。

#define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 幀傳送/接收使用經典CAN */
#define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 幀傳送/接收使用FDCAN格式 */
  • TxEventFifoControl

用於設定傳送事件FIFO控制。

#define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不儲存 Tx events */
#define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 儲存Tx events  */
  • MessageMarker

用於設定複製到TX EVENT FIFO的訊息Maker,來識別訊息狀態,範圍0到0xFF。

91.3.7 FDCAN匯流排訊息接收結構體FDCAN_RxHeaderTypeDef

下面是CAN FD接收訊息結構體:

typedef struct
{
  uint32_t Identifier;            /*!< Specifies the identifier.
                                       This parameter must be a number between:
                                        - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
                                        - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */

  uint32_t IdType;                /*!< Specifies the identifier type of the received message.
                                       This parameter can be a value of @ref FDCAN_id_type               */

  uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
                                       This parameter can be a value of @ref FDCAN_frame_type            */

  uint32_t DataLength;            /*!< Specifies the received frame length.
                                        This parameter can be a value of @ref FDCAN_data_length_code     */

  uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.
                                       This parameter can be a value of @ref FDCAN_error_state_indicator */

  uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit
                                       rate switching.
                                       This parameter can be a value of @ref FDCAN_bit_rate_switching    */

  uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD
                                       format.
                                       This parameter can be a value of @ref FDCAN_format                */

  uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame
                                       reception.
                                       This parameter must be a number between 0 and 0xFFFF              */

  uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.
                                       This parameter must be a number between:
                                        - 0 and 127, if IdType is FDCAN_STANDARD_ID
                                        - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */

  uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
                                         Acceptance of non-matching frames may be enabled via
                                         HAL_FDCAN_ConfigGlobalFilter().
                                         This parameter can be 0 or 1                                    */

} FDCAN_RxHeaderTypeDef;
  • Identifier

用於設定ID,如果IdType是標準FDCAN_STANDARD_ID,範圍0到0x7FF,如果IdType是FDCAN_EXTENDED_ID擴充套件ID,範圍0到0x1FFFFFFF。

  • IdType

用於設定標誌ID或者擴充套件ID。

#define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 標準ID */
#define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 擴充套件ID */
  • RxFrameType

用於設定接收幀型別,資料幀或遙控幀

#define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 資料幀 */
#define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遙控幀 */
  • DataLength

用於設定資料長度。

#define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */
#define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
#define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
#define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
#define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
#define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
#define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
#define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
#define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
#define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
#define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
#define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
#define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
#define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
#define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */
#define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
  • ErrorStateIndicator

用於設定錯誤狀態指示:

#define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 傳輸節點error active  */
#define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 傳輸節點error passive */
  • BitRateSwitch

用於設定接收是否帶波特率切換

#define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 幀傳送/接收不支援波特率可變*/
#define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 幀傳送/接收支援波特率可變 */
  • FDFormat

用於設定接收幀是經典格式還是CANFD格式

#define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 經典幀 */
#define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN幀 */
  • RxTimestamp

用於設定幀接收時間戳,範圍0到0xFFFF。

  • FilterIndex

用於設定接收過濾索引。如果是標準ID,範圍0到127,如果是擴充套件ID,範圍0到63。

  • IsFilterMatchingFrame

用於設定是否接收非匹配幀,通過函式HAL_FDCAN_ConfigGlobalFilter()可以使能。

0:表示不接受。

1:表示接收。

91.3.8 FDCAN匯流排控制代碼結構體FDCAN_HandleTypeDef

下面是CANFD控制代碼結構體:

#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
typedef struct __FDCAN_HandleTypeDef
#else
typedef struct
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
{
  FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */

  TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */

  FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */

  FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */

  uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
                                               of latest Tx FIFO/Queue request */

  __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */

  HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */

  __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */

#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */
  void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */
  void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */
  void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */
  void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */
  void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */
  void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */
  void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */
  void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */
  void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
  void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */
  void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */
  void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */
  void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
  void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */
  void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
  void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */

  void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */
  void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */

} FDCAN_HandleTypeDef;

注意事項:

條件編譯USE_HAL_FDCAN_REGISTER_CALLBACKS用來設定使用自定義回撥還是使用預設回撥,此定義一般放在stm32h7xx_hal_conf.h檔案裡面設定:

#define USE_HAL_FDCAN_REGISTER_CALLBACKS 1

函式HAL_FDCAN_RegisterCallback註冊回撥,取消註冊使用函式HAL_FDCAN_UnRegisterCallback。

這裡重點介紹下面幾個引數,其它引數主要是HAL庫內部使用和自定義回撥函式。

  • FDCAN_GlobalTypeDef *Instance

這個引數是暫存器的例化,方便操作暫存器。

  • TTCAN_TypeDef *ttcan

TT CAN時間觸發暫存器基地址。

  • FDCAN_InitTypeDef Init

FDCAN相關的初始化引數。

  • FDCAN_MsgRamAddressTypeDef msgRam

訊息RAM地址。

  • uint32_t LatestTxFifoQRequest

Tx buffer索引最後一個Tx FIFO/Queue引數。

  • __IO HAL_FDCAN_StateTypeDef State

HAL_LockTypeDef Lock

__IO uint32_t ErrorCode

程式內部使用的狀態引數。

  • 剩下的都是回撥函式

91.4 FD CAN匯流排原始檔stm32h7xx_hal_fdcan.c

此檔案涉及到的函式較多,這裡把幾個常用的函式做個說明:

91.4.1 函式HAL_FDCAN_Init

函式原型:

HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
{
  uint32_t tickstart;
  HAL_StatusTypeDef status;
  const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};

  /* 檢測FDCAN控制代碼是否有效 */
  if (hfdcan == NULL)
  {
    return HAL_ERROR;
  }

  /* 檢查FDCAN例化 */
  if (hfdcan->Instance == FDCAN1)
  {
    hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
  }

  /* 檢查函式引數 */
  assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
  assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
  assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
  assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
  assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
  assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
  assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
  assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
  assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
  assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));
  if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
  {
    assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));
    assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
    assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
    assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
  }
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
  if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
  {
    assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
  }
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
  if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
  {
    assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
  }
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
  if (hfdcan->Init.RxBuffersNbr > 0U)
  {
    assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
  }
  assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
  assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
  if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
  {
    assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
  }
  if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
  {
    assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
  }

#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  if (hfdcan->State == HAL_FDCAN_STATE_RESET)
  {
    /* 解鎖*/
    hfdcan->Lock = HAL_UNLOCKED;

    /* 復位設定預設回撥 */
    hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
    hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
    hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
    hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */
    hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
    hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */
    hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
    hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
    hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
    hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
    hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */
    hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */
    hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */
    hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */

    if (hfdcan->MspInitCallback == NULL)
    {
      hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */
    }

    /* 初始化CLOCK和NVIC  */
    hfdcan->MspInitCallback(hfdcan);
  }
#else
  if (hfdcan->State == HAL_FDCAN_STATE_RESET)
  {
    /* 解鎖 */
    hfdcan->Lock = HAL_UNLOCKED;

    /* 初始化底層硬體 */
    HAL_FDCAN_MspInit(hfdcan);
  }
#endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */

  /* 退出Sleep  */
  CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);

  /* 獲取時鐘 */
  tickstart = HAL_GetTick();

  /* 等待Sleep模式確認 */
  while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
  {
    if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    {
      /* 更新錯誤碼 */
      hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;

      /* 改變FDCAN狀態 */
      hfdcan->State = HAL_FDCAN_STATE_ERROR;

      return HAL_ERROR;
    }
  }

  /* 請求初始化 */
  SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);

  /* 獲取時鐘 */
  tickstart = HAL_GetTick();

  /* 等待CCCR暫存器的INIT位 */
  while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
  {
    /* 檢查溢位時間 */
    if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    {
      /* 更新錯誤碼 */
      hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;

      /* 設定FDCAN狀態 */
      hfdcan->State = HAL_FDCAN_STATE_ERROR;

      return HAL_ERROR;
    }
  }

  /* 使能配置修改 */
  SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);

  /* 設定是否自動重傳 */
  if (hfdcan->Init.AutoRetransmission == ENABLE)
  {
    CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
  }
  else
  {
    SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
  }

  /* 設定傳輸暫停特性 */
  if (hfdcan->Init.TransmitPause == ENABLE)
  {
    SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
  }
  else
  {
    CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
  }

  /* 設定協議異常處理 */
  if (hfdcan->Init.ProtocolException == ENABLE)
  {
    CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
  }
  else
  {
    SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
  }

  /* 設定FDCAN幀格式 */
  MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);

  /* 復位FDCAN操作模式 */
  CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));
  CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);

  /* 設定FDCAN操作模式:
               | Normal | Restricted |    Bus     | Internal | External
               |        | Operation  | Monitoring | LoopBack | LoopBack
     CCCR.TEST |   0    |     0      |     0      |    1     |    1
     CCCR.MON  |   0    |     0      |     1      |    1     |    0
     TEST.LBCK |   0    |     0      |     0      |    1     |    1
     CCCR.ASM  |   0    |     1      |     0      |    0     |    0
  */
  if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
  {
    /* 使能限制操作模式 */
    SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
  }
  else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
  {
    if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    {
      /* TEST暫存器寫訪問使能 */
      SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);

      /* 使能迴環模式 */
      SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);

      if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
      {
        SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
      }
    }
    else
    {
      /* 使能檢測模式 */
      SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
    }
  }
  else
  {
    /* Nothing to do: normal mode */
  }

  /* 設定nominal bit timing 暫存器 */
  hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
                            (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
                            (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
                            (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));

  /* 如果使能BRS(BitRate Switching可變波特率),設定data bit timing 暫存器*/
  if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
  {
    hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
                              (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
                              (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \
                              (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
  }

  if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
  {
    /* 設定Tx FIFO 或 Tx Queue 操作模式 */
    SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
  }

  /* 配置Tx element 大小 */
  if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
  {
    MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
  }

  /* 配置Rx FIFO 0 大小 */
  if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
  {
    MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));
  }

  /* 配置Rx FIFO 1大小 */
  if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
  {
    MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));
  }

  /* 配置 Rx buffer element 大小 */
  if (hfdcan->Init.RxBuffersNbr > 0U)
  {
    MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));
  }

  /* 預設是的事件觸發模式,如果使用時間觸發模式,使用者需要在HAL_FDCAN_Init 
後呼叫HAL_FDCAN_TT_ConfigOperation */
  if (hfdcan->Instance == FDCAN1)
  {
    CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
  }

  /* 初始化Tx FIFO/Queue */
  hfdcan->LatestTxFifoQRequest = 0U;

  /* 初始化錯誤碼 */
  hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

  /* 初始化FDCAN狀態 */
  hfdcan->State = HAL_FDCAN_STATE_READY;

  /* 計算每個RAM塊地址 */
  status = FDCAN_CalcultateRamBlockAddresses(hfdcan);

  /* 返回函式狀態 */
  return status;
}

函式描述:

此函式用於初始化FDCAN。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數,用於配置要初始化的引數。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

注意事項:

  1. 函式HAL_FDCAN_MspInit用於初始化FDCAN的底層時鐘、引腳等功能。需要使用者自己在此函式裡面實現具體的功能。由於這個函式是弱定義的,允許使用者在工程其它原始檔裡面重新實現此函式。當然,不限制一定要在此函式裡面實現,也可以像早期的標準庫那樣,使用者自己初始化即可,更靈活些。
  2. 如果形參hfdcan的結構體成員State沒有做初始狀態,這個地方就是個坑。特別是使用者搞了一個區域性變數FDCAN_HandleTypeDef FdCANHandle。

對於區域性變數來說,這個引數就是一個隨機值,如果是全域性變數還好,一般MDK和IAR都會將全部變數初始化為0,而恰好這個 HAL_FDCAN_STATE_RESET = 0x00U。

解決辦法有三

方法1:使用者自己初始化FDCAN和涉及到的GPIO等。

方法2:定義FDCAN_HandleTypeDef FdCANHandle為全域性變數。

方法3:下面的方法

if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)
{
    Error_Handler();
}  
if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)
{
    Error_Handler();
}

使用舉例:

FDCAN_HandleTypeDef hfdcan1;

/*
*********************************************************************************************************
*    函 數 名: bsp_InitCan1
*    功能說明: 初始CAN1
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_InitCan1(void)
{     
    /*                    位時間特性配置
        Bit time parameter         | Nominal      |  Data
        ---------------------------|--------------|----------------
        fdcan_ker_ck               | 20 MHz       | 20 MHz
        Time_quantum (tq)          | 50 ns        | 50 ns
        Synchronization_segment    | 1 tq         | 1 tq
        Propagation_segment        | 23 tq        | 1 tq
        Phase_segment_1            | 8 tq         | 4 tq
        Phase_segment_2            | 8 tq         | 4 tq
        Synchronization_Jump_width | 8 tq         | 4 tq
        Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
        Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
    */
    hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */             
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可變波特率 */  
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */ 
    hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自動重發 */ 
    hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止傳輸暫停特性 */
    hfdcan1.Init.ProtocolException = ENABLE;       /* 協議異常處理使能 */
    
    /* 
        配置仲裁階段波特率 
        CAN時鐘20MHz時,仲裁階段的波特率就是
        CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps    
        
        其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    */
/* CAN時鐘分配設定,一般設定為1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    hfdcan1.Init.NominalPrescaler = 0x01; 

    /* 用於動態調節  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */
    hfdcan1.Init.NominalSyncJumpWidth = 0x08; 

/* 特別注意這裡的Seg1,這裡是兩個引數之和,對應位時間特性圖的 Pro_Seg + Phase_Seg1 */
    hfdcan1.Init.NominalTimeSeg1 = 0x1F;      

/* 對應位時間特性圖的 Phase_Seg2 */
    hfdcan1.Init.NominalTimeSeg2 = 0x08;     


    /* 
        配置資料階段波特率 
        CAN時鐘20MHz時,資料階段的波特率就是
        CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
        
        其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2
    */
/* CAN時鐘分配設定,一般設定為1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
範圍1-32 */
    hfdcan1.Init.DataPrescaler = 0x01; 

/* 用於動態調節  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,範圍1-16 */
    hfdcan1.Init.DataSyncJumpWidth = 0x04;  

/* 特別注意這裡的Seg1,這裡是兩個引數之和,對應位時間特性圖的 Pro_Seg + Phase_Seg1,範圍 */
    hfdcan1.Init.DataTimeSeg1 = 0x05; 

/* 對應位時間特性圖的 Phase_Seg2 */        
    hfdcan1.Init.DataTimeSeg2 = 0x04;           
    
    
    hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560個字, 這裡CAN1分配前1280字 */
    
    
    hfdcan1.Init.StdFiltersNbr = 1;                     /* 設定標準ID過濾器個數,範圍0-128 */       
    hfdcan1.Init.ExtFiltersNbr = 0;                     /* 設定擴充套件ID過濾器個數,範圍0-64 */   
    hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 設定Rx FIFO0的元素個數,範圍0-64 */  
    /* 設定Rx FIFO0中每個元素大小,支援8,12,16,20,24,32,48或者64位元組 */   
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 
    hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 設定Rx FIFO1的元素個數,範圍0-64 */

/* 設定Rx FIFO1中每個元素大小,支援8,12,16,20,24,32,48或者64位元組 */    
    hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; 
    hfdcan1.Init.RxBuffersNbr = 0;                      /* 設定Rx Buffer個數,範圍0-64 */
    
/* 設定Rx Buffer中每個元素大小,支援8,12,16,20,24,32,48或者64位元組 */
hfdcan1.Init.RxBufferSize = 0;                         


    hfdcan1.Init.TxEventsNbr = 0;          /* 設定Tx Event FIFO中元素個數,範圍0-32 */    
    hfdcan1.Init.TxBuffersNbr = 0;         /* 設定Tx Buffer中元素個數,範圍0-32 */
    hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 設定用於Tx FIFO/Queue的Tx Buffers個數。範圍0到32 */
    hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 設定FIFO模式或者QUEUE佇列模式 */

/* 設定Tx Element中的資料域大小,支援8,12,16,20,24,32,48或者64位元組 */
    hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;          
    HAL_FDCAN_Init(&hfdcan1);


    //省略未寫

}

91.4.2 函式HAL_FDCAN_DeInit

函式原型:

HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
{
  /* 檢測控制代碼 */
  if (hfdcan == NULL)
  {
    return HAL_ERROR;
  }

  /* 檢查函式形參 */
  assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));

  /* 停止FDCAN */
  (void)HAL_FDCAN_Stop(hfdcan);

  /* 禁止中斷 */
  CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));

#if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  if (hfdcan->MspDeInitCallback == NULL)
  {
    hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
  }

  /* 復位底層硬體,如時鐘,NVIC等 */
  hfdcan->MspDeInitCallback(hfdcan);
#else
 /* 復位底層硬體,如時鐘,NVIC等 */
  HAL_FDCAN_MspDeInit(hfdcan);
#endif 

  /* 復位錯誤碼 */
  hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

  /* 設定FDCAN狀態 */
  hfdcan->State = HAL_FDCAN_STATE_RESET;

  /* 返回HAL_OK */
  return HAL_OK;
}

函式描述:

用於復位FDCAN。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

91.4.3 函式HAL_FDCAN_ConfigFilter

函式原型:

HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
{
  uint32_t FilterElementW1;
  uint32_t FilterElementW2;
  uint32_t *FilterAddress;
  HAL_FDCAN_StateTypeDef state = hfdcan->State;

  if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
  {
    /* 檢測函式引數 */
    assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
    assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    {
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
    }

    /* 標準ID */
    if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
    {
      /* 檢測函式形參 */
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
      if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
      {
        assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
        assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
      }

      /* 構建過濾元素 */
      if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
      {
        FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
                           (sFilterConfig->FilterID1 << 16U)       |
                           (sFilterConfig->IsCalibrationMsg << 8U) |
                           sFilterConfig->RxBufferIndex);
      }
      else
      {
        FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |
                           (sFilterConfig->FilterConfig << 27U) |
                           (sFilterConfig->FilterID1 << 16U)    |
                           sFilterConfig->FilterID2);
      }

      /* 計算過濾地址 */
      FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));

      /* 將過濾元素寫到訊息RAM中 */
      *FilterAddress = FilterElementW1;
}
/* 擴充套件ID */
    else 
    {
      /* 檢測函式引數 */
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
      assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));
      if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
      {
        assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
        assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));
      }

      /* 構建第1個word的過濾元素 */
      FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);

      /* 構建第2個word的過濾元素 */
      if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
      {
        FilterElementW2 = sFilterConfig->RxBufferIndex;
      }
      else
      {
        FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
      }

      /* 計算過濾地址 */
      FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));

      /* 寫過濾元素到訊息RAM */
      *FilterAddress = FilterElementW1;
      FilterAddress++;
      *FilterAddress = FilterElementW2;
    }

    return HAL_OK;
  }
  else
  {
    /* 更新錯誤碼e */
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;

    return HAL_ERROR;
  }
}

函式描述:

此函式主要用於設定FDCAN過濾。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 第2個引數是FDCAN_FilterTypeDef型別結構體變數,主要用於過濾引數配置。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

FDCAN_HandleTypeDef hfdcan1;

/*
*********************************************************************************************************
*    函 數 名: bsp_InitCan1
*    功能說明: 初始CAN1
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_InitCan1(void)
{     
    
    /* 
        配置過濾器, 過濾器主要用於接收,這裡取樣遮蔽位模式。
        FilterID1 = filter
        FilterID2 = mask
        
        FilterID2的mask每個bit含義
        0: 不關心,該位不用於比較;
        1: 必須匹配,接收到的ID必須與濾波器對應的ID位相一致。
        
        舉例說明:
        FilterID1 = 0x111
        FilterID2 = 0x7FF 
        表示僅接收ID為0x111的FDCAN幀。
        
    */
    sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 設定標準ID或者擴充套件ID */
    /* 用於過濾索引,如果是標準ID,範圍0到127。如果是擴充套件ID,範圍0到64 */
sFilterConfig1.FilterIndex = 0;                           
    sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 過濾器取樣遮蔽位模式 */
    sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果過濾匹配,將資料儲存到Rx FIFO 0 */
    sFilterConfig1.FilterID1 = 0x111;                       /* 遮蔽位模式下,FilterID1是訊息ID */
    sFilterConfig1.FilterID2 = 0x7FF;                     /* 遮蔽位模式下,FilterID2是訊息遮蔽位 */
    HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置過濾器 */

}

91.4.4 函式HAL_FDCAN_ConfigFifoWatermark

函式原型:

HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
{
  /* 檢測引數 */
  assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
  if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
  {
    assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
  }
  else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
  {
    assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
  }

  if (hfdcan->State == HAL_FDCAN_STATE_READY)
  {
    /* 設定傳送事件FIFO */
    if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    {
      MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
}
/* 設定接收FIFO0 */
    else if (FIFO == FDCAN_CFG_RX_FIFO0)
    {
      MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));
}
/* 設定接收FIFO1 */
    else 
    {
      MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
    }

    /* 返回狀態 */
    return HAL_OK;
  }
  else
  {
    /* 更新錯誤碼 */
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;

    return HAL_ERROR;
  }
}

函式描述:

此函式主要用於配置FIFO Watermark

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 第2個引數是FDCAN FIFO Watermark
#define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */
#define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
#define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
  • 第3個引數FIFO Watermark 中斷位置,如果是FDCAN_CFG_TX_EVENT_FIFO,範圍0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,範圍0到64。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

FDCAN_HandleTypeDef hfdcan1;

/* 設定Rx FIFO0的wartermark為1 */
HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);

91.4.5 函式HAL_FDCAN_ActivateNotification

函式原型:

HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)
{
  HAL_FDCAN_StateTypeDef state = hfdcan->State;

  /* 檢測函式形參 */
  assert_param(IS_FDCAN_IT(ActiveITs));

  if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
  {
    /* 使能中斷行 */
    if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
    {
      /* 使能中斷行0 */
      SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
    }
    else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
    {
      /* 使能中斷行1 */
      SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
    }
    else
    {
      /* 使能中斷行0和中斷行1 */
      hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);
    }

    if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
    {
      /* 使能Tx Buffer Transmission 中斷 */
      SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
    }

    if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
    {
      /* 使能 Tx Buffer Cancellation Finished 中斷 */
      SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);
    }

    /* 使能選擇的中斷 */
    __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);

    /* 返回函式狀態 */
    return HAL_OK;
  }
  else
  {
    /* 更新錯誤碼 */
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;

    return HAL_ERROR;
  }
}

函式描述:

此函式主要用於使能中斷。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 第2個引數用於設定要使能的中斷,支援的引數如下:
#define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  
#define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
#define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         

#define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */
#define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer 

#define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
#define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */

#define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
#define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred 

#define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */
#define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */
#define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */
#define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */

#define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */
#define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */
#define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
#define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */

#define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
#define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
#define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
#define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */

#define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              
#define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred 
#define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
#define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     
#define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            
#define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              

#define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
#define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */
#define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
  • 第3個引數是Tx Buffer Indexes,可以如下引數的任意組合:
#define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
#define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */
#define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */
#define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
#define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */
#define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */
#define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */
#define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
#define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */
#define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
#define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */
#define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
#define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
#define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
#define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
#define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
#define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
#define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
#define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
#define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
#define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
#define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */
#define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */
#define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
#define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
#define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */
#define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
#define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */
#define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
#define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
#define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
#define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */

如果第2個引數不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此引數將被忽略。

  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

FDCAN_HandleTypeDef hfdcan1;

/* 啟用RX FIFO0的watermark通知中斷,位開啟Tx Buffer中斷*/
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);

91.4.6 函式HAL_FDCAN_Start

函式原型:

HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)
{
  if (hfdcan->State == HAL_FDCAN_STATE_READY)
  {
    /* 設定FDCAN外設狀態 */
    hfdcan->State = HAL_FDCAN_STATE_BUSY;

    /* 請求離開初始化狀態 */
    CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);

    /* 設定錯誤碼 */
    hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

    return HAL_OK;
  }
  else
  {
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;

    return HAL_ERROR;
  }
}

函式描述:

此函式主要用於啟動FDCAN。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

/**
* @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
* @param  pData: Pointer to the buffer that will contain the data to transmit
* @param  WriteAddr: Address from where data is to be written
* @param  NumOfBlocks: Number of SD blocks to write
* @retval SD status
*/
uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
{

  if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
  {
    return MSD_OK;
  }
  else
  {
    return MSD_ERROR;
  }
}

91.4.7 函式HAL_FDCAN_AddMessageToTxFifoQ

函式原型:

HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
{
  uint32_t PutIndex;

  /* 檢查函式形參 */
  assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
  if (pTxHeader->IdType == FDCAN_STANDARD_ID)
  {
    assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
  }
  else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
  {
    assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
  }
  assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
  assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
  assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
  assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
  assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
  assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
  assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));

  if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
  {
    /* 檢測Tx FIFO/Queue 是否在RAM中分配到空間 */
    if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    {
      /* 更新錯誤碼 */
      hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

      return HAL_ERROR;
    }

    /* 檢查Tx FIFO/Queue 是否滿 */
    if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
    {
       /* 更新錯誤碼 */
      hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;

      return HAL_ERROR;
    }
    else
    {
      /* 獲取Tx FIFO PutIndex */
      PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);

      /* 新增訊息到Tx FIFO/Queue */
      FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);

      /* 啟用相應的傳輸請求 */
      hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);

      /* 儲存最近的Tx FIFO/Queue Request Buffer Index */
      hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
    }

    /* 返回錯誤狀態 */
    return HAL_OK;
  }
  else
  {
     /* 更新錯誤碼 */
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;

    return HAL_ERROR;
  }
}

函式描述:

此函式用於新增訊息到Tx FIFO/Queue並激活相應的傳輸請求。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 第2個引數是FDCAN_TxHeaderTypeDef型別結構體變數,用於訊息傳送。
  • 第3個引數是要傳送的資料地址。程式裡面會將資料複製到傳送緩衝區。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

/*
*********************************************************************************************************
*    函 數 名: can1_SendPacket
*    功能說明: 傳送一包資料
*    形    參:_DataBuf 資料緩衝區
*              _Len 資料長度, 支援8,12,16,20,24,32,48或者64位元組
*    返 回 值: 無
*********************************************************************************************************
*/
void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)
{        
    FDCAN_TxHeaderTypeDef TxHeader = {0};
    
    /* 配置傳送引數 */
    TxHeader.Identifier = 0x222;                      /* 設定接收幀訊息的ID */
    TxHeader.IdType = FDCAN_STANDARD_ID;              /* 標準ID */
    TxHeader.TxFrameType = FDCAN_DATA_FRAME;         /* 資料幀 */
    TxHeader.DataLength = (uint32_t)_Len << 16;      /* 傳送資料長度 */
    TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 設定錯誤狀態指示 */
    TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 開啟可變波特率 */
    TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */
    TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用於傳送事件FIFO控制, 不儲存 */
    TxHeader.MessageMarker = 0;     /* 用於複製到TX EVENT FIFO的訊息Maker來識別訊息狀態,範圍0到0xFF */
    
    /* 新增資料到TX FIFO */
    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
}

91.4.8 函式HAL_FDCAN_GetRxMessage

函式原型:

HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
{
  uint32_t *RxAddress;
  uint8_t  *pData;
  uint32_t ByteCounter;
  uint32_t GetIndex = 0;
  HAL_FDCAN_StateTypeDef state = hfdcan->State;

  if (state == HAL_FDCAN_STATE_BUSY)
  {
    if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    {
      /* 檢查Rx FIFO 0 分配了RAM空間  */
      if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
      {
        /* 更新錯誤碼*/
        hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

        return HAL_ERROR;
      }

      /* 檢查Rx FIFO 0 非空 */
      if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
      {
        /* 更新錯誤碼*/
        hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;

        return HAL_ERROR;
      }
      else
      {
        /* 檢查Rx FIFO 0 滿且開了覆蓋模式 */
        if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
        {
          if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
          {
            /* 開啟了覆蓋模式,丟棄第1個數據 */
            GetIndex = 1U;
          }
        }

        /* 計算Rx FIFO 0 element 索引 */
        GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);

        /* 計算 Rx FIFO 0 element 地址  */
        RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
      }
    }
    else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    {
       /* 檢查Rx FIFO 1 分配了RAM空間  */
      if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
      {
        /* 更新錯誤碼 */
        hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

        return HAL_ERROR;
      }

      /* 檢查 Rx FIFO 0 非空 */
      if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
      {
       /* 更新錯誤碼 */
        hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;

        return HAL_ERROR;
      }
      else
      {
         /* 檢查Rx FIFO 1 滿且開了覆蓋模式 */
        if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)
        {
          if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
          {
            /* 開啟了覆蓋模式,丟棄第1個數據 */
            GetIndex = 1U;
          }
        }

        /* 計算  Rx FIFO 1 element 索引 */
        GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);

        /* 計算 Rx FIFO 1 element 地址 */
        RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
      }
    }
    else /* Rx element 分配了專用 Rx buffer */
    {
      /* 檢查選擇的buffer分配了RAM空間 */
      if (RxLocation >= hfdcan->Init.RxBuffersNbr)
      {
        /* 更新錯誤碼 */
        hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

        return HAL_ERROR;
      }
      else
      {
        /* 計算Rx buffer 地址 */
        RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));
      }
    }

    /* 接收IdType */
    pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;

    /* 接收Identifier */
    if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
    {
      pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
    }
    else /* Extended ID element */
    {
      pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    }

    /* 接收RxFrameType */
    pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);

    /* 接收ErrorStateIndicator */
    pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);

    /* Increment RxAddress pointer to second word of Rx FIFO element */
    RxAddress++;

    /* 接收RxTimestamp */
    pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);

    /* 接收DataLength */
    pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);

    /* 接收BitRateSwitch */
    pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);

    /* 接收FDFormat */
    pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);

    /* 接收FilterIndex */
    pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);

    /* 接收NonMatchingFrame */
    pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);

    /* 增加地址,指向Rx FIFO element的payload */
    RxAddress++;

    /* 接收 Rx payload */
    pData = (uint8_t *)RxAddress;
    for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
    {
      pRxData[ByteCounter] = pData[ByteCounter];
    }

    if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
    {
      /* 確認Rx FIFO 0先進的資料已經讀出 */
      hfdcan->Instance->RXF0A = GetIndex;
    }
    else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    {
     /* 確認Rx FIFO 1先進的資料已經讀出 */
      hfdcan->Instance->RXF1A = GetIndex;
    }
    else /* Rx element is assigned to a dedicated Rx buffer */
    {
      /* 清除當前Rx buffer的新資料標誌 */
      if (RxLocation < FDCAN_RX_BUFFER32)
      {
        hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
      }
      else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
      {
        hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
      }
    }

    /* 返回狀態 */
    return HAL_OK;
  }
  else
  {
    /* 更新錯誤碼 */
    hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;

    return HAL_ERROR;
  }
}

函式描述:

此函式主要用於獲取接收到的資料。

函式引數:

  • 第1個引數是FDCAN_HandleTypeDef型別結構體指標變數。
  • 第2個引數是讀取位置,支援如下幾種引數:
#define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
#define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
#define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
#define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */
#define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */
#define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */
#define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
#define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
#define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
#define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
#define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
#define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
#define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */
#define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */
#define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */
#define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */
#define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */
#define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
#define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */
#define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */
#define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */
#define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */
#define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */
#define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
#define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */
#define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
#define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */
#define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */
#define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
#define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
#define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
#define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */
#define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
#define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */
#define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
#define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */
#define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
#define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
#define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
#define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
#define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */
#define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
#define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */
#define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
#define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */
#define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
#define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */
#define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
#define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
#define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */
#define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */
#define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */
#define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */
#define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
#define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
#define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */
#define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
#define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
#define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */
#define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */
#define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
#define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
#define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
#define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */
#define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */
#define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
  • 第3個引數是FDCAN_RxHeaderTypeDef型別結構體變數,主要用於訊息接收。
  • 第4個引數是資料接收緩衝地址。
  • 返回值,返回HAL_TIMEOUT表示超時,HAL_ERROR表示引數錯誤,HAL_OK表示傳送成功,HAL_BUSY表示忙,正在使用中。

使用舉例:

/*
*********************************************************************************************************
*    函 數 名: HAL_FDCAN_RxFifo0Callback
*    功能說明: CAN中斷服務程式-回撥函式
*    形    參: hfdcan
*    返 回 值: 無
*********************************************************************************************************
*/
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
    if (hfdcan == &hfdcan1)
    {
        if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
        {
            /* 從RX FIFO0讀取資料 */
            HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);

            /* 啟用Rx FIFO0 watermark notification */
            HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
            
            if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
            {
                bsp_PutMsg(MSG_CAN1_RX, 0);    /* 發訊息收到資料包,結果在g_Can1RxHeader, g_Can1RxData */
            }
        }
    }
}

91.5 總結

本章節就為大家講解這麼多,更多FDCAN知識可以看本教程的第90章。

微信公眾號:armfly_com 安富萊論壇:www.armbbs.cn 安富萊淘寶:https://armfly.taobao.com