你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7的FDCAN总线基础知识和HAL库API

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示
  FDCAN基础知识点可以看第90章,已经进行了详细说明
  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接
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框图。


f4f1d5cd872648458911e8be8ddfffe0.png



通过这个框图要了解到以下信息:

(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格式

c692adda5a1149b0a6e3d8a30745fd62.png



第一个仲裁阶段(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的区别:


050433e4b8fe4f4d91de7eb85d5e6bdd.png



标识符后,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个字节。


c4fbc9fa3f184422a77784de5280382d.png



通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为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位来确保。


a00dca8056bf40dc860b52366afa5197.png



91.3 FDCAN总线的HAL库用法
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef
FD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:

  1. typedef struct
  2. {
  3.   __IO uint32_t CREL;   
  4.   __IO uint32_t ENDN;        
  5.   __IO uint32_t RESERVED1;   
  6.   __IO uint32_t DBTP;        
  7.   __IO uint32_t TEST;        
  8.   __IO uint32_t RWD;         
  9.   __IO uint32_t CCCR;         
  10.   __IO uint32_t NBTP;         
  11.   __IO uint32_t TSCC;         
  12.   __IO uint32_t TSCV;         
  13.   __IO uint32_t TOCC;         
  14.   __IO uint32_t TOCV;         
  15.   __IO uint32_t RESERVED2[4];
  16.   __IO uint32_t ECR;         
  17.   __IO uint32_t PSR;         
  18.   __IO uint32_t TDCR;         
  19.   __IO uint32_t RESERVED3;   
  20.   __IO uint32_t IR;           
  21.   __IO uint32_t IE;           
  22.   __IO uint32_t ILS;         
  23.   __IO uint32_t ILE;         
  24.   __IO uint32_t RESERVED4[8];
  25.   __IO uint32_t GFC;         
  26.   __IO uint32_t SIDFC;      
  27.   __IO uint32_t XIDFC;      
  28.   __IO uint32_t RESERVED5;   
  29.   __IO uint32_t XIDAM;      
  30.   __IO uint32_t HPMS;        
  31.   __IO uint32_t NDAT1;      
  32.   __IO uint32_t NDAT2;      
  33.   __IO uint32_t RXF0C;        
  34.   __IO uint32_t RXF0S;      
  35.   __IO uint32_t RXF0A;      
  36.   __IO uint32_t RXBC;      
  37.   __IO uint32_t RXF1C;      
  38.   __IO uint32_t RXF1S;      
  39.   __IO uint32_t RXF1A;      
  40.   __IO uint32_t RXESC;        
  41.   __IO uint32_t TXBC;         
  42.   __IO uint32_t TXFQS;        
  43.   __IO uint32_t TXESC;        
  44.   __IO uint32_t TXBRP;        
  45.   __IO uint32_t TXBAR;      
  46.   __IO uint32_t TXBCR;        
  47.   __IO uint32_t TXBTO;        
  48.   __IO uint32_t TXBCF;      
  49.   __IO uint32_t TXBTIE;      
  50.   __IO uint32_t TXBCIE;      
  51.   __IO uint32_t RESERVED6[2];
  52.   __IO uint32_t TXEFC;        
  53.   __IO uint32_t TXEFS;        
  54.   __IO uint32_t TXEFA;        
  55.   __IO uint32_t RESERVED7;   
  56. } FDCAN_GlobalTypeDef;
复制代码

这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。

__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:

  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

下面我们看下FDCAN的定义,在stm32h743xx.h文件。

  1. #define PERIPH_BASE           (0x40000000UL)
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE

  3. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)
  4. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)
  5. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)

  6. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000
  7. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
  8. #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中可以找到这个类型定义:

  1. typedef struct
  2. {
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */
  22. } TTCAN_TypeDef;
复制代码

91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef
下面是FDCAN总线的初始化结构体:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  63. } FDCAN_InitTypeDef;
复制代码

下面将结构体成员逐一做个说明:

  FrameFormat
用于设置CAN帧格式。

  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

  Mode
用于设置CAN操作模式。

  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */
  5. #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每个元素中数据大小,支持参数如下:

  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

  RxFifo1ElmtsNbr
RX FIFO1个数,范围0到64。

  RxFifo1ElmtSize
RX FIFO1每个元素中数据大小,支持参数如下:

  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

  RxBuffersNbr
设置Rx Buffer元素个数,范围0 - 64:

  RxBuffersSize
设置Rx Buffer元素中每个数据大小,范围0 - 64:

  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
  8. #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队列模式。

  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码

  TxElmtSize
设置Tx Element中的数据域大小。支持参数如下:

  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
下面是消息RAM结构体:

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

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

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

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

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

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

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

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

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

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

  23. } 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
下面是过滤结构体:

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

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

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

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

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

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

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

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

  39. } FDCAN_FilterTypeDef;
复制代码

  IdType
用于设置标准ID和扩展ID。

  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

  FilterIndex
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。

  FilterType
用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。

  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */

  3. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */
  4. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)

  5. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */
  6. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

  FilterConfig
用于设置过滤类型。

  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1
  8. #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发送消息结构体:

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

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

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

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

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

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

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

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

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

  27. } FDCAN_TxHeaderTypeDef;
复制代码

  Identifier
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。

  IdType
用于设置标准ID或者扩展ID。

  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

  TxFrameType
用于设置帧类型,数据帧或遥控帧。

  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

  DataLength
用于设置数据长度。

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

  ErrorStateIndicator
用于设置错误状态指示:

  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

  BitRateSwitch
用于设置发送是否波特率可变。

  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码

  FDFormat
用于设置发送帧是经典格式还是CANFD格式。

  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码

  TxEventFifoControl
用于设置发送事件FIFO控制。

  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
  2. #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接收消息结构体:

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

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

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

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

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

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

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

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

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

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

  32. } FDCAN_RxHeaderTypeDef;
复制代码

  Identifier
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。

  IdType
用于设置标志ID或者扩展ID。

  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

  RxFrameType
用于设置接收帧类型,数据帧或遥控帧

  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

  DataLength
用于设置数据长度。

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

用于设置错误状态指示:

  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

  BitRateSwitch
用于设置接收是否带波特率切换

  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

  FDFormat
用于设置接收帧是经典格式还是CANFD格式

  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
  2. #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句柄结构体:

  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  2. typedef struct __FDCAN_HandleTypeDef
  3. #else
  4. typedef struct
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
  6. {
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */

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

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

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

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

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

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

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

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

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

  37. } FDCAN_HandleTypeDef;
复制代码

注意事项:

条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
  1. #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
函数原型:

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

  6.   /* 检测FDCAN句柄是否有效 */
  7.   if (hfdcan == NULL)
  8.   {
  9.     return HAL_ERROR;
  10.   }

  11.   /* 检查FDCAN例化 */
  12.   if (hfdcan->Instance == FDCAN1)
  13.   {
  14.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
  15.   }

  16.   /* 检查函数参数 */
  17.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
  18.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
  19.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
  20.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
  21.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
  22.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
  23.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
  24.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
  25.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
  26.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));
  27.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
  28.   {
  29.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));
  30.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
  31.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
  32.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
  33.   }
  34.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
  35.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
  36.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
  37.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
  38.   {
  39.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
  40.   }
  41.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
  42.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
  43.   {
  44.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
  45.   }
  46.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
  47.   if (hfdcan->Init.RxBuffersNbr > 0U)
  48.   {
  49.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
  50.   }
  51.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
  52.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
  53.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
  54.   {
  55.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
  56.   }
  57.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
  58.   {
  59.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
  60.   }

  61. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  62.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
  63.   {
  64.     /* 解锁*/
  65.     hfdcan->Lock = HAL_UNLOCKED;

  66.     /* 复位设置默认回调 */
  67.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
  68.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
  69.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
  70.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
  71.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */
  72.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
  73.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
  74.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */
  75.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
  76.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
  77.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
  78.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
  79.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */
  80.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */
  81.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
  82.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */
  83.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */

  84.     if (hfdcan->MspInitCallback == NULL)
  85.     {
  86.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */
  87.     }

  88.     /* 初始化CLOCK和NVIC  */
  89.     hfdcan->MspInitCallback(hfdcan);
  90.   }
  91. #else
  92.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
  93.   {
  94.     /* 解锁 */
  95.     hfdcan->Lock = HAL_UNLOCKED;

  96.     /* 初始化底层硬件 */
  97.     HAL_FDCAN_MspInit(hfdcan);
  98.   }
  99. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */

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

  102.   /* 获取时钟 */
  103.   tickstart = HAL_GetTick();

  104.   /* 等待Sleep模式确认 */
  105.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
  106.   {
  107.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
  108.     {
  109.       /* 更新错误码 */
  110.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;

  111.       /* 改变FDCAN状态 */
  112.       hfdcan->State = HAL_FDCAN_STATE_ERROR;

  113.       return HAL_ERROR;
  114.     }
  115.   }

  116.   /* 请求初始化 */
  117.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);

  118.   /* 获取时钟 */
  119.   tickstart = HAL_GetTick();

  120.   /* 等待CCCR寄存器的INIT位 */
  121.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
  122.   {
  123.     /* 检查溢出时间 */
  124.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
  125.     {
  126.       /* 更新错误码 */
  127.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;

  128.       /* 设置FDCAN状态 */
  129.       hfdcan->State = HAL_FDCAN_STATE_ERROR;

  130.       return HAL_ERROR;
  131.     }
  132.   }

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

  135.   /* 设置是否自动重传 */
  136.   if (hfdcan->Init.AutoRetransmission == ENABLE)
  137.   {
  138.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
  139.   }
  140.   else
  141.   {
  142.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
  143.   }

  144.   /* 设置传输暂停特性 */
  145.   if (hfdcan->Init.TransmitPause == ENABLE)
  146.   {
  147.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
  148.   }
  149.   else
  150.   {
  151.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
  152.   }

  153.   /* 设置协议异常处理 */
  154.   if (hfdcan->Init.ProtocolException == ENABLE)
  155.   {
  156.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
  157.   }
  158.   else
  159.   {
  160.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
  161.   }

  162.   /* 设置FDCAN帧格式 */
  163.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);

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

  167.   /* 设置FDCAN操作模式:
  168.                | Normal | Restricted |    Bus     | Internal | External
  169.                |        | Operation  | Monitoring | LoopBack | LoopBack
  170.      CCCR.TEST |   0    |     0      |     0      |    1     |    1
  171.      CCCR.MON  |   0    |     0      |     1      |    1     |    0
  172.      TEST.LBCK |   0    |     0      |     0      |    1     |    1
  173.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0
  174.   */
  175.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
  176.   {
  177.     /* 使能限制操作模式 */
  178.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
  179.   }
  180.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
  181.   {
  182.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
  183.     {
  184.       /* TEST寄存器写访问使能 */
  185.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);

  186.       /* 使能回环模式 */
  187.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);

  188.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
  189.       {
  190.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
  191.       }
  192.     }
  193.     else
  194.     {
  195.       /* 使能检测模式 */
  196.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
  197.     }
  198.   }
  199.   else
  200.   {
  201.     /* Nothing to do: normal mode */
  202.   }

  203.   /* 设置nominal bit timing 寄存器 */
  204.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
  205.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
  206.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
  207.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));

  208.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/
  209.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
  210.   {
  211.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
  212.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
  213.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \
  214.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
  215.   }

  216.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
  217.   {
  218.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
  219.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
  220.   }

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

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

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

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

  241.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
  242. 后调用HAL_FDCAN_TT_ConfigOperation */
  243.   if (hfdcan->Instance == FDCAN1)
  244.   {
  245.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
  246.   }

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

  249.   /* 初始化错误码 */
  250.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

  251.   /* 初始化FDCAN状态 */
  252.   hfdcan->State = HAL_FDCAN_STATE_READY;

  253.   /* 计算每个RAM块地址 */
  254.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);

  255.   /* 返回函数状态 */
  256.   return status;
  257. }
复制代码

函数描述:

此函数用于初始化FDCAN。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
注意事项:

函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。

解决办法有三

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

方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。

方法3:下面的方法

  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)
  2. {
  3.     Error_Handler();
  4. }  
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)
  6. {
  7.     Error_Handler();
  8. }
复制代码

使用举例:

  1. FDCAN_HandleTypeDef hfdcan1;

  2. /*
  3. *********************************************************************************************************
  4. *        函 数 名: bsp_InitCan1
  5. *        功能说明: 初始CAN1
  6. *        形    参: 无
  7. *        返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_InitCan1(void)
  11. {         
  12.         /*                    位时间特性配置
  13.                 Bit time parameter         | Nominal      |  Data
  14.                 ---------------------------|--------------|----------------
  15.                 fdcan_ker_ck               | 20 MHz       | 20 MHz
  16.                 Time_quantum (tq)          | 50 ns        | 50 ns
  17.                 Synchronization_segment    | 1 tq         | 1 tq
  18.                 Propagation_segment        | 23 tq        | 1 tq
  19.                 Phase_segment_1            | 8 tq         | 4 tq
  20.                 Phase_segment_2            | 8 tq         | 4 tq
  21.                 Synchronization_Jump_width | 8 tq         | 4 tq
  22.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
  23.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
  24.         */
  25.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */            
  26.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  
  27.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */
  28.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */
  29.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */
  30.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */
  31.         
  32.         /*
  33.                 配置仲裁阶段波特率
  34.                 CAN时钟20MHz时,仲裁阶段的波特率就是
  35.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        
  36.                
  37.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
  38.         */
  39. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
  40.         hfdcan1.Init.NominalPrescaler = 0x01;

  41.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */
  42.         hfdcan1.Init.NominalSyncJumpWidth = 0x08;

  43. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */
  44.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;         

  45. /* 对应位时间特性图的 Phase_Seg2 */
  46.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     


  47.         /*
  48.                 配置数据阶段波特率
  49.                 CAN时钟20MHz时,数据阶段的波特率就是
  50.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
  51.                
  52.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2
  53.         */
  54. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
  55. 范围1-32 */
  56.         hfdcan1.Init.DataPrescaler = 0x01;

  57. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
  58.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  

  59. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
  60.         hfdcan1.Init.DataTimeSeg1 = 0x05;

  61. /* 对应位时间特性图的 Phase_Seg2 */               
  62.         hfdcan1.Init.DataTimeSeg2 = 0x04;           
  63.         
  64.         
  65.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */
  66.         
  67.         
  68.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
  69.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   
  70.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  
  71.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
  72. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
  73.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */

  74. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        
  75.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
  76.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
  77.         
  78. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
  79. hfdcan1.Init.RxBufferSize = 0;                             


  80.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        
  81.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
  82.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */
  83.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */

  84. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */
  85.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;         
  86.         HAL_FDCAN_Init(&hfdcan1);


  87.         //省略未写

  88. }
复制代码

91.4.2 函数HAL_FDCAN_DeInit
函数原型:

  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
  2. {
  3.   /* 检测句柄 */
  4.   if (hfdcan == NULL)
  5.   {
  6.     return HAL_ERROR;
  7.   }

  8.   /* 检查函数形参 */
  9.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));

  10.   /* 停止FDCAN */
  11.   (void)HAL_FDCAN_Stop(hfdcan);

  12.   /* 禁止中断 */
  13.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));

  14. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
  15.   if (hfdcan->MspDeInitCallback == NULL)
  16.   {
  17.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
  18.   }

  19.   /* 复位底层硬件,如时钟,NVIC等 */
  20.   hfdcan->MspDeInitCallback(hfdcan);
  21. #else
  22. /* 复位底层硬件,如时钟,NVIC等 */
  23.   HAL_FDCAN_MspDeInit(hfdcan);
  24. #endif

  25.   /* 复位错误码 */
  26.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

  27.   /* 设置FDCAN状态 */
  28.   hfdcan->State = HAL_FDCAN_STATE_RESET;

  29.   /* 返回HAL_OK */
  30.   return HAL_OK;
  31. }
复制代码

函数描述:

用于复位FDCAN。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
91.4.3 函数HAL_FDCAN_ConfigFilter
函数原型:

  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
  2. {
  3.   uint32_t FilterElementW1;
  4.   uint32_t FilterElementW2;
  5.   uint32_t *FilterAddress;
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;

  7.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
  8.   {
  9.     /* 检测函数参数 */
  10.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
  11.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
  12.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
  13.     {
  14.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
  16.     }

  17.     /* 标准ID */
  18.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
  19.     {
  20.       /* 检测函数形参 */
  21.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
  22.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
  23.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
  24.       {
  25.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
  26.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
  27.       }

  28.       /* 构建过滤元素 */
  29.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
  30.       {
  31.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
  32.                            (sFilterConfig->FilterID1 << 16U)       |
  33.                            (sFilterConfig->IsCalibrationMsg << 8U) |
  34.                            sFilterConfig->RxBufferIndex);
  35.       }
  36.       else
  37.       {
  38.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |
  39.                            (sFilterConfig->FilterConfig << 27U) |
  40.                            (sFilterConfig->FilterID1 << 16U)    |
  41.                            sFilterConfig->FilterID2);
  42.       }

  43.       /* 计算过滤地址 */
  44.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));

  45.       /* 将过滤元素写到消息RAM中 */
  46.       *FilterAddress = FilterElementW1;
  47. }
  48. /* 扩展ID */
  49.     else
  50.     {
  51.       /* 检测函数参数 */
  52.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
  53.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));
  54.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
  55.       {
  56.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
  57.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));
  58.       }

  59.       /* 构建第1个word的过滤元素 */
  60.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);

  61.       /* 构建第2个word的过滤元素 */
  62.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
  63.       {
  64.         FilterElementW2 = sFilterConfig->RxBufferIndex;
  65.       }
  66.       else
  67.       {
  68.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
  69.       }

  70.       /* 计算过滤地址 */
  71.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));

  72.       /* 写过滤元素到消息RAM */
  73.       *FilterAddress = FilterElementW1;
  74.       FilterAddress++;
  75.       *FilterAddress = FilterElementW2;
  76.     }

  77.     return HAL_OK;
  78.   }
  79.   else
  80.   {
  81.     /* 更新错误码e */
  82.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;

  83.     return HAL_ERROR;
  84.   }
  85. }
复制代码

函数描述:

此函数主要用于设置FDCAN过滤。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:

  1. FDCAN_HandleTypeDef hfdcan1;

  2. /*
  3. *********************************************************************************************************
  4. *        函 数 名: bsp_InitCan1
  5. *        功能说明: 初始CAN1
  6. *        形    参: 无
  7. *        返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void bsp_InitCan1(void)
  11. {         
  12.         
  13.         /*
  14.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。
  15.                 FilterID1 = filter
  16.                 FilterID2 = mask
  17.                
  18.                 FilterID2的mask每个bit含义
  19.                 0: 不关心,该位不用于比较;
  20.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。
  21.                
  22.                 举例说明:
  23.                 FilterID1 = 0x111
  24.                 FilterID2 = 0x7FF
  25.                 表示仅接收ID为0x111的FDCAN帧。
  26.                
  27.         */
  28.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */
  29.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
  30. sFilterConfig1.FilterIndex = 0;                                                   
  31.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */
  32.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
  33.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
  34.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
  35.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */

  36. }
复制代码

91.4.4 函数HAL_FDCAN_ConfigFifoWatermark
函数原型:

  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
  2. {
  3.   /* 检测参数 */
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
  6.   {
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
  8.   }
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
  10.   {
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
  12.   }

  13.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
  14.   {
  15.     /* 设置发送事件FIFO */
  16.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
  17.     {
  18.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
  19. }
  20. /* 设置接收FIFO0 */
  21.     else if (FIFO == FDCAN_CFG_RX_FIFO0)
  22.     {
  23.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));
  24. }
  25. /* 设置接收FIFO1 */
  26.     else
  27.     {
  28.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
  29.     }

  30.     /* 返回状态 */
  31.     return HAL_OK;
  32.   }
  33.   else
  34.   {
  35.     /* 更新错误码 */
  36.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;

  37.     return HAL_ERROR;
  38.   }
  39. }
复制代码

函数描述:

此函数主要用于配置FIFO Watermark

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  第2个参数是FDCAN FIFO Watermark
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
  3. #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表示忙,正在使用中。
使用举例:

  1. FDCAN_HandleTypeDef hfdcan1;

  2. /* 设置Rx FIFO0的wartermark为1 */
  3. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码

91.4.5 函数HAL_FDCAN_ActivateNotification
函数原型:

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

  4.   /* 检测函数形参 */
  5.   assert_param(IS_FDCAN_IT(ActiveITs));

  6.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
  7.   {
  8.     /* 使能中断行 */
  9.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
  10.     {
  11.       /* 使能中断行0 */
  12.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
  13.     }
  14.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
  15.     {
  16.       /* 使能中断行1 */
  17.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
  18.     }
  19.     else
  20.     {
  21.       /* 使能中断行0和中断行1 */
  22.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);
  23.     }

  24.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
  25.     {
  26.       /* 使能Tx Buffer Transmission 中断 */
  27.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
  28.     }

  29.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
  30.     {
  31.       /* 使能 Tx Buffer Cancellation Finished 中断 */
  32.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);
  33.     }

  34.     /* 使能选择的中断 */
  35.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);

  36.     /* 返回函数状态 */
  37.     return HAL_OK;
  38.   }
  39.   else
  40.   {
  41.     /* 更新错误码 */
  42.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;

  43.     return HAL_ERROR;
  44.   }
  45. }
复制代码

函数描述:

此函数主要用于使能中断。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  第2个参数用于设置要使能的中断,支持的参数如下:
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */

  8. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
  9. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred
  10. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */
  11. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */
  12. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */
  13. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */

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

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

  22. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              
  23. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
  24. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
  25. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     
  26. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            
  27. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              
  28. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
  29. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */
  30. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码

  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
  32. #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
函数原型:

  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)
  2. {
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
  4.   {
  5.     /* 设置FDCAN外设状态 */
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;

  7.     /* 请求离开初始化状态 */
  8.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);

  9.     /* 设置错误码 */
  10.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;

  11.     return HAL_OK;
  12.   }
  13.   else
  14.   {
  15.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;

  16.     return HAL_ERROR;
  17.   }
  18. }
复制代码

函数描述:

此函数主要用于启动FDCAN。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:

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

  10.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
  11.   {
  12.     return MSD_OK;
  13.   }
  14.   else
  15.   {
  16.     return MSD_ERROR;
  17.   }
  18. }
复制代码

91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
函数原型:

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

  4.   /* 检查函数形参 */
  5.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
  6.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
  7.   {
  8.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
  9.   }
  10.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
  11.   {
  12.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
  13.   }
  14.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
  15.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
  16.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
  17.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
  18.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
  19.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
  20.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));

  21.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
  22.   {
  23.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */
  24.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
  25.     {
  26.       /* 更新错误码 */
  27.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

  28.       return HAL_ERROR;
  29.     }

  30.     /* 检查Tx FIFO/Queue 是否满 */
  31.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
  32.     {
  33.        /* 更新错误码 */
  34.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;

  35.       return HAL_ERROR;
  36.     }
  37.     else
  38.     {
  39.       /* 获取Tx FIFO PutIndex */
  40.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);

  41.       /* 添加消息到Tx FIFO/Queue */
  42.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);

  43.       /* 激活相应的传输请求 */
  44.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);

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

  48.     /* 返回错误状态 */
  49.     return HAL_OK;
  50.   }
  51.   else
  52.   {
  53.      /* 更新错误码 */
  54.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;

  55.     return HAL_ERROR;
  56.   }
  57. }
复制代码

函数描述:

此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
使用举例:

  1. /*
  2. *********************************************************************************************************
  3. *        函 数 名: can1_SendPacket
  4. *        功能说明: 发送一包数据
  5. *        形    参:_DataBuf 数据缓冲区
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节
  7. *        返 回 值: 无
  8. *********************************************************************************************************
  9. */
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)
  11. {               
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};
  13.         
  14.         /* 配置发送参数 */
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */
  24.         
  25.     /* 添加数据到TX FIFO */
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
  27. }
复制代码

91.4.8 函数HAL_FDCAN_GetRxMessage
函数原型:

  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
  2. {
  3.   uint32_t *RxAddress;
  4.   uint8_t  *pData;
  5.   uint32_t ByteCounter;
  6.   uint32_t GetIndex = 0;
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;

  8.   if (state == HAL_FDCAN_STATE_BUSY)
  9.   {
  10.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
  11.     {
  12.       /* 检查Rx FIFO 0 分配了RAM空间  */
  13.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
  14.       {
  15.         /* 更新错误码*/
  16.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

  17.         return HAL_ERROR;
  18.       }

  19.       /* 检查Rx FIFO 0 非空 */
  20.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
  21.       {
  22.         /* 更新错误码*/
  23.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;

  24.         return HAL_ERROR;
  25.       }
  26.       else
  27.       {
  28.         /* 检查Rx FIFO 0 满且开了覆盖模式 */
  29.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
  30.         {
  31.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
  32.           {
  33.             /* 开启了覆盖模式,丢弃第1个数据 */
  34.             GetIndex = 1U;
  35.           }
  36.         }

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

  39.         /* 计算 Rx FIFO 0 element 地址  */
  40.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
  41.       }
  42.     }
  43.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
  44.     {
  45.        /* 检查Rx FIFO 1 分配了RAM空间  */
  46.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
  47.       {
  48.         /* 更新错误码 */
  49.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

  50.         return HAL_ERROR;
  51.       }

  52.       /* 检查 Rx FIFO 0 非空 */
  53.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
  54.       {
  55.        /* 更新错误码 */
  56.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;

  57.         return HAL_ERROR;
  58.       }
  59.       else
  60.       {
  61.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
  62.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)
  63.         {
  64.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
  65.           {
  66.             /* 开启了覆盖模式,丢弃第1个数据 */
  67.             GetIndex = 1U;
  68.           }
  69.         }

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

  72.         /* 计算 Rx FIFO 1 element 地址 */
  73.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
  74.       }
  75.     }
  76.     else /* Rx element 分配了专用 Rx buffer */
  77.     {
  78.       /* 检查选择的buffer分配了RAM空间 */
  79.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
  80.       {
  81.         /* 更新错误码 */
  82.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;

  83.         return HAL_ERROR;
  84.       }
  85.       else
  86.       {
  87.         /* 计算Rx buffer 地址 */
  88.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));
  89.       }
  90.     }

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

  93.     /* 接收Identifier */
  94.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
  95.     {
  96.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
  97.     }
  98.     else /* Extended ID element */
  99.     {
  100.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
  101.     }

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

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

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

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

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

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

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

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

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

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

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

  128.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
  129.     {
  130.       /* 确认Rx FIFO 0先进的数据已经读出 */
  131.       hfdcan->Instance->RXF0A = GetIndex;
  132.     }
  133.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
  134.     {
  135.      /* 确认Rx FIFO 1先进的数据已经读出 */
  136.       hfdcan->Instance->RXF1A = GetIndex;
  137.     }
  138.     else /* Rx element is assigned to a dedicated Rx buffer */
  139.     {
  140.       /* 清除当前Rx buffer的新数据标志 */
  141.       if (RxLocation < FDCAN_RX_BUFFER32)
  142.       {
  143.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
  144.       }
  145.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
  146.       {
  147.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
  148.       }
  149.     }

  150.     /* 返回状态 */
  151.     return HAL_OK;
  152.   }
  153.   else
  154.   {
  155.     /* 更新错误码 */
  156.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;

  157.     return HAL_ERROR;
  158.   }
  159. }
复制代码

函数描述:

此函数主要用于获取接收到的数据。

函数参数:

  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  第2个参数是读取位置,支持如下几种参数:
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */
  66. #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表示忙,正在使用中。
使用举例:

  1. /*
  2. *********************************************************************************************************
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback
  4. *        功能说明: CAN中断服务程序-回调函数
  5. *        形    参: hfdcan
  6. *        返 回 值: 无
  7. *********************************************************************************************************
  8. */
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
  10. {
  11.         if (hfdcan == &hfdcan1)
  12.         {
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
  14.                 {
  15.                         /* 从RX FIFO0读取数据 */
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);

  17.                         /* 激活Rx FIFO0 watermark notification */
  18.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
  19.                         
  20.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
  21.                         {
  22.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */
  23.                         }
  24.                 }
  25.         }
  26. }
复制代码

91.5 总结
本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。


收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版