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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示3 ~% Z, x( _' r. Z, M, @' J
  FDCAN基础知识点可以看第90章,已经进行了详细说明
% r; ?7 z* Q5 }: n  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接
3 [$ I, v" w6 V; J% h91.2 FDCAN基础知识
- G0 C6 f) y9 W' I0 |7 TFDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。2 Z  n4 Z7 g- x6 l

3 h! G. T/ o7 |6 A. D& x91.2.1 CAN FD协议介绍
& O; O  a8 v& SSTM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:
; _3 U7 T7 h4 J2 [' C& ~% X1 Z2 R! G' U; Z) f
(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
3 ?- _+ w) }+ `( ~5 {. `
, [- N5 _" A9 }# ~(2)可访问的10 KB RAM内存,最多可分配2560个字。. w9 i6 i4 ?+ h/ G, W5 o

) u- i" i0 x1 J(3)改进了接收过滤。( n3 z& m/ G5 ?& A! X, X, v

, o4 L9 \- l* Q(4)两个可配置的接收FIFO。; h3 B  \8 R' b" I% W$ m1 J
: p' b0 Z' W; h/ J
(5)多达64个专用接收缓冲区。
7 D' M7 p% C% o. o  J% I5 g5 x) i! v; H# x3 n( {) `
(6)接收高优先级消息时的单独信令。0 K* _# Y8 z6 U# [

! q& L9 p4 t. O2 H(7)多达32个专用发送缓冲区。
1 g9 K: E) R. E& S
: |4 ~4 Z. S* ]) V3 k(8)可配置的发送FIFO和发送队列。
1 _5 J$ w: O9 G/ K
: Y" R0 O) g$ F; b4 q8 M3 ]3 h(9)可配置的发送事件FIFO。
" A- y; ^. n8 n5 `- r* n! v! t" i; |8 w2 m; g+ o
(10)时钟校准单元。
; g" O/ R1 D- r) Z- z: y# W+ Q3 C4 p* g( P! \6 e* j$ j' K6 Y
(11)收发器延迟补偿。6 u7 u7 U) t& d. O% b. G: A2 N& ]

! i4 |: Q% q. o/ Y. N7 v( @' ^" C下图说明了FDCAN框图。! D  M3 R0 U9 [4 V

1 f, l4 {, @, h' h7 W5 P* ^
( o& r( T# g3 `9 _4 [
f4f1d5cd872648458911e8be8ddfffe0.png

0 }' G/ i2 e" u0 m) R* Q  ~' p. L/ y/ H7 f% N+ Q, D

  |- p; r; s( o% ]' i通过这个框图要了解到以下信息:
; I1 S+ k! Z, N# x9 d8 ^+ M4 C' c! Q$ q
(1)CANFD1和CANFD2共用一个RAM空间。" o  M$ A0 ^, i- R
2 b5 u/ L0 `; W' B8 z
(2)每个CANFD都有自己的内核。2 m$ U8 ^; L  d! ?+ {  |
: D9 }& ~, W+ A% |9 b. O9 d- E
(3)CAN内核实现协议控制和收发移位寄存器。
3 ?& I3 o% g, T5 V, k
$ ~2 P% s; b" n" V(4)Tx handler控制消息从CAN消息RAM到CAN内核。9 S9 ]3 r$ S3 Y* S& G0 F+ d
& C0 _+ e3 O+ y! P+ l7 m
(5)Rx handler控制CAN内核到CAN消息RAM。
; j0 W( x( v; \2 Q2 [  J' j( q" h3 h/ g1 _
91.2.2 CAN FD特性
& D! R' o1 O# l(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。
1 q/ r5 Q  M+ A  U/ _; ^* J. z& [  U7 f2 d' O
(2)提升错误检测,支持高达CRC 21位的校验和。$ \7 }5 k* B! ]" I: p
9 y, W0 \- c( K2 [: w
(3)消息优先级。7 U5 c$ V  p7 r. w' T

. V6 a' {9 U1 Z4 R/ G8 m(4)保证延迟时间。$ Y. \$ [$ q* g" C: j6 |) W  w

3 ?4 O3 p* o; T  ^* P  ?7 C1 }(5)配置灵活性。7 \/ R: ~) Y) b% x6 `# ^/ H5 u
& ^9 _3 B1 l* {3 O+ ?
(6)具有时间同步的组播接收。1 g+ Q9 _7 v# Y+ K6 f

6 k2 N1 ?& t$ M(7)系统范围内的数据一致性,每条消息最多64个字节。
, u) }8 m- k1 m( v, K
6 E) h: L% g4 Z) O  X6 J) f(8)多主机。
& `! D- C, H8 w' \8 d9 o
; L# L/ `# o& A9 s8 r(9)错误检测和信号。
% u4 R- x: k1 m; d/ x- o! e- z6 S; P9 P9 A! P, \/ q9 Z
(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。( x' l! y( c1 w( g. b

0 q1 u! }0 t6 g# p; q3 ]91.2.3 CAN FD格式6 G& x# S. r3 F( I

& ~% a' o) J  D& N$ A8 B2 b
c692adda5a1149b0a6e3d8a30745fd62.png
0 L% z/ c) d  F; ~  x

- V, o! `0 j) `, i. t' i( A
* H( C- J7 R" R8 T  T; m( S5 A第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:' Z8 [! ?, h: k$ j3 @% H
4 v5 J# w! v1 ]1 s, j9 R  }2 P7 V
(1)帧开始(SOF)。
$ r  z. S& Y! _. a2 T. r4 s% l/ A+ ^9 E# ~9 r* ~
(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。( B( L1 B% z2 B( I1 G. M- h7 A* F3 t

. c; [3 w9 x  y5 @) W数据传输阶段(The data transmission phase)包括:
8 Z# d6 W- K) S" c  K9 r: Z( K) P7 g& S* H2 e/ B6 M+ G
(1)数据长度代码(DLC),指示消息包含多少数据字节。
9 Y1 k7 |3 V# r5 c
1 t* U" L& R. E/ ^% Y* W(2)用户希望发送的数据。
$ s1 O3 j  _# X9 U% ?# N
6 H5 E6 ~! Z, u$ x7 {' m8 h(3)检查循环冗余序列(CRC)。
: C% R6 |6 \) _% K5 l0 x* ]/ I& C1 Q) [$ h+ |- |5 u
(4)显性位。
! Y9 }* [2 j) j4 C" h& s: Z$ }# o9 L: t( a" t7 Z
第二个仲裁阶段(The second arbitration phase)包含:
# q- @2 X9 `5 v2 O# |3 z4 G- l- q, ?1 U9 G9 M) A" A9 q! e' W5 S
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)
4 Z9 j. {8 S- F% d, a
5 m; I6 S7 e) u' N(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。7 {! M( g9 H1 H4 R- c( G' h
8 A3 N% L0 ^; V+ s5 x$ k1 H( K4 S
注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
, X! D, }' \; {! _: j, ]
+ v' }" K# r# N$ t7 ~91.2.4 CAN FD相比CAN2.0的提升
  E6 n) Q; i( Y2 h3 X! a* yCAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:
+ e* C- K* y$ [% n' G% ]0 p9 E/ S) m8 X- o" U4 n
(1)17级多项式对最大16字节的有效载荷进行CRC。0 {8 x1 p+ {- K2 K0 e
' o( [1 a/ Z; n/ a% |; E0 ^
(2)21级多项式对16到64字节之间的有效载荷进行校验。$ n0 e, ]2 `. u! H0 \2 M

8 V: P$ _8 ]8 G) U标准帧和CAN FD的区别:0 F! m1 D; X! k+ }2 M
4 S) i5 a, B+ ]

( y# s8 Z* J8 w0 f- o
050433e4b8fe4f4d91de7eb85d5e6bdd.png

* p0 |6 w) u- Y9 \6 p: O+ R1 N9 r( J& P# b: D* L

, n: E& @; L1 j# j标识符后,CAN 2.0和CAN-FD具有不同的作用:
. Q6 k# G1 E. G( T, c) L, j. J; n1 \/ b
(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。  U6 b! r. i" t0 t& D
$ v7 K$ J+ g: Y8 _( ]0 F+ c
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。
, E0 P% U3 M' A' e: n5 X; d1 _3 T9 s+ t/ m
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。( q( j" Q* t6 l* N3 v& |4 c& s

% M( v$ v, u9 D) Q与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:
- \0 d5 Q+ j9 D- M7 o, T; t. o: F. x  X- |# s) u* a. k! f
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。
+ O1 A7 [+ `1 d1 c
" F, k; V' F  M: W  M, C8 w(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
# K9 V! L5 {% p$ C
; z" z5 w, i+ ^/ W, E) A(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。% \4 }9 z3 K6 y7 j9 p
% C, _0 B: E' _. }& f. b, b
控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。% Z0 o9 s1 F! Y; V6 T

7 }2 s7 I6 C. \8 B9 c' b. S, d: C5 G+ T7 k* H8 S( d
c4fbc9fa3f184422a77784de5280382d.png

. V) z5 {5 @3 u0 s
( |7 [- y0 n2 r# l5 L) F, r( i
/ j( r/ t9 u) ]+ ^1 x通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
, p. C/ x- G  |  ~3 N: G& U2 E+ B( b
& V7 G3 ~6 |; Z' e0 T4 h' R(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。
9 \8 ]0 s8 P* i  j* p( f3 k8 u# |' W$ V3 i) A* T
(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。: b/ M& m9 u) Y; ~+ _
: }' W9 B1 j2 r% O8 J' j" b
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
5 u# z" e' s3 G, F' G0 ~
: L7 j2 V' K1 Y/ z8 y3 l. P- j& s0 q) y% K/ F: R, @( D0 U
a00dca8056bf40dc860b52366afa5197.png

: `4 X6 [1 v& S+ ^, ^7 k" |. m. _0 c" ~! J

' Q; t$ a; y3 r1 K  J91.3 FDCAN总线的HAL库用法# C! d3 j: O8 _$ ?
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef8 \( F, [/ e' G9 o) U' ]3 q
FD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
0 V: \; t. |8 x- g
" C( n2 d! @# L+ |5 H9 A8 z# q
  1. typedef struct
    8 X- e- n1 ]1 f0 k" c* n% s
  2. {( H2 _4 p) s2 {
  3.   __IO uint32_t CREL;   
    3 R) s. F8 F/ o- U, Z' {7 m
  4.   __IO uint32_t ENDN;        . c& F0 W) o% u% V! {4 o
  5.   __IO uint32_t RESERVED1;    2 h) z' s- t1 k+ ]8 x! i# G
  6.   __IO uint32_t DBTP;        + }4 S3 S; g  U! W1 C
  7.   __IO uint32_t TEST;        2 c7 e; x5 z6 s4 O  J! q. g
  8.   __IO uint32_t RWD;         
    4 k- p* ]6 `) \; ~* ?0 ?5 K" ?
  9.   __IO uint32_t CCCR;         
    6 I8 o  `- w& t7 v8 F
  10.   __IO uint32_t NBTP;         
    ) j$ R0 N5 t6 M" a7 @: C! w
  11.   __IO uint32_t TSCC;         
    3 `6 `8 y3 H" u' b) f# B# V2 {8 r/ P
  12.   __IO uint32_t TSCV;         1 t7 C7 e4 m. N5 _( ?/ u  s
  13.   __IO uint32_t TOCC;         + O3 _2 G) E9 H4 o5 O( F7 U
  14.   __IO uint32_t TOCV;         + ?% J+ J# E& P6 A" P) _
  15.   __IO uint32_t RESERVED2[4];+ B( n$ l- l: w$ }
  16.   __IO uint32_t ECR;          , f  r& z/ \8 T
  17.   __IO uint32_t PSR;         
      ^2 R* Q  ?+ |* J  ]& ^' ]0 K" ~
  18.   __IO uint32_t TDCR;         
    , z& U  |# J% h
  19.   __IO uint32_t RESERVED3;    * `& m8 M' w! ^2 S8 m
  20.   __IO uint32_t IR;           
    6 ~  e- E9 T5 g
  21.   __IO uint32_t IE;           
    " y" z" K+ f4 e, G8 }5 b* s
  22.   __IO uint32_t ILS;         # n4 _1 f6 W2 ~, O2 e' f
  23.   __IO uint32_t ILE;         2 O6 w8 Z( i8 E$ F' t1 \) G( x
  24.   __IO uint32_t RESERVED4[8];9 _2 d/ r- m7 z
  25.   __IO uint32_t GFC;          + Z+ J/ u8 F+ n9 q/ b: w
  26.   __IO uint32_t SIDFC;      
    ; w* F: w  ^8 I, E
  27.   __IO uint32_t XIDFC;      
    9 g  M& g' @; ?8 \& }: \) q
  28.   __IO uint32_t RESERVED5;   
    9 I# G1 M$ g# O5 T( m* F
  29.   __IO uint32_t XIDAM;      
    ) G0 v$ e; |. _
  30.   __IO uint32_t HPMS;        ; Q/ w4 I! M7 Y+ h$ N
  31.   __IO uint32_t NDAT1;       8 {+ [! ^1 W- M& T7 `5 C/ b$ `  h
  32.   __IO uint32_t NDAT2;       5 |4 B$ |. G4 a& b
  33.   __IO uint32_t RXF0C;        
    5 l: B6 P: V' `% r! O" Q
  34.   __IO uint32_t RXF0S;       ' _9 ?; P$ _) ]2 H. @8 e
  35.   __IO uint32_t RXF0A;      
    ; g" [: f+ }$ [
  36.   __IO uint32_t RXBC;       7 D/ u  I. I' l' z& N) O0 C5 T
  37.   __IO uint32_t RXF1C;      
    , W5 ]1 M, b2 c1 c
  38.   __IO uint32_t RXF1S;       9 u8 o4 b! W3 ~  D4 \1 P
  39.   __IO uint32_t RXF1A;       5 |; R* i5 F* W3 l. d- Q% T
  40.   __IO uint32_t RXESC;        
    ' X1 S6 c6 Y2 j# B- z7 _! D0 x, A
  41.   __IO uint32_t TXBC;         
    * O3 h& p! ?" @/ p- ?' M; x/ E4 w
  42.   __IO uint32_t TXFQS;        . F/ P% u: f0 v' i; Z" g! _
  43.   __IO uint32_t TXESC;        
    7 g1 n2 [9 y# ]4 [* d* c
  44.   __IO uint32_t TXBRP;        & W2 B# p: i. k/ n5 v. d
  45.   __IO uint32_t TXBAR;      
    - b5 o( e* {" t" [. c
  46.   __IO uint32_t TXBCR;        
    0 ?: m% `( L% ~
  47.   __IO uint32_t TXBTO;        $ n# t8 e2 o1 ~" W
  48.   __IO uint32_t TXBCF;       6 {! b3 ^" C( Q- Y6 D5 j4 D4 l$ _
  49.   __IO uint32_t TXBTIE;      
    1 g: O+ |/ i3 C7 B8 L8 n
  50.   __IO uint32_t TXBCIE;       : I2 a* D4 u$ w6 z; j1 [/ l0 Y
  51.   __IO uint32_t RESERVED6[2]; 5 z, \! O# g( }2 T
  52.   __IO uint32_t TXEFC;        
    & V! [) R# O8 T' Y. w
  53.   __IO uint32_t TXEFS;        ! G, U+ M. J0 |) l! }
  54.   __IO uint32_t TXEFA;        
    / |: B9 K6 ?( g
  55.   __IO uint32_t RESERVED7;   
    - Y9 g) l7 @/ i  }5 D- Q) S
  56. } FDCAN_GlobalTypeDef;
复制代码
: y" v& B3 D- c. S
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
+ I. W$ t3 j/ [5 c1 l) q2 ~( P8 ?3 a& P) c  N- V
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:$ A/ O; Z2 U8 U5 O! W# S5 d. f
1 b$ ]! C/ [6 g5 M( W# Q6 L
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    4 v6 @$ s5 T* ]  k4 Q
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
5 B# b) w* w! b" K3 s. h' e+ P
下面我们看下FDCAN的定义,在stm32h743xx.h文件。
7 k, y3 y; v" C" T$ E
4 Q+ o$ g; [/ U
  1. #define PERIPH_BASE           (0x40000000UL) ! `/ }( v4 u( t' b' _
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE
    * F5 F2 ^5 J" G0 m" _
  3. / c3 T8 U+ E$ g* P% v7 c
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)6 B  ~  J; W2 g# X4 n
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)2 p) w' A1 g3 \4 Q! _0 x& t
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)
    . C% B& o) x! m! Y' M* H
  7. ( T8 y1 n7 E2 p6 i
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A0009 ]9 v( \' L% I6 E1 a
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
    6 }8 K1 H( ?3 y/ E. X
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码
# ?  l6 H, d, g  u- N" {# u
我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。( o# u% b: V) L! Y& ~0 \# h- T
7 Q9 Y/ b# u2 ?  V6 X. E6 O- l/ A
91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef
8 Q8 F8 W2 X4 CFDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:! b+ o% \) |% m% }4 H0 c
4 p# u# T6 [, `0 f, H8 }
  1. typedef struct; T5 n% A1 G& o4 F
  2. {) y, r# R0 a4 F) i& W( B- D+ r2 F4 _
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */
    3 l$ b6 }; m. l1 A+ w
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */
    6 i0 k! C7 B0 @
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */$ I! d$ K2 |0 U5 \0 X3 W9 x* T
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */9 E% H+ Z. |9 Z% ]- u! O- j
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */7 e8 m- F5 `. q2 U) w0 ^; H( B
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */% n( y' F* ^# e' o7 y4 P& S5 p
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
    . v8 a9 l( C' y. X; B! g
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
    , @5 W! @0 R# K( H- L# C
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
    % p9 n* ~. n+ z+ w" y# s% N
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    . Q$ x% k7 O: \8 |4 Z
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */( `; o4 E0 }5 ?8 F. |3 |
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */6 h4 a( `2 k/ [" X
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */& r5 Q6 |+ D2 Q3 E" R. d  `
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */
    3 X1 a$ P6 w- j; C
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */- B6 m) \4 d2 [$ s( G3 T
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    ; P; s+ h1 B6 ^+ T, E& V" L
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */4 ?( t/ a3 O* [4 V5 R
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
    , X* V! }% U9 W2 f
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */' R# h% n3 H0 `6 I% S% W
  22. } TTCAN_TypeDef;
复制代码

9 z1 d6 h, F( G. v; D91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef: x1 ]3 {+ _9 D! `$ j
下面是FDCAN总线的初始化结构体:
0 k7 p+ V* q* r( y& P0 {
1 j6 Z/ L! n* Q1 d) H7 X9 W  S
  1. typedef struct
    & p; `9 T1 X1 c# [% `1 k9 h$ X+ q
  2. {
    $ C1 K3 P% e( x- U2 p
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.( k% h2 {- B: b  X# O* H
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     */4 h8 M+ W7 [8 d6 C

  5. 6 S6 z4 }$ B8 ^7 b
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.5 A; P* I% t5 r1 i9 R. Q  N
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */6 z. B1 X& M! A4 W4 P! ]
  8. 9 A  X( @) U1 f9 ]6 k' z$ D
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.# X5 M8 V5 A1 H& k
  10.                                               This parameter can be set to ENABLE or DISABLE               */
    * W( Y$ }0 F/ h) g
  11. + Y) W" ]% l! s! U- T) w* h6 X2 u
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.! h' W  y' u0 c9 p
  13.                                               This parameter can be set to ENABLE or DISABLE               */
    9 z( E. T5 L) P# a3 I

  14. * J4 e" c) d& R  |; e# O
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.$ F( N1 J5 F- W3 U
  16.                                               This parameter can be set to ENABLE or DISABLE               */, d1 ^9 v' l( F2 d  Z. x
  17. ; ^) M& L6 r# j. b7 q
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is
    6 g7 n; E) D$ O  d  L8 Q4 g0 i
  19.                                               divided for generating the nominal bit time quanta.
    ! R* p6 R! Q/ g0 w+ @# d' @3 L
  20.                                               This parameter must be a number between 1 and 512            */
    , D  [* A; P3 z! A8 x

  21. $ ]% A7 G0 W& p! M& B
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    , H- w' a8 X. ?; k" K2 f) F
  23.                                               hardware is allowed to lengthen or shorten a bit to perform
    ' d5 [( y/ C( \( C) T
  24.                                               resynchronization.# m' y# v# z/ H% `( Q' e
  25.                                               This parameter must be a number between 1 and 128            */
    8 V' L! n+ s+ _( ?. D8 H
  26. 8 n7 r- G" X7 h
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.9 Y8 L) H. V/ b: w% p1 |4 N* G7 _
  28.                                               This parameter must be a number between 2 and 256            */
    $ ]+ ]  n* E3 K/ Z6 J+ y
  29. , e) C& H4 s! n
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.! w+ y; n  w5 H8 V7 G6 }
  31.                                               This parameter must be a number between 2 and 128            */
    0 Y6 R2 V+ e; @9 `
  32. . ]3 s# f+ m# ^
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is2 K9 H0 }* I+ ?, y/ x
  34.                                               divided for generating the data bit time quanta.+ c# C8 `- _; K
  35.                                               This parameter must be a number between 1 and 32             */2 m4 \* V2 H+ F: g2 g3 w
  36. " A) ^& D( B/ _; h
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN% v0 F5 M9 B' O# Q$ R
  38.                                               hardware is allowed to lengthen or shorten a data bit to  F7 n  |7 w0 A' U5 w
  39.                                               perform resynchronization.
    . _3 h8 `) S; v7 k) a0 d' Z
  40.                                               This parameter must be a number between 1 and 16             */7 j9 M- p! l5 z! S+ z
  41. 1 z: B; i1 f/ s5 X8 Z
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.
    8 x" x3 O' T0 Y2 F+ Z/ _
  43.                                               This parameter must be a number between 1 and 32             */- }! B3 k# G* h
  44. + R' U# B! r6 }
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.* l8 u/ m" l1 d0 E% o+ p/ W$ u3 p* }
  46.                                               This parameter must be a number between 1 and 16             */
    - @' @- K% @# \3 T* K
  47. , k" B3 E3 z5 j" `5 N. ?1 Q  Y' m( K
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.
    8 P% a6 t( @, p3 \9 d
  49.                                               This parameter must be a number between 0 and 2560           */
    + D  ~  @# \+ z0 ^5 T
  50. - [+ A( {6 S8 F5 S' E
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters." V6 \; k8 E- M# j& P" W$ U) A
  52.                                               This parameter must be a number between 0 and 128            */. a1 f9 \! s0 p7 W/ s' _3 X

  53. / F1 {* K+ R9 V8 g1 H* {, u) y# ]
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.
    ' u, b; o- V7 f0 v' f! ^6 d# \
  55.                                               This parameter must be a number between 0 and 64             */
    ! d: c6 k, m6 T) |
  56. ' o; x( O; {( }6 v
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
    / z- D% C9 Q3 x, @
  58.                                               This parameter must be a number between 0 and 64             */- Z2 M# M3 R3 K" X% u; g! ^

  59. 8 ^! \) q2 q. c* \% W  w
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
    % Y/ P  ?% L( z$ M, ^
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    # k" p+ b( L9 ~9 D% v: h
  62. & F. t; Y3 E' R2 z) I7 ~
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
    + F# b; @- M7 U- d4 {
  64.                                               This parameter must be a number between 0 and 64             */: n* p" l* f$ t' Z! O. q
  65. + P- G! h/ w* W( x( m5 H
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.. l4 ~" |* M7 o, k1 R
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    ! m' }  p% A6 |, o" B1 w2 B* V2 @

  68. - q3 j* w4 h8 S) }: [( T2 Y1 @
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.
    , [! Y2 R% e% k# M3 D& q! L
  70.                                               This parameter must be a number between 0 and 64             */
    : R; D- L2 \3 y4 [' J0 u

  71. . Y+ q$ _. s7 W+ ^0 I+ O8 z
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.
    6 u( X8 Q( h( @9 ~4 h1 v
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    - s5 S4 L+ |3 u

  74. - r" u: p% D7 h# @0 ^5 q6 d$ ]
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.7 O4 C' L9 \4 M" B2 H
  76.                                               This parameter must be a number between 0 and 32             */
    0 W# n0 Q5 i. u( B9 p

  77. & v7 M2 A8 X0 Z# w& B& m
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.4 ?2 j( s# w/ f( ]; e/ F& Q0 K
  79.                                               This parameter must be a number between 0 and 32             */# Q0 ^) o5 A9 \" v

  80. ! s. h/ _0 q$ c' r  S3 L
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.- U/ J8 T1 u; T
  82.                                               This parameter must be a number between 0 and 32             */! g8 Z& S* s# c+ m  Z0 d
  83. 9 S* Q0 z, h4 C. T
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.
    0 q# {+ G& q  k+ U1 d
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
    1 l. ]6 r4 d2 a  X$ y( s# c

  86. ) f( _; `; F8 }' R2 f
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.3 s5 _$ B" I6 j& ]
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */! V5 m% y; |- D3 K" J  U
  89. ! K/ h/ z- ?- k1 t$ n0 |0 M! F+ g
  90. } FDCAN_InitTypeDef;
复制代码
( K+ C+ ?. \7 q# B
下面将结构体成员逐一做个说明:
* N3 X  ~! y0 o8 ~: w6 l- N7 |1 t+ E( s) c9 U' O8 e" k
  FrameFormat
, U' |! U4 P3 y用于设置CAN帧格式。' z) d: o/ ~5 L! j4 T$ D$ ^

7 ]3 J) l- j, M& _% ^
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */% E. l. C4 P9 [+ M, c. q0 \/ `
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */+ p& H' |# z' X' Y. t
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码
8 e6 H) ^! \, B7 e
  Mode
, \" K0 D8 C; Z0 T8 }- j用于设置CAN操作模式。
0 q& z& d7 x" z9 i; ?/ K' n2 h  M( L9 }5 D
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
    $ W, p( v* H2 D, |  W- j5 }  F
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */4 B* @9 z$ k# M: I8 d
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    3 b7 R: G8 x, P" Z+ ^. {
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */4 Q! g3 m8 c: s9 w& y  h4 C6 z& X5 S
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码

6 t# J* g2 x" ~* b6 c5 t2 r) C. T  G  AutoRetransmission
: ]7 A9 Y$ p) {9 [. b0 _使能自动重传模式。! b, I% T: n% @  O4 u, R2 @6 g

2 o& m; u  }( u$ {4 a# G/ i, I使能ENABLE或者禁止DISABLE。9 `8 U0 Q2 x2 P

' f; n# O& D3 L/ x. C& [  TransmitPause
1 e0 m0 v) N- W0 g使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。* j+ `& w- x8 m* g$ ^  A3 n
4 c. f7 O: |; B7 f$ D
  ProtocolException. l: S/ k% j6 T
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
8 n; p# \8 p& w; m
% q' {3 @- ~! Y9 U  NominalPrescaler
- P  Q: Y; K; f: s% F: ^用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。8 ~9 R: o0 h( F3 V7 Y( Q/ ^

! B4 p, v1 }' i: v  NominalSyncJumpWidth' P* D3 H! z0 i$ N9 D7 r
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。( J2 C! p' l2 p/ X: j
0 Q$ [, b4 g( Y
  NominalTimeSeg1
1 L( j' B/ ~. i9 D设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。. a! y6 c6 u# Z. r0 e0 N
! y. |5 u) V% I4 {7 P
  NominalTimeSeg2% C$ y+ o2 W0 p. d
设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。. T% d: @( \3 ?3 s# Z3 a1 Q+ m1 g
5 K$ s2 F. q. J+ w7 M9 v/ h2 ~7 Y) }
  DataPrescaler
3 t1 J. \/ C: o! p8 F# B用于CAN FD数据阶段分频设置,范围1-32。
0 f& z6 e* W5 c
% J3 G8 m( G5 @9 y4 K2 f  DataSyncJumpWidth& N$ t  T* V- `% Z* @" ]
设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。( {9 B$ g, Q/ w- {0 }8 j1 i
7 V/ B/ p% R% X* \
  DataTimeSeg1
( d9 L- ~+ E2 G, S4 a设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。! |+ ]/ J6 V: S9 c  u4 I

! x4 b/ ?: _' a+ C2 n  DataTimeSeg2( }! _+ _! G+ X( ]4 H- G
设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。
; L% E! [3 I4 p& c: t# g
5 A7 a/ k( _2 S# J( J  MessageRAMOffset% C# R/ U$ c- e( d
设置消息RAM起始地址,范围0到2560。9 m3 {  m+ Q6 k8 G$ @$ f3 {: s

5 w" S- y# q* a8 v7 A  StdFiltersNbr
6 ~. H8 |* ~. Q4 C) U标准ID过滤个数,范围0到128。
/ |; X7 F* s0 x; b3 X0 `
; e: E4 y: G: h$ O  ExtFiltersNbr
( }  O  T8 V5 H/ [. Y1 l1 _6 H扩展ID过滤个数,范围0到64。" u. ~' x% f# H

$ j; c. d  p1 y/ r- r" A# n; D  RxFifo0ElmtsNbr, j2 P( ^6 m# N$ Z! a: N  b, Q0 [& }
RX FIFO0元素个数,范围0到64。& b  |  V) u$ X5 r

' _- f4 C/ A' K. c$ o$ E: L  RxFifo0ElmtSize# O8 X# k8 X1 y- h
RX FIFO0每个元素中数据大小,支持参数如下:
# i7 D8 r8 |4 ?  }% U" N* n! q0 k! C8 ]: ~
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    # q% n4 I! l" Z0 V2 l
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */, H2 G# N9 {  H, E' M+ M
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    3 h/ I: S; r7 m. i- ]+ h
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */  w$ i# h4 v% s% E# [' l1 _) C
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    1 ]$ R1 u) F5 m' b( d
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    6 \: P: |1 `2 K( w4 c9 l
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */- L- O, w( T4 Y4 D( M9 P3 F) i
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

" Q. ?/ y# O2 G% p) |  ?  RxFifo1ElmtsNbr. i; ?2 Z+ c9 t. V' I' e: D
RX FIFO1个数,范围0到64。  H7 j$ _4 n/ u2 i8 U6 m+ F1 L

* Y8 {' I2 J0 s! h6 f3 l; e- S& a  RxFifo1ElmtSize
$ G" q$ ]) w3 ]' y% f% B! w5 ZRX FIFO1每个元素中数据大小,支持参数如下:
7 z* t$ i  @' q2 y. ~3 Z5 ^6 [* R0 k  n4 y! Y6 _
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    " q# O* ^3 H1 l
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */) D9 H5 L3 a0 Q7 c/ T
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */: G8 n# r7 x9 R1 h# a* k: p
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */1 g$ }3 ]3 u  K5 S8 Z1 q- d5 s
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    ) j3 E. I0 V! i! O
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */; N6 [( w, S0 l" \! K9 d, o& g
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    3 b) \7 K( L* e/ i( |  [( w. ]( r9 I
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
. X7 t1 T8 G" ~* X
  RxBuffersNbr
8 ~, [8 X5 I- E5 Z3 U设置Rx Buffer元素个数,范围0 - 64:1 O/ _! C2 {, a$ N; w* ^
  c: I1 Z% O: i
  RxBuffersSize
* y% d7 ?* N) R设置Rx Buffer元素中每个数据大小,范围0 - 64:
% ]+ b* r& H* K, t9 u' A7 g9 ?4 I) K2 U8 ^, _# s( P, K
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */) e/ f- ~  r1 V; {  M
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    7 I; z9 G% y$ g, E8 [6 q8 J
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    ) @4 Y8 t9 d) v9 V) f7 D5 {5 _+ b
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    * ~: h) {& {; W7 o
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
      h, u$ A  a3 V5 z
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    $ m* A' H; l# q9 [& P' H$ \: G* _
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    0 B! G/ E4 D0 ?# F2 `: V1 @4 I
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
3 R+ o! F6 i, O2 t0 W* Z7 l6 R
  TxEventsNbr6 D4 a" o" l4 H) w8 ^7 `& R  h' i
Tx Event FIFO元素个数,范围0到32。( l9 I* O0 {1 Q6 a# a

9 W! r, D; a6 Y! y7 A7 O  A  TxBuffersNbr6 L- p2 f# K1 a# E0 k' D
设置专用的Tx Buffer元素个数,范围0到32。5 z5 ^/ \& C: q

* L6 r/ e% e! ~: E! U3 B6 q  TxFifoQueueElmtsNbr( H' S# L3 p, t
设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。
7 C  O: A: R1 J4 U4 q- f5 \$ P& t. o; Q4 [# ^
  TxFifoQueueMode
' z: @! x* `" v) V5 G设置FIFO模式或者QUEUE队列模式。. m1 T) Q% W2 P$ x: a6 L
* f9 ?' m' b6 `0 }* g5 j5 A- h9 Q3 ?% l
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
    2 q  f- d, y) N$ F1 `# j; @, u( s
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码

3 t& U' f% t, t" ~& H+ t- n0 U  TxElmtSize. e, H. v; j! @% X$ E5 N
设置Tx Element中的数据域大小。支持参数如下:: ?- _7 e' n0 O  n5 d- O' z. x
3 w4 z9 E+ ~/ u
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */0 J. Z& J4 i- ~* ?
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field *// E2 ~/ R9 l; i2 G
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */& }& S3 b0 l! v# d
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */2 E: z' r8 ]7 x
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    ; d- j2 e; k/ P2 I- w+ _
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    0 T* ?6 u/ ~$ H$ p9 f, j
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    5 D7 E) ]  _  m4 o# L9 M! }
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
0 T4 x! l- X1 t' _
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
) d6 R8 h" r6 Y3 G9 t下面是消息RAM结构体:. k9 \! |2 x+ |; P) k
  1. 4 r2 P7 b) w5 N/ L1 x# q# I
  2. typedef struct3 Y" Y# ^8 s6 Y' A; d  }  z, K
  3. {& a9 n: W; @9 N$ x3 q) u
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
    . m7 h8 M7 K1 p7 g1 B7 e$ w0 w
  5.                                   This parameter must be a 32-bit word address      */
    / k  P6 Z7 w) g2 z8 q
  6. . B; n3 d: O* R* ~9 X
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.9 t5 x. _! ~0 C( T' f- T0 m
  8.                                   This parameter must be a 32-bit word address      */$ o' y! i8 l5 g- H8 j+ M; g/ t0 V

  9. ) P6 U- B6 j) r* O' Q
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.; ?0 c  L" t& P% D5 [% o, A
  11.                                   This parameter must be a 32-bit word address      */
    7 o4 B/ K6 ?& I- K: Q7 N

  12. / |5 I4 j6 v  ~) C- Q4 f! }: V
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.
    1 y* z6 ]7 R7 w  ~
  14.                                   This parameter must be a 32-bit word address      */# q2 L0 O6 Z  \. H! m* z
  15. . |0 I8 Z# F- o$ Z; f: S
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.
    7 w! x" `0 `, l* g! n0 j
  17.                                   This parameter must be a 32-bit word address      */0 F, P& q2 \! v# J& O
  18. $ x2 M1 U- a/ G5 H  F; o
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.
    1 o! ]* {0 ~" C% e4 ^. p
  20.                                   This parameter must be a 32-bit word address      */0 ^; g4 C1 F: s0 M& }( n% w

  21. ( v( j2 K4 D6 P' E6 V; Y8 E; t
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.
    ; N/ F' Q5 k7 ^2 H" U) L3 @
  23.                                   This parameter must be a 32-bit word address      */2 \, D  N/ v) K9 ^- `+ w. @

  24. * Y) \  Z% V1 b
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.: X: V; H) N: x% K0 g
  26.                                   This parameter must be a 32-bit word address      */
    5 s7 E% X/ ?& l% n  h' _$ ~' a' \
  27. . M7 x) Q1 s6 L
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.
    2 ?$ j) a. C" W7 X' q
  29.                                   This parameter must be a 32-bit word address      */
    ; c% v$ c4 _0 m" F% |5 n3 b

  30. ! s* A' v1 j; `  P9 y
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.
    % O' K! l' _2 y0 ~) n) ]
  32.                                   This parameter must be a 32-bit word address      */
    : x, P. T6 z7 s8 `6 a

  33. 6 Z7 z+ d4 Q4 ]! i- j) H
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码
' I8 O* O; h& c
下面将结构体成员逐一做个说明:! d. V3 e" o+ v/ f

( H5 h* C" f' [' G/ k0 ]  StandardFilterSA1 _( v! L8 @3 f" \7 |
设置标准过滤器起始地址,必须是32bit地址。$ N" w6 X6 I+ f6 l0 ~9 ?; k, b* e3 M0 x

1 s. E* X4 ^7 {/ ]$ [  ExtendedFilterSA9 {# F( T3 Q$ T& I; E
设置扩展过滤器起始地址,必须是32bit地址。$ Q& Q+ z/ s3 }% h% l7 U
( m' F3 y8 ]5 @' m! J
  RxFIFO0SA
) a: s6 q/ `9 g/ R7 J7 t设置RX FIFO 0起始地址,必须是32bit地址。  [4 ], Y/ m. L1 W. g* {0 L

% W, E/ F* Z) q3 q; r, g  RxFIFO1SA  N3 s, H, j3 |/ J+ q1 a: e
设置RX FIFO 1起始地址,必须是32bit地址。/ }0 G; l3 `* P6 l7 d+ J5 s& Y
' a  A4 B1 \( q) q) H$ G3 z
  RxBufferSA/ D9 V- [8 k" X* d9 f0 a
设置RX Buffer起始地址,必须是32bit地址。. q% J- W) s; I( _  i$ H# c! n
, l1 I) F: Q/ i4 m, a, j" x
  TxEventFIFOSA
/ D9 }+ [- Y# Z0 U. _% X  U+ B' T设置Tx Event FIFO起始地址,必须是32bit地址。: @$ n& k+ l; w: j2 z- F& J# z

. x7 T& a  v0 ~/ W  A% `" B$ h# e& x6 @  TTMemorySA
5 D4 c* [8 c% y! V( c设置触发内存起始地址,必须是32bit地址。% N' r# _+ |0 n1 e6 W
! L# A. h6 ]( \' V
  EndAddress
  i1 g- P( O5 r; I设置申请RAM空间的结束地址,必须是32bit地址。
) J( `8 D8 ~  s& w) N
% z8 c  Z0 |3 L4 |% c& s/ X) I( j91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef3 f. u3 J, V! m4 l0 r# P
下面是过滤结构体:2 {  |: i  C5 n! M/ G' P1 v
3 O+ }1 n; ?3 w/ _, X* J$ L9 L
  1. typedef struct" N9 h1 ]1 c" d, i8 y
  2. {
    . M3 ~7 S8 i, b' @  @! K, U. Q
  3.   uint32_t IdType;           /*!< Specifies the identifier type.1 f6 v# H  U# p& D) n, C9 S
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */" n$ n6 u- A$ x  d4 L2 f6 a
  5. $ _5 A( Z) H+ J/ G' w( u3 l
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.
    & h9 e4 H& `; J/ M8 y. s
  7.                                   This parameter must be a number between:+ x: D# l/ \" t4 n
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID
    3 V3 P+ Q1 y/ J# W) w! R
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */* A# Y% p9 N1 u0 R* i2 E
  10. / x9 b( l5 Q: |- N5 \( H
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
      x: Y9 h# p8 B8 I" K
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.4 e7 ?0 H1 E, I5 T( G) R
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted1 {) i  N. F0 K5 g- l+ G
  14.                                   only when IdType is FDCAN_EXTENDED_ID.0 b3 |7 Z# p( |2 f' N. G! y
  15.                                   This parameter is ignored if FilterConfig is set to
    - p6 h3 f. J) L
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */
    9 }5 G& b% o. h

  17. 5 {9 [6 W, i2 K* B1 o" I
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.: x0 m( J( T* h/ A% J! A5 N0 ~
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */+ O& x& z: {9 s9 Y3 V) C! O# A4 M
  20. % Q& B/ N9 l( @* M' k" j% A4 [
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.
    8 Q, ]* p0 p: v3 I9 F% _2 r
  22.                                   This parameter must be a number between:- B5 K6 H( x- ]# N4 P
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID) ?5 m) Q0 [/ `, A+ N
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */0 u! z) e$ Y9 F# A7 e
  25. & j7 W  g% T$ f  I0 t: V" `
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.) C( t9 t  u" T2 i: m. @
  27.                                   This parameter is ignored if FilterConfig is set to
    1 n1 x7 n: a6 D( O& y
  28.                                   FDCAN_FILTER_TO_RXBUFFER.
    3 B2 |7 m7 U6 f2 C0 p& B& U& C" e, s
  29.                                   This parameter must be a number between:* Y" b6 f) q/ Q6 }/ u- ?/ l( `8 t
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID/ J5 A# C7 G6 q5 r! \  D
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    * d. f/ Z+ e% U# Q" p

  32. * i  P. ^) h. J* h5 ^
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
    6 h" x/ q2 L" W3 A, q5 o. D
  34.                                   matching message will be stored.
    3 U( _( S/ ]. |
  35.                                   This parameter must be a number between 0 and 63./ e5 c  O/ b- U
  36.                                   This parameter is ignored if FilterConfig is different
    $ u" y) R. {7 Y; M# |
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */
    " F7 ~: U- u) V% J% u$ S/ B

  38. 4 L" |& W1 ~: `6 M* F. y& a
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for3 K) T7 S% l; L  A5 i- A% h3 n' v
  40.                                   calibration messages.
    * _- H2 {9 f5 Q) d1 J3 R
  41.                                   This parameter is ignored if FilterConfig is different  d7 u9 f# c3 A. L( E4 d6 J$ b
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.# J/ y& r3 ]  \7 i- e
  43.                                   This parameter can be:9 H! W8 h  o6 J6 [, i/ ~* e) i# x
  44.                                    - 0 : ordinary message
    3 P: o3 w3 C3 L" [9 W  {/ }
  45.                                    - 1 : calibration message                                */
    : I: Q8 H2 T% Q/ Q9 X; j% B+ y& }

  46. 9 G2 ?: u2 {3 ~% M( ^' {2 u9 Q
  47. } FDCAN_FilterTypeDef;
复制代码

% y) Q% b% N' N. r' l  IdType; g+ r3 T5 g# c1 Q+ C- h  l
用于设置标准ID和扩展ID。
( X' O0 A, N3 B5 ~& s
0 l, l0 P& t  k! {; P) M
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */( F4 z9 [9 Q, F; ~, c3 Y
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
3 `) V- y) e- y0 }9 u0 _5 Y, c
  FilterIndex2 e" `0 ~" G; m, q- c  }
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。
, E7 `; T1 e0 _8 j2 h; U: e
5 o3 l' o, a' M) \  FilterType  `& p: L8 F( A
用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。' v. t( A8 u8 O2 Q
8 O! y( ?3 k8 d; F& H  d
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */- v& f  R8 W5 J. K8 n
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */
    2 [4 S5 d. x  ^- W, U8 j7 [% ^

  3. + L* s" u, ]% P- d
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */  R3 Y/ Z) A* C! {( ?: {( I
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)
    , m+ D; ^' [1 U* b% J1 R
  6. 6 [7 [* P3 j3 q4 u9 m
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */# ~+ H4 U  V4 _0 W, Y4 k. u; v8 B
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码
5 y9 c3 h2 {9 d
  FilterConfig
( i) ^6 P! s6 ~$ ^- _/ L用于设置过滤类型。
1 V  _" |; y4 \: z$ `# J; J6 q
, v6 x3 j1 h3 v5 J' \
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤
    * O1 M1 ?* Z/ N
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    " E7 ~+ T. t* s2 K* j. g, s6 B
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1
    8 c1 Y0 U' P& a9 K: x- y6 _/ [: l' A
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID
    1 t1 E+ s5 a/ y: `3 W; ~" {) p% h
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级, x2 J2 W) P4 S4 g
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
    : X& T! @7 K5 q6 e( Z1 N
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1& p( U& R; F; Y& J
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码
! j& {' z3 _! `( L8 Q: |( d6 R5 w
配置
% Y4 I- m3 W2 O, }7 d  FilterID1
( ~7 l  o7 J* s/ q& z用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。( c4 I% e9 b1 M8 f9 b7 H1 [

& `2 L" X# _  G4 t/ a/ ^+ x  FilterID2
  ~" Y/ l5 P- e3 K! [用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。4 ?) v- t# V7 K4 M

: K) z* n% V' o8 t  RxBufferIndex
1 c8 k/ ^( ~/ j匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。0 ~, E1 ^! Y  G* L1 k$ w0 H+ _
- I* D  s: b" T% X5 L( y" m" |
  IsCalibrationMsg
1 n1 @7 z& S" |' \) l* [) @用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
+ z  C  Q5 ?/ V6 l  |) e1 w6 G+ \+ B. h
0 : 表示正常消息。
) `- E/ g3 J' e9 l* V' O7 D( N7 e! J# A& q; |
1 : 标志校准消息。
' I7 r& X6 X# h+ F: p9 S- e1 b6 @3 v3 [* }
91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
$ d# I, m; T4 {! u/ `下面是CAN FD发送消息结构体:
% N) ?! u& q) J( x/ Q
+ p* v5 z1 V: X8 ?) K
  1. typedef struct5 q! n& t' x6 k/ x: \1 M, J( _6 I
  2. {4 H3 X) G. J2 q+ i; E" Q
  3.   uint32_t Identifier;          /*!< Specifies the identifier.1 s- Z' C" r% r: W- T7 Z. A
  4.                                      This parameter must be a number between:: C2 P. e! C5 c) u
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID# j- b! x( [( v, n
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    ( W+ b  w3 F  u# \: ]/ Q- G
  7. ' o9 [, |2 T" l& C# H
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be
    4 K* W& s% ^7 T  W& O3 c
  9.                                      transmitted.9 S' @$ F& c: x- f
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */
    - h$ }) e8 W' I6 c

  11. 5 \5 Y2 }8 J9 |2 h5 T. N
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.% l3 g2 L# S" V
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
    2 `3 E5 m( E/ ^! n1 ^
  14. * B2 G8 B9 w  o# _
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
    $ ]/ f8 X4 O8 q$ X
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */4 S  s) a- q3 \$ u
  17. # x9 R1 @) K" R
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.  r( K+ N5 G1 S) g- K: ?" u1 n
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */# K( @6 c7 U1 L# l$ a+ g

  20. 8 c2 ^% V# G0 l3 p  O
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
    & s) ?2 a# [- Q2 H7 ]
  22.                                      bit rate switching.
    ) [0 h, y" G* v! _+ ^3 Z
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    : ~2 {' i9 W. I. _  }% u7 s9 x- y
  24. # @( }% D' U+ b8 q9 I8 V4 o
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or  g: i2 B! o; {% {" _7 D
  26.                                      FD format.
    % j# K6 X$ D7 D  B3 {
  27.                                      This parameter can be a value of @ref FDCAN_format                */
      p7 z5 a; u9 d0 x' x7 X  l
  28. . B' }: G$ H% H' B
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.- P* I- N3 ?" ]
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */
    " w* K! |/ @! M0 [+ r# ~

  31. 8 j) P+ q) h! @% i( j/ }
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO0 A# a+ D/ a  w1 |7 r
  33.                                      element for identification of Tx message status.8 h. X" k) ~/ H4 j2 j* h+ ~
  34.                                      This parameter must be a number between 0 and 0xFF                */
    : s2 f$ ?7 x4 T2 E% W" v# `- I
  35. * ~; P. b/ Q; H5 H1 [7 n
  36. } FDCAN_TxHeaderTypeDef;
复制代码

) D3 C. E, {% M( @9 T. N  Identifier  b; A  d  }( r+ C
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
5 \, N, Y0 J1 v& v( I6 F9 U/ g' Q7 A, I
  IdType
3 w9 _7 t+ @$ P# B+ L7 ^用于设置标准ID或者扩展ID。; ^7 r+ f  j, q6 f! |) [* \. ?

# q7 G1 O" C. L1 x$ y$ G7 j
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    $ |7 d; `0 }6 j& L- I  D2 P7 S1 b. S
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
% C5 H( k! f  R- G& r
  TxFrameType- D  J# l' L- W; U( E0 n
用于设置帧类型,数据帧或遥控帧。
0 H$ h' t/ M, k' a# l$ Z9 A3 d
# j; ]- \4 x! G6 w
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    . j( B& m% s/ b- d5 a7 Y4 J
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

9 y3 `. b3 _* P$ E1 y% K0 F  DataLength; }. k5 j% K* E6 b
用于设置数据长度。4 u; o( T, Z  c$ _2 o( C  h7 |

8 s* A" U2 [* [/ n1 J2 H/ `
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */* r- A( ]2 d, z$ g
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    5 J- E( R  `" a" n
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    0 n6 _2 r+ I7 H% J. d. V( g
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */1 j- T& G% j) V- R1 ~+ `. |* Y: N" D
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */1 }. c  c3 N+ z1 v
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */) d8 o* }/ h$ l1 T8 X1 I
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */5 C: e+ Q5 p# t, w
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */- L+ V& S0 l+ H
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    6 W& X" ~0 b7 |0 d* o
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    9 d' M2 [) P  o; B
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */- |$ b1 S  J1 D1 e: K
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */3 H* q' I$ B8 R2 I8 ~
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */$ \7 [% ]. T; ^+ @' ?5 `
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */0 J: S- c9 l' K6 S0 R
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */0 I& r5 l5 S3 c* @0 I) ~" N1 }8 @) G
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码
3 x  A6 n" v3 Y
  ErrorStateIndicator- @$ q7 \3 {4 v# S7 r  K0 P5 p
用于设置错误状态指示:% s2 A/ O, K. Y

$ `; d8 W! Q7 X$ b. K' }+ G
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */
    ' Q0 t' M# S# u' t2 I
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
( M" s9 N( O  A* D
  BitRateSwitch1 P3 O/ H' a2 L6 i
用于设置发送是否波特率可变。
2 _4 E- a8 I& o' A
1 ]& j6 q3 R% x& f
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
    ; a9 ]" L. h9 F+ o2 C
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码
6 y$ D, S" K: v& j0 D' T
  FDFormat
4 x4 A9 o- ?  Q- \: Z用于设置发送帧是经典格式还是CANFD格式。
; }) q! }! t5 u( K: x- p
  1. : O* n2 O6 k/ r5 n0 N! q
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
    ; x8 B* ~0 @6 |' h3 P2 Z7 ~4 R1 o
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码

" j; [7 L) ~0 L7 m) h  TxEventFifoControl* Z" Z  c3 I9 f) y
用于设置发送事件FIFO控制。
' q0 Q" l4 k. v/ s6 Y
3 x/ H. D1 T0 e) w/ u% P5 M/ A
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
    9 \9 y! O5 B$ G0 S$ ?  Y" }2 e
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码
+ j3 Y8 I6 k4 x4 S
  MessageMarker* Z: \8 a! L4 s1 \) `
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。4 a: `$ ]1 k1 F

: m/ E) D" b# [6 L3 _* e: @91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef% u8 H* E6 U7 M: l* f# q; u7 r0 X
下面是CAN FD接收消息结构体:
2 }2 _3 ~( M  Z( @8 d0 \; P% ]; |4 C2 h' w' B+ W
  1. typedef struct
    & w, Z* t% C; F$ _7 ?3 r( ]: v
  2. {  G" P* [! H# k9 d; E  R
  3.   uint32_t Identifier;            /*!< Specifies the identifier.7 d& g4 }* i3 y2 m* f
  4.                                        This parameter must be a number between:0 H1 f  n/ `! \1 i2 D6 G
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    ( r% f0 r1 U4 A( e  a( Y+ C/ [
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    ( n# k0 J/ T* Z$ n
  7. - N$ _& b2 q' l4 l) ]' k" u! w: ~
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.+ G- N7 e. X8 y2 S* P
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */7 k; F# @$ c' i

  10. 5 v( @% o6 D. V6 s
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.) i( ?6 f1 D. Y8 l) H
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */
    1 {" p8 k9 C- N

  13. 5 M; H+ c' H) s5 E1 x2 t- o: d
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.
    ; T; F4 u! }" P0 k8 n: }- x7 T
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */
    . }# N3 E0 A4 d; L) }% l" G& E
  16. 0 |0 }! k0 ?+ u$ S9 A0 G
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.; y8 K* J2 F+ l! t
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */
    2 z8 \3 ?, Z, [& o: [% _3 N
  19. 4 r- D! F4 ]$ t  M
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit
    # ^  F3 s2 ?8 w
  21.                                        rate switching.
    0 G% |# Z! _$ ?. O/ B
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */+ _* c6 W0 U4 [$ m! k1 @6 @* j
  23. ! X+ ]& n! {, N& g3 Z* a) k3 N
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD8 z5 J- V8 M/ y  R5 w( \& M: c$ D
  25.                                        format.8 s6 h' `4 B1 [: {/ F4 F1 P2 Y0 D
  26.                                        This parameter can be a value of @ref FDCAN_format                */
    ( {( z3 i  E# i$ X8 E

  27. / P& H2 n) W2 |1 @" {0 r
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame; p  Q/ Q9 g; k) H
  29.                                        reception.
    " }2 Z. T+ O5 U& w: X, k
  30.                                        This parameter must be a number between 0 and 0xFFFF              */5 g! n1 E# e6 n4 _# g5 H6 x
  31. 3 q3 D2 `4 B7 i
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.
    + }, u1 K2 e0 y0 |
  33.                                        This parameter must be a number between:% T/ d# r3 [1 ~
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID& {; u$ @5 W( M9 f2 i
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */% \9 t+ ?& y2 R& D, b1 D
  36. $ s. [1 m3 ^0 Y3 U9 w0 e* M" c* ~, d
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.# A. r+ Y) u, f, Y% v. c7 x) G
  38.                                          Acceptance of non-matching frames may be enabled via
    1 a0 P  q7 C+ B$ N% g
  39.                                          HAL_FDCAN_ConfigGlobalFilter().
    ; `$ ?, r( z/ g5 Z% M
  40.                                          This parameter can be 0 or 1                                    */
    2 ]8 h+ z$ U8 h
  41. 1 h+ r" W1 n6 a
  42. } FDCAN_RxHeaderTypeDef;
复制代码

$ w# l7 P2 d9 X+ J$ O; m6 K! ?  Identifier
. Q; L: e! G5 B" s: o; m3 n) f用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
- s( w" X, Q/ q. v, {( h
, }" A3 F; K, a+ V5 H+ ?  IdType
' u/ |" S8 p+ s8 o& ]' a用于设置标志ID或者扩展ID。
6 \- u; v. L4 \: R3 l9 b6 `
' C+ w) p5 r5 Z6 [$ j5 t% Z
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    4 ^. I3 h& ~5 C
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

! v& V. h7 J4 m3 T4 D5 P% u: u/ Z( c7 J  RxFrameType
- q) H5 o% S8 C' z$ \, c; A用于设置接收帧类型,数据帧或遥控帧' X3 s. U7 I, M4 T1 p5 q

$ g( `3 {6 y0 F  r5 j
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    + I$ N- V7 e" H+ J
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码
: `% u2 C% i3 P
  DataLength
8 ?; Z0 J# x, d2 g! ]$ v用于设置数据长度。+ _( a- L' ~' M$ |& H
# g0 Q( v( g2 H1 i2 h0 v% V
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */# F) `# _3 `2 |4 [5 A' E  M. |
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    7 O1 H/ q. r4 ]6 g( H1 ^
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    5 ?+ _" H3 E' \0 M& C$ \% |& g. O
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */9 o; ^6 _# c2 S
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    ; A, {* `0 n4 x" n6 D
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    6 \9 ~# T: _* x0 ]
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */3 i0 `- R* W/ r. ^- ^5 U& W
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  *// v. h0 B8 k# i4 Z# L2 Z, w, S
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    + z9 [! {5 t! |' c& {6 `9 a
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */4 K. [9 I* z, |6 i+ I$ K
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */! @5 U- @& ?) C7 r0 r0 k* E
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */: S' u$ X+ ~  m# R
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */+ N6 i  @! o4 V
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    ) j  e/ _( J' D  g9 u
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */. T' [, d6 O7 p" [' a$ X
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
    5 Q5 K0 H. ^( `7 l5 E
  17.   ErrorStateIndicator
复制代码
  \$ E7 Y  p. x$ J
用于设置错误状态指示:% t/ [9 L' ~+ P0 z; }6 z2 r
* }) V. q0 i( x9 ]
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */( _4 \/ G* }/ X( y. O  s
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

0 O: X% I$ M7 y" i* f$ {# g  BitRateSwitch2 x, n8 B# U" [  B- L! f
用于设置接收是否带波特率切换
3 K; N# C6 k2 j9 i# S( m& \  K: o* Y
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
    + w2 \# ?8 X2 d! J+ Z/ z0 F0 K
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

( `( b  {' ^+ T2 G, e  FDFormat
/ W6 p* s9 |, P5 i5 F用于设置接收帧是经典格式还是CANFD格式
  \& P: F' m* \7 E- }* R- W
- a2 U5 x& S( J& U' y/ q
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */% g  ]6 S) Q8 D9 R4 W5 |1 H6 l7 @
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码
$ W* c( V9 n# N# I% P- M; {& E/ H( m' W1 s
  RxTimestamp
5 N0 v( t( L( Q8 [# L2 E用于设置帧接收时间戳,范围0到0xFFFF。   
6 v$ n+ X0 W4 m' [" X: F
" G5 z" z/ C5 r/ \0 g9 t8 Z  FilterIndex
7 S% X; |% K/ U5 h! W( w! m5 f用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。
; k: A  R; u! n2 H. I  b" T& J7 H! _
8 _3 ?* E, m! a4 p6 i, p  IsFilterMatchingFrame: _, \; ^: }+ P/ d* i; [
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。4 ~) X  l2 y+ e3 z* ~+ N
- a. x+ s- T$ P7 b3 h% u
0:表示不接受。5 E. ^# c8 g' i: d# Z# N8 O7 |6 `( I' B/ g% _

& C4 V$ N& ~) n; q6 M, C' M% n6 U5 t1:表示接收。; T$ f: r9 t' T* c
! p2 L1 o7 u- F4 @
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef
& P) Q2 v6 R$ U9 D) i9 i. u& L下面是CANFD句柄结构体:- a) p, C8 Q% p# d( L+ |

1 Z$ J- G& q; d9 y) ?) |' D
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    & k9 x% }2 Y/ @1 R: @
  2. typedef struct __FDCAN_HandleTypeDef. i% ]& d; `. A4 e/ e, h
  3. #else
    ( V2 w- y( ~' M% {- d
  4. typedef struct! {1 k" g4 r& e/ ?
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    6 p  K- Q6 ~$ Q$ r
  6. {
    - Y% n5 d: Y3 D
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */$ c" l3 X: a  ?$ v2 w
  8. " A/ V0 h. J* M, _* q7 _( F" g2 f
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */( v& e" ^2 Z8 d2 e
  10. - j6 B& F; ]3 A. r, q: }
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */
    7 {. t7 X/ y  A/ y5 x6 o6 `, }5 x) `
  12. ( _3 o# i3 V, \$ m/ L1 C5 k
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */# @% d( R# o" }. F: E3 G) p

  14. % Y9 D+ A. p4 ?8 L/ G& k
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index8 k2 h/ m- S6 \- I! _. {: F
  16.                                                of latest Tx FIFO/Queue request */
    7 E( r' e* {. O
  17. 8 ~. A' x: y: T5 e. c( @. S
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */
    9 A3 S( H$ b4 u; T0 ]% x3 g" |# _
  19. , j# s  |2 }( }0 E# P
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */
    ! Z' `4 H" R6 _3 g7 M
  21. ; o. k; H+ g6 M4 o% p: o+ T+ Q& _* i
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */9 a$ K) b; _2 a1 o" m
  23. # P9 u7 L& B; Y2 P  z8 b' W2 w
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 14 {% T- m3 {  b; K
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */5 s& |$ J; V- ~" [- W  D
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */
    ! ^- P' _& e9 |) [
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */1 }( V# ^( b1 D: C
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */: ^0 z' Z9 v" m4 s0 L
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */9 D/ f3 f% ~4 ?$ J& c
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */' z$ t* U) k% f* a/ A& n1 B
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */
    % P# f: {# i6 b( b( R* i
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */
    + f7 n4 M% b* `* [( F
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */, L1 F& c, ^: p0 s1 K+ z/ W' ^
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
    / ^. G% f5 n& C6 e; J/ k% \' A+ D
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */- J" x4 M5 ^% {& Y' F% t
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */. \7 y" F) @+ ]  r$ S5 _$ e
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */
      d4 N" ]1 e, j# ^- @
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
    1 I: ~+ \/ \- J  G/ O1 q
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */. a. t+ S/ Y% x+ V) v6 v  N, j* K1 L
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
    " f8 f# p; D" ^% u
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */. D& @0 @, Q4 \+ M* H$ C

  42. 8 r- s8 @; T+ K/ O  m, R
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */
    7 u3 K, M2 k/ ^' u. |' w
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
    9 d: c" A3 p# ]+ m4 Z9 u
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */7 q3 m9 m3 m# E+ x$ g* L) f

  46. ! q  {( [% O% j5 [. B) Y6 a% x4 O
  47. } FDCAN_HandleTypeDef;
复制代码
* V6 W6 m+ F  X. z
注意事项:& |! ?" ]4 t  I
' Y+ J8 M/ C+ `1 o, N3 j
条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
# k5 }& Z& l8 Z+ A# K* f9 ^
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码

  ^5 V2 v) _* I5 k' o( D9 Y( O
. M- @- W* r! n( f  A$ p# j7 O函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。, K7 N# j% d! |$ o8 u2 Z

/ n8 m# J" F- m" g: e- @% x这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
) N# V0 O7 G2 v
9 {- X7 F9 N2 I8 L5 d$ \  FDCAN_GlobalTypeDef         *Instance
, q$ Q, ?. E& B3 H& n这个参数是寄存器的例化,方便操作寄存器。
  y/ ?5 V" i* _6 y; c, V% O) G; a3 U9 }8 b) n
  TTCAN_TypeDef               *ttcan2 J# E/ c' A' L. U& l
TT CAN时间触发寄存器基地址。
8 C: ^9 U# t+ W
  o9 l; |* A* z; x# `: b  FDCAN_InitTypeDef           Init
6 C4 Q9 r9 l2 V* ?: Z2 T: YFDCAN相关的初始化参数。
2 b2 @$ h6 H, p7 T& h8 {! x5 B0 M7 o) L+ ^3 `" \: n9 I
  FDCAN_MsgRamAddressTypeDef  msgRam2 P/ O, t" S& O9 ], [
消息RAM地址。
3 F1 }3 Z1 |4 z& r: [7 X% W
8 L4 h9 a, B( B) ?  uint32_t    LatestTxFifoQRequest9 z# H4 D, c" W  K; J7 W9 h
Tx buffer索引最后一个Tx FIFO/Queue参数。! C6 O  C, C9 y- Z# Q! R/ k) `9 r" S
/ k3 p$ \7 B& `# i6 C% X# C
  __IO HAL_FDCAN_StateTypeDef State          1 z/ a' g+ k0 r" i/ K- }% `. c
HAL_LockTypeDef             Lock         
' T- v, G* h4 L7 v4 H  h7 T; @
! M% Z* n* W# i__IO uint32_t               ErrorCode& W! L8 A1 F: j3 t" U# [

4 M5 }7 L# |" h' ?# r9 a; V# V* J程序内部使用的状态参数。) b" f0 n$ B' Z  L' v2 x7 ~3 X8 _! D
3 [/ K$ i& ^8 C' \9 i9 u
  剩下的都是回调函数
( A& ^  o) m0 m& |4 _' x91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
4 L5 _9 t7 k# m: y此文件涉及到的函数较多,这里把几个常用的函数做个说明:
: f9 A" w: F' R8 P/ m- B' P$ r2 l0 |& K5 |2 U
91.4.1 函数HAL_FDCAN_Init
: y: G3 X! N4 ?7 L3 C1 I% p' q函数原型:8 _# Y. v7 J, J# S' S! `' S0 f

. w7 d+ v, V3 w! \) e) z/ T( ^
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
    8 C  ]( m0 I' w
  2. {
    : z( y6 F6 @5 o; P; J: g
  3.   uint32_t tickstart;
    2 a. v& \8 L3 P' O; P% i1 R7 r
  4.   HAL_StatusTypeDef status;) ~* Z1 e% U' s3 H4 a, x
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};* k. M8 J$ Q* k/ G0 r2 t, J0 l% u
  6. . I9 V' n- u. U1 u; ~* F: x5 ]" v+ J
  7.   /* 检测FDCAN句柄是否有效 *// l- g# R2 @* ?
  8.   if (hfdcan == NULL)
    3 B" U' }+ b4 K, N* s
  9.   {
    * `% t1 F1 J  R) D
  10.     return HAL_ERROR;1 ?! P: d' T5 r
  11.   }; L8 n3 b  e) g2 K1 Z

  12. : I/ p; g% }0 B8 n
  13.   /* 检查FDCAN例化 */
    % x/ _) q' N: C+ M5 ?4 K' t
  14.   if (hfdcan->Instance == FDCAN1)* f) L; J" i9 I% Y) _! _% S
  15.   {
    ' u6 g8 U: [* V1 Q5 m  g! @1 r
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
      z' I: ]0 |3 a4 Z, p7 F. {
  17.   }
    2 l5 R# X9 N7 Y$ J; ~
  18. 6 e  t5 m* J; s3 Q. d& w
  19.   /* 检查函数参数 */- |7 m: I7 c4 I$ }0 j
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    ) I0 s9 T3 \1 S4 g6 H
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
    ( @( R0 j$ E6 {( E) a5 J% w
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
    ' d/ [" W! z% g& h
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));  h( P2 v8 j# M4 R4 Q
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
    ; H0 U' f" B, q, v: B$ I
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    ; R, p8 f  I" S8 z
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));) s, H4 m: W  y* i) \
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
    ( G1 |# F. S! J- s! m6 w' I& p. |$ W) [5 Z
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));- v7 q. E1 x1 p) q/ {; L
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));8 R$ J7 M+ L* h5 n7 O2 P+ P
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    + K  v( V5 u2 C  y) T' N
  31.   {
    6 B0 @* @3 Z4 \
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));. `, s; a, H, S. o3 m
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));* H- Q) w- w+ ~- _' `* H& }
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
    3 m% J# D" W$ ~4 G/ i6 I- `6 t
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));9 t& q9 l" Z6 b. a3 a# o  V0 G- ~
  36.   }
    5 l2 i# s! q! D8 s  ~
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));' x+ p  H% }* k& E7 K" }
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));( G, t3 X9 L" I5 h
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    . n3 a  R1 }) X
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)* I9 ^* y+ L, U: W8 a
  41.   {8 E; F1 Z8 D1 x6 S; G; E
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));# b$ s9 C8 I: t+ P4 f/ A. z
  43.   }4 b# D" ?; @4 {( N- |, B3 x
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
    % k7 e9 i% z% k$ a
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)" ^6 x$ ~4 j' L6 V. Q
  46.   {
    9 z# A/ B: o; p1 Y& Q; W
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
    4 L7 p/ q6 s% n6 |! ]0 U
  48.   }* E5 F" }" t. I( t* M
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
    $ i6 ]) N2 G2 i5 E$ |4 y: M6 W
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    3 y* m' z4 R* ?, O  }% j5 Q
  51.   {9 T# ?: w9 T1 r6 B. o' {
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));% j% l( P: _, y( Y6 O* k& t
  53.   }
    2 w8 p/ E; _+ v, `  i8 Q0 l3 D6 g
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));% [7 M, {/ X- @) f7 w" W: M* m
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));* x# E" {' ~# P0 c6 [; X* @
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    * A* ^; P8 ^, \1 A0 M/ O* z
  57.   {
    ) O" w' v7 |+ ^5 F$ x: e6 k, F
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
    2 d; C2 _( O! |6 ^: Y3 n
  59.   }7 Q7 F# a% r$ I, F7 f% g1 A. M0 @
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)7 Y7 K1 S  b* W* H4 g/ G
  61.   {
    . N  Z9 L' F; O! t# T( }5 j
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
    * ~& z7 O% |$ u8 R, c" a
  63.   }: P) v6 t/ {7 o5 {, d3 h3 B) Q

  64. " I; y7 P8 O# @+ @, h/ Z
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
      S* b8 I9 {& H6 U" S
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET); f7 W4 r9 y$ K; Y4 Q7 ?  a) x% d
  67.   {; O2 ]" y1 O; ?: z
  68.     /* 解锁*/( Y# |7 T* r& F1 P
  69.     hfdcan->Lock = HAL_UNLOCKED;
    , D, C' H1 X' e6 B

  70. ) _7 K9 [/ @9 S/ R- c4 b
  71.     /* 复位设置默认回调 */
    3 G* B$ F% V$ C% a
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */' h! D$ p0 T% E% C/ t, {3 @: N
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */) r* `1 x6 V& `! ~* _. d! e7 A
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    6 Q8 |" K5 f' I, \
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
    3 l! j! }8 z) @2 Q8 D
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */
    , f( {- K& N3 T; z; z8 ?
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
    3 ]. y; S+ I' x0 L/ |9 u% H5 C
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    * N4 r7 F1 t/ ~8 I; Z5 }( R# H
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */8 Q; b- u% p. ~5 _9 o* j0 g
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */! v5 J5 }0 }: H1 r+ u
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
    / B3 \8 o, `9 A7 w/ J
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
    . r* M4 H# D2 P% O' r* Q6 V# p
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */0 v6 B1 G6 O3 v; E* q+ C4 X% D) Y
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */7 C2 i0 B3 z" d- J
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */& j" ]3 o8 E0 a% S4 K0 S8 d# o
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    2 K- q5 M: `9 _3 W. j- m& l& _
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */
    , P* N, K; s5 S7 }6 @6 O! q
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    * O2 u; L* h! c/ D, h- A6 m

  89. * e2 R; p0 w5 e7 k3 o3 [& R
  90.     if (hfdcan->MspInitCallback == NULL)" w! L. F9 j4 e: W9 X
  91.     {
    6 E. _3 X8 W9 Q# g( G  J& q9 T
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */5 u0 P, m$ W4 }& @8 F: @
  93.     }
    $ v/ V! n, m/ V

  94. ) f/ `% V& P4 H$ r9 d7 h
  95.     /* 初始化CLOCK和NVIC  */
    " x" r4 C, J. y) S3 z+ E0 |
  96.     hfdcan->MspInitCallback(hfdcan);
    / e( T6 j' x0 p
  97.   }
    * [& i5 m: q4 _) N7 W% m) A) f
  98. #else
    0 M6 b+ G+ W2 x4 J( x1 R
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    & x8 {' Q; q; r$ W  P$ v
  100.   {9 Y* Z& Y1 a+ i6 A4 V
  101.     /* 解锁 */; a/ W. @6 X; W0 B8 S# v
  102.     hfdcan->Lock = HAL_UNLOCKED;
    + B- P1 G! V7 R3 ?# U, J+ t
  103. ! L/ ?  w. \+ E
  104.     /* 初始化底层硬件 */
    0 q- x7 f6 o4 X
  105.     HAL_FDCAN_MspInit(hfdcan);
    ' d* B4 h) D" r8 g( z) O
  106.   }
    9 j1 `( K. ^* z
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    9 Z4 q8 A( _9 |
  108. 5 N( X- Q0 f4 |" y& q
  109.   /* 退出Sleep  */
    , }' G: q+ H* H
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);: h6 T  h! H! J1 n" _$ d6 h
  111. 2 ?- ~+ P( {7 M" Z; [; u, e4 f# |
  112.   /* 获取时钟 */
    ) ~( J  X* H, ~! }1 k+ b) O
  113.   tickstart = HAL_GetTick();  g* [1 L& `$ C) E$ @! W% Y

  114. 9 {" f2 K0 Y5 O
  115.   /* 等待Sleep模式确认 */
    2 F  b( X9 {7 }2 W( [2 F. \
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)# V; K' D/ M  m' ?0 |" t
  117.   {
    6 B* j6 [2 ^( u$ P
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)- \) [" w  b& o  E
  119.     {
    + m/ f! |( P( O/ n7 `5 [, }
  120.       /* 更新错误码 */" E) V5 l8 g5 o. N
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;% c9 z5 y& x. q5 c( M) }
  122. - Z0 v. w5 _. A1 h! T$ z  s
  123.       /* 改变FDCAN状态 */# D8 M* q, K1 ^& _9 i9 l+ F9 Z
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;
    2 `; K& U+ O% n5 i

  125. 6 l5 ^( g# B* v( r. {( C" @
  126.       return HAL_ERROR;. G+ \$ G# W$ s
  127.     }8 v* R7 H: S# S* {; r/ R5 B
  128.   }
    0 Y& {: ?* N% Y# V

  129. 5 e. m+ f) e& D- B. D/ B* |2 ^
  130.   /* 请求初始化 */7 z# w. Y( M. n5 f. K0 v
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    9 T2 S; f. Y" }+ P: w( T
  132. - @# @8 u( O. u# R" O4 X9 p
  133.   /* 获取时钟 */2 B* B7 U2 g% H$ j& ]
  134.   tickstart = HAL_GetTick();
    ; K. e+ A6 `" v7 F

  135. 4 E3 s, W0 W, S8 i& U) D+ r
  136.   /* 等待CCCR寄存器的INIT位 */- ]/ J% ^1 H& R9 x
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)" x, B+ s, \% P
  138.   {
    8 T) m$ n0 e- r/ h; x$ I8 B$ d' i
  139.     /* 检查溢出时间 */; G  M) P0 O' Z, }$ L  e, J2 ]
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    4 v9 }) [' Y" {  \: v
  141.     {1 O% N- s; _  t- I
  142.       /* 更新错误码 */
    % H# O9 U' L: U# U& p
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    5 ?# g3 n) Y! @+ c6 V9 o- i

  144. ( K1 q7 D: d- o& [6 I+ S
  145.       /* 设置FDCAN状态 */3 \, A/ |4 O5 o" Y
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;- O% D3 h# G" g) r+ q/ w

  147. + p6 ~+ {  p. G  F3 P/ T
  148.       return HAL_ERROR;
    6 Y" `# w$ c5 ^3 `6 L9 s; R
  149.     }
    ! P3 c" ^* f+ S8 {8 v( @
  150.   }0 J5 z9 c* Z7 W$ Q* Q
  151. ! Y1 f8 [, Q9 |- Q' ?
  152.   /* 使能配置修改 */
    * c4 G( x  v, D9 a5 ?$ s+ Z1 C" C
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
      S% m+ N8 ^+ F8 S* t
  154. 7 u0 [0 ]9 K( o) u
  155.   /* 设置是否自动重传 */% d, @) m4 x+ E$ O9 I
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    # ^. G1 f# e3 x% `
  157.   {0 n0 G' E/ n- q  ?0 `; `- A
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);# Q' M- c# g) }7 |4 q
  159.   }
    8 N4 k/ {" a; t" V. E
  160.   else
    : h/ y# x+ {. R: B3 v; O0 {5 c
  161.   {# a7 e8 M# M6 v' ]
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    0 ^$ u8 p7 V, q; a
  163.   }
    $ t: m3 h7 p  @& }
  164. 5 l6 ^& s% R& i# z$ `. D. C+ _& |
  165.   /* 设置传输暂停特性 */
    : T( Q: x: ^' `) f* C: w6 B
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    9 L" w6 ~+ z, X
  167.   {: {8 U3 `' _/ L5 N9 Y
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    9 a( j& B( z0 J+ V
  169.   }
    / S/ R- O# }( Y: M* X
  170.   else
    $ q) g2 m# E% S8 m) n7 c; j/ v- Q- E
  171.   {
    1 R  p% s8 ?4 w2 ^' j: q8 |2 D
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    6 p9 Y- c- D8 u4 C. H7 H
  173.   }
    # u6 b0 L7 P6 R  |/ J2 p

  174. . z. T( E" c* D; N. `
  175.   /* 设置协议异常处理 */
    * G/ t5 A) R% }- [) e
  176.   if (hfdcan->Init.ProtocolException == ENABLE)
    7 ~' v7 f& ~/ J) a
  177.   {
    ) v' j! }. h& S2 Q
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    - W; A2 i2 G' N. `3 X
  179.   }1 K% o" R& i& h
  180.   else
    . A# E& L  z) O, o
  181.   {: C1 h% ?% F( T* k  i9 a8 K
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);/ n9 m; @6 w. C: d3 W
  183.   }1 h; Z: l; _' j- Q( h
  184. 3 Y/ H9 F8 [5 }
  185.   /* 设置FDCAN帧格式 */& P& o0 {4 V7 ~
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    2 v" \# c: V+ x9 H& U# R
  187. 9 w+ ^8 m! f, f( J+ S3 N- P6 E
  188.   /* 复位FDCAN操作模式 */
    . ^" r" ~! A6 F( B) z& N1 R; D
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));+ [. F. r& \9 J* T% Q3 @
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
    3 E" h: M$ I4 N! r( ~! y
  191.   F7 A  ~3 O+ Z# ^! b8 J
  192.   /* 设置FDCAN操作模式:
    $ ~& X; H- I& O% Z, N
  193.                | Normal | Restricted |    Bus     | Internal | External& H' h/ U% m* d6 N
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack
    2 I( ~+ ^! o" |$ \; c# B
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    11 J; J" I) S$ H( y+ @
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    00 s. K# i. _( @7 h' i# p& Q9 B
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    11 g; N5 _% N' O, h+ q) w
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    05 g% m  |6 ], R2 c* L' E( }* o$ e( ^
  199.   */
    % [9 I# A0 h+ o! Q( M
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
    * k/ Y7 W1 X' d' A/ x6 J
  201.   {3 A( S1 i6 v4 d* L& U% B0 u" B
  202.     /* 使能限制操作模式 */
    $ j1 ^* V" W5 W& g
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
    % s* T+ R4 v. n0 G8 D
  204.   }
    6 O" g) g: i  q' I# p
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
    . t/ |6 Y3 c2 \2 k( f
  206.   {2 V+ W5 H( o) u9 b& j1 n4 d
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)$ G5 P" x( t% l" C# i
  208.     {3 _6 A6 a" T; u& |% K8 t
  209.       /* TEST寄存器写访问使能 */) L; ^4 D  w; a
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);2 h1 [" |) r1 C0 p
  211. % K. m6 J. ^: H1 [" K
  212.       /* 使能回环模式 */. f6 q$ s7 G% C; {
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);' ^# I" e" M1 z

  214. 1 h. S- Q  Q. u  a; ]
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)$ o' V- o4 r. D4 z
  216.       {
    : s* S4 Y1 w9 _9 q+ c" d  t' a( l
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
    2 N' m4 K  J& ~& E' |' u" m
  218.       }
    * G2 p* x. e% M
  219.     }
    4 D: b  ]. G5 g0 _% O, R) U
  220.     else
    ' Q& f1 j. [+ p: i
  221.     {
    2 T7 z* w; ?( `, P" T; J* G
  222.       /* 使能检测模式 */: T! i) [5 g0 t( c& G
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);: l, K( W! X- X* V5 U3 r6 H7 c& Z
  224.     }
    0 ~0 b% E( t1 c) D, x% Z9 t3 M
  225.   }
    , X9 \! g( c" Q* M
  226.   else# \7 i" H% L1 g# K; v
  227.   {
    4 p1 d# Z1 u: e" K$ d
  228.     /* Nothing to do: normal mode */( u. `8 A; Y5 a: R" N; b6 U* \
  229.   }
    7 f* I$ ]4 k% N% l( L) \
  230. 7 ~8 U5 I# t! J1 |3 j3 ]2 h: C
  231.   /* 设置nominal bit timing 寄存器 */
    ; O# R1 j- |+ j# H
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \* Z* q8 E# E. Q3 m1 U) {" D) m
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
    + U( e: H; {" S: \# s# N  F  ^
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
    + x+ a& W0 Z! _, t9 F
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));9 }, v- }, j- e2 d+ v  b! e5 B; _
  236. 3 v7 T7 l4 T1 L
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/
    * `! @) L4 j% ~1 \
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    $ [. t* P/ z% z5 a" K6 `
  239.   {
    , A+ \5 V% x9 t+ e( g
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \- L  V+ T# O' F8 w6 c7 X0 L
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \" m6 k6 w! c3 l' Y! E4 v9 X; L, x
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \  G2 u, }! G6 p' p9 E( B( D
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));8 ^( F* M6 K- z; [' z
  244.   }
    ) x4 F6 k$ N/ c3 u% n
  245. 0 E0 ^( B2 u) S8 W
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)" Q6 {  f% P. F' J7 J7 c4 {
  247.   {9 c( }5 i$ J! `4 b. _+ u$ D; C
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */0 b' @9 G; K" Z; L" C
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
    ( ^; Y2 C: b3 ], q
  250.   }- g$ K2 X' y8 e% |5 O
  251. $ x2 N/ s: G# {! G
  252.   /* 配置Tx element 大小 */
    1 U+ Y! e$ J) ?* c1 Z( B; x$ k8 O  ?
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    9 N" Q# }0 j9 p7 j
  254.   {7 r1 W. d' o) V: P! e
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
    $ B( M) i$ f0 ]
  256.   }; ?. n% b: i2 k7 `

  257. 4 e6 b2 U$ x( W0 _8 d* Z5 t
  258.   /* 配置Rx FIFO 0 大小 */
    & ~9 |. b" s$ D$ {
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)6 h0 s; Q# y( e* X/ c' N3 S7 e  M
  260.   {) @/ p+ r! K: e
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));# _4 s4 S9 [* e+ G4 Q
  262.   }
    6 j; V' [' d& l; q7 |0 `1 j# ~
  263. ! v7 n( P+ r( x/ i$ i4 }
  264.   /* 配置Rx FIFO 1大小 */
    4 o! U% a: Z5 {) O5 p+ s
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
    ) ?" K) k7 z4 I: V2 f( U0 w
  266.   {
    ! B% Q- ]& h' R$ r1 v( n
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));: b( }. w1 L: T" ?
  268.   }
    . q5 A6 i3 `. u" Y8 `

  269. 7 [! y  |2 J' P6 ]( e+ K
  270.   /* 配置 Rx buffer element 大小 */, g% i4 Y& }7 T9 R+ t( n
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)
    9 P( n7 y' [( d- K
  272.   {
    - j6 p4 c/ ~/ |* g
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));; n1 E$ P$ f/ `6 F7 \
  274.   }
    8 Z3 u& ~- {3 |! k; }  E

  275. # A3 I/ k& t7 c7 ?1 S5 w2 w  r, @
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init 0 `0 W- O$ I/ L4 C# j4 Q
  277. 后调用HAL_FDCAN_TT_ConfigOperation */
    + a# M, c2 L. [+ W  T) ?$ A
  278.   if (hfdcan->Instance == FDCAN1)8 j( _: J. b) @7 j' e) F, v
  279.   {6 A3 v5 H, H# ?9 b' H
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
    ; @' J1 n9 F- h* B& ?% x* j% x
  281.   }/ l3 V7 H, P# [) |8 s
  282. $ W) u6 o, D$ A/ a, n
  283.   /* 初始化Tx FIFO/Queue */
    ) R* I/ _7 ~6 G! W. h, n/ v2 H
  284.   hfdcan->LatestTxFifoQRequest = 0U;
    ! U9 K/ K# h: l
  285. 2 ^' R1 U7 e  d4 @
  286.   /* 初始化错误码 */2 n+ A$ O6 ?) F* t
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;8 l5 @5 E1 A: X; M6 z1 l) L9 k
  288. - a7 w4 R, x0 L& D
  289.   /* 初始化FDCAN状态 */3 @; b- y6 Z' I1 Y6 _, A
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;2 d7 ?$ ^" P) i! O! V9 Z# |

  291. : G% t: Q7 N# r; P* l) i8 X
  292.   /* 计算每个RAM块地址 */3 h1 q, I# D3 j2 V# O: T
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
    & h, T2 ]5 y0 P4 D% ~( P$ \  v: E( Z

  294. . {) Q7 I) F) Y# _# l& P
  295.   /* 返回函数状态 */# E1 d( V4 J! y+ y, k5 p) R
  296.   return status;( r2 h& c1 @3 m3 [/ L3 C, X
  297. }
复制代码
. q$ K( g8 p8 s6 h+ g
函数描述:2 a3 V, h$ O; S- ?

7 J9 [" y' |, o$ M此函数用于初始化FDCAN。; l) m, J  ?, P

( ?8 b1 K1 [/ J5 o函数参数:
, q/ e) t) A) p3 o* ^" x# t0 j2 H4 n: K# V1 ~
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
& t  a: r7 a" v3 `) x  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 E2 V  Q+ w! n  g3 w
注意事项:
8 p: y; X' q0 |0 Q: @/ e! P6 G5 J* h, j' }5 ?- n7 {9 q
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。+ }) f' X4 O2 q: a% m$ O& d; ]- v+ r
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
) s( E. m+ G0 B( x- I! P7 Y8 K对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。
/ z* {+ p# A& D2 y
) `' ^9 z# X1 B  v2 h- V+ |% E, C$ F$ [解决办法有三
' k* e2 q$ d: D8 z- _
6 g* n0 `4 Z( Y* _5 h" Q方法1:用户自己初始化FDCAN和涉及到的GPIO等。
9 J' j3 w+ V$ l% \
5 a7 o$ G) \+ y方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。: h& g* s6 B" W8 e8 Z' W+ h6 v
5 v: {! [# T$ \0 d8 q
方法3:下面的方法
& \+ M/ Q! L$ ^
# {  ^, N3 N, b  M! I. A
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)  P& |' D8 v" S  q
  2. {
    & @% n" t) K# i5 c6 {
  3.     Error_Handler();! v: r7 U& a. c+ F
  4. }  
    # ]# c' B& Y$ W* @  I
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)& F5 ?# s4 A7 `9 S% w
  6. {
    ( w2 H9 S/ ?3 Z# v4 J0 u' b
  7.     Error_Handler();: R  i2 V6 b7 O4 f4 _* ]: ~& Y
  8. }
复制代码

; T. y. Z4 @. h' G6 w4 T使用举例:; ^, U) f+ D/ s  w% W

/ ?  y$ e6 m9 B. n
  1. FDCAN_HandleTypeDef hfdcan1;1 G  r  ]0 l- _/ W

  2. ( M+ o% `) U; o/ Q: e
  3. /*
    6 S# T3 A! f+ f/ g
  4. *********************************************************************************************************
    + d/ H; O: m: C0 [# y
  5. *        函 数 名: bsp_InitCan1- R! `; x3 ]% z9 x
  6. *        功能说明: 初始CAN1
    6 l0 o  ?; u% v- {" S1 K* t
  7. *        形    参: 无  ]; d2 e8 T9 e! V* A
  8. *        返 回 值: 无5 r5 w7 ?4 Z' k$ ]- V: h7 k
  9. *********************************************************************************************************
    & Y# u) g& i& [' f% N
  10. */% k2 d; a: _/ A, [% I
  11. void bsp_InitCan1(void)
    9 A7 b" V( y' L
  12. {           Y  u# S6 m; m* m8 D9 A
  13.         /*                    位时间特性配置
    : ?# Y9 N$ f1 d& g+ N
  14.                 Bit time parameter         | Nominal      |  Data1 }* H% l9 Q; N) J. M3 ]5 H- z
  15.                 ---------------------------|--------------|----------------# c- I. O1 B- ^- T( d8 Y: R
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz8 v& S% V5 L) z( l- {4 G
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns9 n# l- `% w. Q1 w' ~2 x$ v
  18.                 Synchronization_segment    | 1 tq         | 1 tq
    . X5 `0 x( F' _* u& ?4 \& O3 E
  19.                 Propagation_segment        | 23 tq        | 1 tq
      }) s1 }4 Q7 p0 i
  20.                 Phase_segment_1            | 8 tq         | 4 tq4 S2 q. B; l8 ~# y/ T
  21.                 Phase_segment_2            | 8 tq         | 4 tq
    ; ?$ I, s2 x& l% p* b
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq
    - K" R- {# q/ {9 d
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us" d' E: k! {4 b, @2 E
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s5 D9 M: P, ]1 ^* M
  25.         */0 E3 A+ N3 U7 M" l% x$ f
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */             - |5 U$ D- N% b. a" E
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  0 @( z0 D) y2 e) h2 ?% B1 S6 k
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */   K1 G$ P( b+ A& j/ ]
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */ ) E: \; F' U( e& p+ I" p* H
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */
    4 r/ {: M$ t9 ^1 v' S5 ]
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */! \, c' a3 q1 r' i' ^
  32.         6 |$ s& H  v: `
  33.         /* 7 s  C2 U( t3 g6 M
  34.                 配置仲裁阶段波特率 * x9 [7 V4 z6 l' G8 Y; n
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是
    4 g' J9 ^& g6 a. z" s
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        5 K- ~  P/ v8 h  `( E
  37.                 : L) l' Z; P) s; J! C  W
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    6 u! N' z7 d% l; m( ]6 Y4 x. ^
  39.         */
    , I3 C. u% e2 ]! F2 E9 e
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */2 ~: p, S9 A- T4 z/ ]- n
  41.         hfdcan1.Init.NominalPrescaler = 0x01;
    ' A0 q) v) N$ D1 b+ w
  42. ( y5 {9 T; E9 |( }: u* |( a: v
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */* l' _2 P# _! e1 l! Q. k
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08; : W8 u/ t7 m! s  |8 u+ x
  45. + {" ^; O* b; F
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */
    , w" {5 B0 l3 O+ e* }
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;          ) v+ ^, |. @5 x5 k8 _# l* n
  48. + U" I$ G7 C6 R5 G# V  A
  49. /* 对应位时间特性图的 Phase_Seg2 */
    1 ~: n9 r( _: Z: ?
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     
    : _1 M) R+ F. D( R. X6 B
  51. * k2 |% V7 r3 v# K
  52. 0 Y" o8 d$ t- X; j% O, i( f2 [
  53.         /*
    2 A  L- K9 W: Y; |. m/ j
  54.                 配置数据阶段波特率
    # S+ S# q; B3 H/ t6 n
  55.                 CAN时钟20MHz时,数据阶段的波特率就是
    * ^' f- Q9 m2 r4 ]; W% O$ i
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps* z9 S) r# q2 e2 b0 I) j% G: Y
  57.                
    # Q. o9 P# }) H& U
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2+ F( F* d' h# O( I$ o$ \
  59.         */
    * i. p/ w8 J% C5 H- p
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
    $ z, Y5 _) w" @  I) ^2 f2 q
  61. 范围1-32 */9 t$ `/ @" P0 P: g  f, X
  62.         hfdcan1.Init.DataPrescaler = 0x01; , Y: E5 }* ~# M9 H7 |
  63. ; B; m' q! j" C
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
    3 Q, d1 I3 C* a( b+ h+ }
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  ; W' v& @& `9 B4 z3 E# l1 c  \) ^

  66. 3 ^4 f# v; @0 o, x8 M8 b7 d
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */4 {$ t5 D4 t$ U$ d* M6 w+ U  J1 z7 T8 c
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05; 0 R* }5 ~0 L9 V3 Q& F* y% G
  69. ( [2 e9 h! v: I/ z. O
  70. /* 对应位时间特性图的 Phase_Seg2 */                " V* m, Z3 f6 Q5 e% Y& M
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           # t) ^1 ~+ R; f% t, \% U! [0 w) ]
  72.         8 Z! @9 l. j' a; N- B" g5 [
  73.         # R0 L0 A4 {( b
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */2 V' U9 K1 ]7 |4 E1 x& U
  75.         
    . l# d$ z/ x! k/ X' K* |! V0 F
  76.         
    7 v. c6 @& a% |" o% c  B# T
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
    $ {% d' T/ l/ a0 m" q, d
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   * L, ~' V+ J3 K0 ?: L1 W
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  ; m2 N) |) R5 C
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   - [: _( g2 [$ g# o! G! c- |
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
    8 u7 J8 X' a& \
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */" q* t% u2 @: G* k9 X/ Z

  83. : b3 y: }+ Y: j, o% P+ b
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        9 K3 I6 E. h  o" ~/ e- k% W6 g# _
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
    $ Z' F  ^  F9 S; d& x  e9 C6 x* O
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
    4 k* a: }3 V) W2 k
  87.         + Z8 q5 j- T8 P9 d2 [
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */7 [% U9 Q: ]( B( F5 V
  89. hfdcan1.Init.RxBufferSize = 0;                             + E2 S( U; |8 b

  90. 1 K$ p9 s. F$ ]) e
  91. 2 w1 V& x- c' P( H& B) p
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        
    6 F, t+ n4 g0 Y7 x3 o* X3 G
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */: \0 G+ ?' W9 q8 {
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */1 S- B* y7 Y6 V# a: r# I
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    5 ?, `  [# y  `* U
  96. # `& K7 F$ D/ B/ U+ ]& k- z
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */+ z% A' o6 h8 ?
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;          , G4 ~  F. e5 @0 \. `) \
  99.         HAL_FDCAN_Init(&hfdcan1);/ A/ j. n, t( [6 A" {' @
  100. # k0 l! Z$ g; p7 }2 K. B# J' v

  101. # F* k+ v- A$ V- A7 |- K
  102.         //省略未写( T  t5 C1 P0 Z7 }" I% U& R

  103. & L3 p0 U2 {2 x1 [& g. E% k
  104. }
复制代码
7 d& X3 \; r+ H0 R2 B
91.4.2 函数HAL_FDCAN_DeInit
" L' {  l1 R- K6 M0 K- [, @. Y函数原型:
+ [$ ^" j7 D. `/ i' O: W
4 ?/ j+ y" g$ T" ]3 C, |
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)% D, R. R* u3 I- ~2 h
  2. {
    . g3 b( n# y8 A0 P) t3 f; X
  3.   /* 检测句柄 */
      ?7 A6 n5 l# g
  4.   if (hfdcan == NULL)' ]/ b4 u' v* |8 ~# D$ ~
  5.   {
    , N8 C8 q/ Z; x4 ]: g* S1 H! [& \
  6.     return HAL_ERROR;
    ' C5 ?0 b" S4 F6 c4 \, ~+ b
  7.   }( B  t  z3 R( {/ H3 b5 a/ U+ w/ \

  8. 6 i& x* }: Z5 R, `0 `3 d9 e
  9.   /* 检查函数形参 */" }+ g0 \1 y1 k# j# l: @( N
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));0 q2 a- }* V6 H8 U4 _( }$ w+ c
  11. % m$ E. P8 l, f5 J
  12.   /* 停止FDCAN */
    ; ^0 y0 w) f( [( n4 n# a
  13.   (void)HAL_FDCAN_Stop(hfdcan);
    ; a# j# t3 O9 M
  14. 2 Y& R6 e2 |& b7 d2 ?; _
  15.   /* 禁止中断 */
    8 n9 j. I0 e  ?; F6 Y
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    % E) k0 X- l' J; x  Y2 T" z

  17. : F) V8 J1 V8 v$ _" h1 Z( Z
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    / O5 ?4 d, B9 r, D/ k
  19.   if (hfdcan->MspDeInitCallback == NULL)1 T1 e3 V8 o9 z9 Q0 d% s* \4 C# e* H
  20.   {, \" y8 u2 z) i, u' [
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
    ; [" E8 P: h6 T' i
  22.   }1 l. q/ n) }8 |7 k1 w3 p& t
  23. ! S6 e4 L' b4 _1 u% \. u. {6 N
  24.   /* 复位底层硬件,如时钟,NVIC等 */
    + P9 M' x9 a0 B: J7 t
  25.   hfdcan->MspDeInitCallback(hfdcan);4 s5 w2 {- F+ B+ y
  26. #else
    # g- n. ^0 ~8 O- d# D9 x# k
  27. /* 复位底层硬件,如时钟,NVIC等 */
    # a# W$ u7 g5 ~/ t; ~
  28.   HAL_FDCAN_MspDeInit(hfdcan);
    ; l0 _: e5 ^, i2 G
  29. #endif
    ) a  f7 v8 C  ?: Z* i
  30. % x8 b# {( N( P6 x
  31.   /* 复位错误码 */  _. s2 c6 T5 J
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;$ ]2 f. c" K* }. O- q
  33. . Z6 o( S8 P  f7 P2 W# {
  34.   /* 设置FDCAN状态 */
    ' M/ R* {4 [0 ]4 _( X9 W2 T; r3 K
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;- i: k$ z5 o6 w5 ^2 q& v  U* _$ [

  36. 0 ^- D9 q; X4 I8 V
  37.   /* 返回HAL_OK */
    1 g8 s( s$ T; z" K. O
  38.   return HAL_OK;
    : H) t8 b7 `0 o( f+ f
  39. }
复制代码

; p+ Y' p# g9 R* D" P. L( g函数描述:) [5 D5 G3 y' c5 B3 W2 E( y
; p- W! u7 f; H6 i& k* I6 r/ c6 T& L0 T
用于复位FDCAN。
/ f$ }9 \4 x% a$ N- l' C  f2 }1 e* n! y; U& S
函数参数:
1 D/ ~0 O0 f1 l. U2 K: F# P, l! J! e# W  S- N
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
' k* x* q6 f' j) h  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
: T; T1 E" W6 i91.4.3 函数HAL_FDCAN_ConfigFilter
0 Y2 I  }  A% f( h函数原型:
8 U3 D1 ^  P7 ^  v& [6 E1 s: ?# Y/ m' B
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
    ! e! o& f' r$ d# w! h, N* `, P
  2. {- D3 s0 |: D! G" {' A
  3.   uint32_t FilterElementW1;# E7 [+ z2 q+ g$ D  y/ a
  4.   uint32_t FilterElementW2;
    2 s- c4 }& ~& D7 T$ T, Q
  5.   uint32_t *FilterAddress;0 N4 l) J3 s4 O5 m& B) T. Q
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    ( z5 H# v+ ^4 l& v/ X* c

  7. ( x; q3 z: m; A) l% q. l
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    & R( U0 Z2 }# ^  Y2 G* k
  9.   {5 z# m5 d6 p$ O2 }& S
  10.     /* 检测函数参数 */
    + }# Q1 z: g$ m" [* G! F7 |; I
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
    + R" `/ s' L  O6 P5 y- m
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    , b! a5 m+ ~% f; X  j. r1 W- H
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    7 v9 r' A/ g6 Z4 f. W  N! [
  14.     {5 ~5 u- I; i7 U% Y- N
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
    . i* ?, K- D. c% U2 @, Y. N
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
    + Y+ r# f$ U2 N! m
  17.     }. l) B! L5 H0 C  }

  18. ; F* Q; Z  c: O- R4 ?, P
  19.     /* 标准ID */1 m* n" s, _9 y+ f. y* `) n
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
    - n4 N9 b: A6 ~% D) d  N
  21.     {
    9 C  B8 v4 \* c
  22.       /* 检测函数形参 */* M1 O. J+ \' g  Z
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
    , _; s, J. |* d0 I  H( C7 F
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
    3 d2 L3 H( g! D4 Y$ k
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)3 f9 a! k) o3 s+ b: ~7 B# a
  26.       {: P& q6 k" t( f% ]2 l; |
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
    : ~, S: a7 q6 c; t4 g$ _6 T* u
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));/ J1 C# e" s( ]2 t( @
  29.       }
    4 C2 H9 I: {1 }( q3 i( m
  30. 8 {( f8 k2 {2 X6 p/ z) f
  31.       /* 构建过滤元素 */
    2 ^0 x& d6 i9 v* H! A% M+ S+ r
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)) m8 g' t- C6 s- Q* |4 l7 i% V
  33.       {
    * e$ s) E) u/ Z$ _
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |! I% p+ Z0 a. @! c7 ?
  35.                            (sFilterConfig->FilterID1 << 16U)       |% v* h  u0 L/ i  l6 m
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |/ I3 s9 y6 N  y) w+ W) t0 S0 ]
  37.                            sFilterConfig->RxBufferIndex);& H2 W- R- q, T: r$ `3 \; n) R
  38.       }" ]1 }% U" G/ }  I1 C* i) j2 Q5 N
  39.       else! h& G0 }0 W; _! B& y2 z" w
  40.       {
    3 H3 x5 h$ n& p+ O: i6 i' k
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |$ }6 [' H% h2 D1 ~
  42.                            (sFilterConfig->FilterConfig << 27U) |% j! ]/ [' z5 _$ P8 \% ?$ L& F8 {
  43.                            (sFilterConfig->FilterID1 << 16U)    |, Q- S$ ?& a  V/ O7 t- J
  44.                            sFilterConfig->FilterID2);
    5 V% W" f- |. {# i- F+ L% W
  45.       }
    2 `' v) }' f1 ?0 j& v
  46. / t: m: k, _2 o' ~; U
  47.       /* 计算过滤地址 */+ }% O  j) W+ B% E5 [
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));
    * H; ]  y, p1 u" N- \+ b* w
  49. 4 @/ C5 Z1 j& m( m( o; D
  50.       /* 将过滤元素写到消息RAM中 *// w. R& c; y* c& A
  51.       *FilterAddress = FilterElementW1;+ Y0 J8 G4 }# m
  52. }- T3 d  v. G, I# n4 z6 K2 F2 T4 O0 H
  53. /* 扩展ID */
    - h+ B) l/ G+ @7 _2 z( A$ V
  54.     else + @; N1 J; V0 q" ]' p
  55.     {; T7 K4 v7 s% x% M& K; f
  56.       /* 检测函数参数 */
    9 r! m! T* c- k0 H( |9 b  [
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));; q1 L( n4 z: w
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));3 M8 Z+ A% `, E+ }
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)& \; S  L% s# H2 p- F
  60.       {, y/ f/ X; t# k, W( n/ o  X  C; T& |
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));$ z, s  d; ~3 r, D/ S6 W
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));+ b- N2 x4 }: {" ?# o4 p
  63.       }
    4 i, k. Q% L: H
  64. " @! W! o- }7 u& u" D
  65.       /* 构建第1个word的过滤元素 */
    ; h( |' H5 h' h3 z0 ]
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);
    & V# t5 W: e; ^1 W6 P- _

  67. 4 Y" @5 t/ w# V7 t$ S  Z1 u; v
  68.       /* 构建第2个word的过滤元素 */$ D+ @+ @6 v! E& k/ v& Q
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    , Z  O4 p5 n) i; x5 ~4 W
  70.       {1 C) s( S+ n$ f) x; h
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;0 u) w6 ~  {) R
  72.       }) Z7 {# Q) f& S% c" d5 I1 _2 D) n
  73.       else
    / c( R( P# n" N
  74.       {
    * k* k3 I  S: G" Y
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);1 F5 B6 A! f' W" c. {) M
  76.       }
    # b6 W1 f/ e- g6 m+ t

  77. 6 G4 s# j6 V* o- E
  78.       /* 计算过滤地址 */
    8 d8 W0 G2 s: j
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));' S+ B: Y4 }  a7 r5 \
  80. 4 c2 \4 b' B+ Q  B
  81.       /* 写过滤元素到消息RAM */
    * v# L- H9 Y+ Y5 l% j4 ~3 N( M
  82.       *FilterAddress = FilterElementW1;
    ) R9 N9 ]$ Y# _& o+ m7 }
  83.       FilterAddress++;
    0 P( b4 }! [4 c$ Y
  84.       *FilterAddress = FilterElementW2;
    $ s2 S8 A+ ~; p+ {; ?9 w; U) q
  85.     }4 @* z* v, f! |/ Y& A8 I

  86. * j9 o' g( U# A7 l+ B* i
  87.     return HAL_OK;& D$ b+ H9 G8 k$ N9 ^2 N0 K+ Q* C: j  Y
  88.   }+ H) i" F9 n0 T5 q3 U! N# |
  89.   else6 ^! o) O4 g9 y2 u
  90.   {
    2 E+ q2 L3 |% F; P# l/ C' Y; W
  91.     /* 更新错误码e */
    + N6 ?6 k+ T  O. F- z! d0 X
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
    ! s4 i& [6 f7 ]

  93. ( I) `* W9 q; B5 p6 a, L
  94.     return HAL_ERROR;
    % Z# U$ }/ W: {2 o1 a
  95.   }
    & f& s* a) Y1 _
  96. }
复制代码

  f/ L* f. ?+ {8 n9 E函数描述:' Z# k5 b& U2 z- l+ J; K
  }1 [6 v5 I( p5 s4 k, J; w
此函数主要用于设置FDCAN过滤。
6 Z9 C1 M  J2 m# M$ |# x2 e7 V; }7 X) \9 f1 b# Z
函数参数:! u7 U" v$ g- p9 Y! G: N
: i6 c% q% Y) \8 J- o0 A
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
9 V3 |* u( b9 O5 B% X! x; T  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
" e1 ?* S/ B2 n0 t2 u7 N- ~# D$ c  c2 b  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。- Q7 ]5 J8 z, z) a, d
使用举例:0 f( x6 V8 a/ y1 d. C
! T6 D: q" `- P7 A% W" x
  1. FDCAN_HandleTypeDef hfdcan1;; C5 N' o8 A/ s' m  Q

  2. & Q& U. C2 G( T% f" ?
  3. /*
    ( Y5 o+ N! X* c$ d1 k
  4. *********************************************************************************************************/ {4 \2 u5 {, S# q
  5. *        函 数 名: bsp_InitCan1! Y4 H" s% r4 k( g. X3 N3 a+ U
  6. *        功能说明: 初始CAN1
    ) E& O, s3 B+ f$ G: U
  7. *        形    参: 无) Y8 K1 m; N: k/ Z3 I
  8. *        返 回 值: 无
    4 ]! X8 L; p" M
  9. *********************************************************************************************************' S/ }; x* ], b& }6 s" k
  10. */; X7 \2 \8 U3 z- c7 p
  11. void bsp_InitCan1(void)
    - g& _; L3 |4 @6 I
  12. {         * I& P" S+ r) r; A, |
  13.         
    # T1 t+ d. L- d) d4 `: x* ^* `6 X1 K7 z
  14.         /*
    : K  N7 Q' [2 s* J
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。
    8 d8 u" c, m  u6 A. [7 Y
  16.                 FilterID1 = filter% o+ ^7 m+ h" v' E; `/ A
  17.                 FilterID2 = mask; n1 c) O$ }( [
  18.                 ( x- U( |  x7 C
  19.                 FilterID2的mask每个bit含义
    * i& c3 t- n. B
  20.                 0: 不关心,该位不用于比较;
    ; \/ e4 |* G1 L# b
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。$ ]$ @* c# ]4 A6 }$ j
  22.                 : x5 Z9 g9 \$ I; k( b- ~0 @
  23.                 举例说明:
    7 O" ?6 R# ?- @% b0 K
  24.                 FilterID1 = 0x111
    / @: K2 c+ W, ~# v" P6 s$ ?2 @
  25.                 FilterID2 = 0x7FF
    ; w" I) q! h2 h8 s, P
  26.                 表示仅接收ID为0x111的FDCAN帧。
    6 l8 g4 l6 Y' x" j5 `) ]0 m
  27.                 7 w6 h" U( }, s1 B5 Z% @; S
  28.         */, B" R$ ^4 c" a) r, e
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */
    7 l1 i: p% {1 o5 F1 }, f% A
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
    4 z  Q9 l6 X, P! P9 L
  31. sFilterConfig1.FilterIndex = 0;                                                   8 m; g' t& S7 g. @1 u
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */
    % r1 F1 f9 q3 G/ y0 t* h% j+ ^
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
    . V& T. ?" t' N
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
    ) `! o, T9 h4 }7 D
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */  U8 i- o! y" s% M; p( e
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    ! m$ w6 E+ K  B" P# q% s
  37. 8 |- t0 N8 |2 X! |' ^3 T+ l) t& K
  38. }
复制代码

- \1 a0 L* _) w# Q  n: J91.4.4 函数HAL_FDCAN_ConfigFifoWatermark
! A# a- u' |# Q' k3 ?函数原型:1 ?$ r: p! k+ T2 L
/ d$ C  f3 j- Z  U% k1 {
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
    2 k4 Q: y' ~$ |1 K! u& H
  2. {9 D2 ]$ l" H) j# M1 v: L
  3.   /* 检测参数 */* ^, |+ u* }+ s
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));/ I  _$ x, }$ Q5 `. U) q
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    4 ^# |  z' N1 f
  6.   {
    & c/ G5 T5 H. }$ b6 G3 o# |
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));- r/ g. z7 P7 {. Y3 O
  8.   }
    9 R/ J; }1 J# e, h0 V* h2 B- C
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
    ' h9 h/ V9 g, V9 u# u1 [
  10.   {
    ' u1 u* |: T( w: T2 e
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));* V! R- i4 Y: y  S& q& y6 ]4 A) }: H. @
  12.   }
    $ ~- ?% @0 R/ F8 W

  13. ; m" u% [" ]+ y3 G$ n
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    ! Y; @0 E! _) b8 \2 ~$ M
  15.   {7 N! f" J7 B8 B5 |% |
  16.     /* 设置发送事件FIFO */: {4 u' u$ ?0 B- L( E9 N! C  x
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    % p8 K$ D. r8 m& _
  18.     {4 C4 f* u! L4 R1 N( T* _& o
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));" J- f. a, _  r) D' Q6 x! o
  20. }
    ) L6 M3 d3 C" C+ o1 H& O$ v
  21. /* 设置接收FIFO0 */
      O0 j1 ^! F% I) d/ p
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)7 k5 x/ ]3 o% P6 x* h$ d! R; }
  23.     {/ Y; E* }( S9 X( q) E* z. F. }
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));. u0 x+ B4 T* i- t+ p" [' [- ~
  25. }' l$ E# o; }& k8 E0 e$ N! C' r  n; C
  26. /* 设置接收FIFO1 *// r$ L4 h! e0 [6 _
  27.     else
    - I1 f3 H! k7 A
  28.     {: T5 Y/ X# |2 I6 p0 q! b1 S' c0 V
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));4 f& M! @  C- t2 c2 E7 B. r
  30.     }
    ( }. r# I! u7 s+ a1 T% h
  31. 7 p9 v! G) l5 W# u" M3 @8 D
  32.     /* 返回状态 */
    - [4 e2 u0 O' x4 m
  33.     return HAL_OK;; ]1 u( C* L" i1 Q* x7 ?* D
  34.   }
    ( f. f( Q' ]' e: s
  35.   else; f* N% ^% l, [$ M& h) M
  36.   {: R7 H5 [  n& Y: h/ r) {7 h
  37.     /* 更新错误码 */; t/ h3 u' e& Z. T0 G' E9 I
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;" _; c2 x! O7 t: d

  39. ( p2 C* |4 c) F" f& M
  40.     return HAL_ERROR;
    ) y/ e5 |  E, z. {
  41.   }
    , _+ ~8 u( r/ F8 j
  42. }
复制代码
, z' q/ v% T9 }2 o* k. i5 y
函数描述:
. r) D  `& `5 V( P7 l0 s- D' V% m! }, X( J5 E$ V% J( E
此函数主要用于配置FIFO Watermark
0 C- R; k, Y" ^
9 d& v! K  s  X- c8 C- f, I函数参数:
) K8 a2 d. `' ?9 t
' u" d8 `* s! a1 x8 I7 b7 [0 E( Z$ D  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
3 U, n& F& t6 J: ^' o  第2个参数是FDCAN FIFO Watermark
. Y4 l* u% X' z3 |- D
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */! ?) b7 `+ F+ y- }3 D
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
    ; m2 f0 M$ _% N8 K
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码

5 }& q' i, S; R8 q& R! T  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。
4 B9 D4 A. F- v9 `8 @  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
, z4 P9 H+ d; D; N使用举例:# \! N! e1 g# K% F2 Y- K
8 Q7 c) O. Y$ L% }4 X; D* d. B
  1. FDCAN_HandleTypeDef hfdcan1;8 K! @8 y; ~3 r( [+ d* m! ?

  2. , U8 E' ?. ?8 A  Z$ o
  3. /* 设置Rx FIFO0的wartermark为1 */
    1 f$ X& _9 P2 h$ r
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
4 F- p+ g5 g/ x$ i: l
91.4.5 函数HAL_FDCAN_ActivateNotification
1 E; Y8 e2 `$ E6 I5 c函数原型:
" ~$ L/ W! I- P, a/ ]- o
+ R5 z# v- n5 w! e7 ~
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)
    # t/ q- [% x. I2 F2 H7 G
  2. {& x# J% {; z) o( z% K$ B
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;) C- a/ c0 V3 z
  4. 8 k4 T) k7 _3 G* G; _
  5.   /* 检测函数形参 */
    , {2 E. `, C+ G9 W; b# G0 n
  6.   assert_param(IS_FDCAN_IT(ActiveITs));
    ' i; |4 t( l7 m
  7. / D% d, [3 _+ b' o
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    + C+ d& A; b: d# P5 ^5 c1 H7 q
  9.   {
    ! i, p* G: @0 m- t, J2 z( \
  10.     /* 使能中断行 */
    " E" \! b: q" F" d! k& K/ f/ G
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
    ( X( O3 L. i6 S# ?
  12.     {
    ! Q4 e5 V+ {) ~( ?! g
  13.       /* 使能中断行0 */
    % ]" H# f; g, t, n
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
    : c, ]7 f2 `5 ?5 x" U
  15.     }  K$ x: F! u- q
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)  |* b9 m5 Y+ |+ Y0 K& E/ U5 b8 q: f
  17.     {) W4 O4 k  G7 M+ ]0 f. G
  18.       /* 使能中断行1 */
    # w1 [  {; S/ w( w2 }9 W
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
    ; b2 Q3 A# e! V% `* M
  20.     }' M1 o3 b4 @% M) M2 O' z
  21.     else
    4 ~6 {  Q$ c* ?+ x* g. w1 E  `3 [- z- X
  22.     {, W# N! x, A/ D8 ^1 M
  23.       /* 使能中断行0和中断行1 */8 q. x. c0 J$ V* F0 F
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);' \7 M4 C: s: |) K+ F) w! c  h5 @
  25.     }
    6 m% N% b$ \" B; `1 h
  26.   \: t' N" r: Y
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)/ G- j8 V% F% _( v& K% B
  28.     {! F% w. ?1 u( y  v
  29.       /* 使能Tx Buffer Transmission 中断 */
    2 [) P: d2 r) U  S# U# i
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);* M. h) a9 Q* J; b' h4 z$ v, b
  31.     }! H$ z# {9 s7 A: l0 T" m( T

  32. 7 q6 C' _- X5 _+ ~. {$ P
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)3 G3 G& @+ _5 v; p
  34.     {* i, w) O! h/ c$ A
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */
    3 M7 v7 @! V8 `& k
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);+ b0 A& i; H) d  L+ d$ ~# W' C
  37.     }$ T5 C7 s# f1 R3 q% s: t
  38. - A2 s. `7 `4 V2 M* F% a  C
  39.     /* 使能选择的中断 */& n' t- t5 l& A' m# M' A
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);3 b) n& m2 q8 W  D5 i  p! |

  41. 0 r9 |0 U: L8 ?& H
  42.     /* 返回函数状态 */( U0 g7 E! s$ b" B& [
  43.     return HAL_OK;! C3 m! ?& S4 f, {/ B8 O
  44.   }
    7 B% V& R9 p6 w
  45.   else1 ?8 E2 h0 r0 F+ _
  46.   {0 K5 |2 T" r4 n( U; h5 e$ s/ T
  47.     /* 更新错误码 */& g( I! u4 {; t! t: w4 _
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
    6 i" g) F" p# P% b3 t; o, l; g
  49. # N! }$ n+ N$ E2 o2 `
  50.     return HAL_ERROR;3 d8 f- s$ K* _+ a. H
  51.   }, Z- v8 Y, f, R- p* @; ?: w
  52. }
复制代码

$ ]7 l' J! d5 r2 O" j函数描述:
- P" ~) c, b9 l& n( u1 ]3 `% l5 H  v1 }7 _0 V# H7 C
此函数主要用于使能中断。2 ^' a* c5 ]9 o4 l1 L0 q, Q" L1 [
3 r/ m% Q, N- m- ~. \+ x4 W0 ~# o
函数参数:
: Z4 f- A1 c7 l( ?4 k( m8 e
5 ]3 U- t( a* Z5 M) l  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
- T* ]- `5 @: C$ v  第2个参数用于设置要使能的中断,支持的参数如下:' a# H8 g$ c& t  y# v
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  
    ) k# @; C, b7 P5 _5 `
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
    * a& }; Z, o1 }) D$ C* E* \) H
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         
    3 _3 }0 y& J0 u& W. C
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */
    " X0 Q+ [1 q* Y  m2 }
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer 5 {8 f' O2 R! F
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
    ! D3 z7 F" O+ D% d# u' F3 M
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */) D" G7 }2 u9 I. Y! e, y0 Z7 b/ A
  8. ! L( u% H7 }8 K6 o9 g
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
    2 y  I! y3 V+ j5 e
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred 9 k# Q: I# |- W
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */3 v" f- L* ?: s6 J5 h: {
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */& G) S  s$ {1 E- a
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */2 P! ?+ U) U2 [# m
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */
    ( s! a7 U8 v: X. G: F$ J7 _

  15. 7 g7 c3 q; _; _( ~/ {5 d
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */9 \* _: c7 ]$ v7 ], d$ y4 z
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */
    & z8 h" M9 R; l: ?/ L
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
    " J5 E6 Z' B9 a7 d
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */
    : c  M# \; P; L. q" q: \6 m2 n
  20. 3 ^  n( H+ V) R6 ?* Q
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
    6 A2 ]6 z3 t, @! B( d' f+ M- _
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
    4 d1 V+ {2 u1 f
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */' x9 O0 U$ u% R+ n
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */% }* f6 _7 I& D
  25. % {: `% u, {8 l+ _$ ?7 p+ s
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              
    ) E, R+ R- Y' ^" M( p
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
    ) K/ t% a  y  n6 ~3 [
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  2 @& i! D3 s) F$ V
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     6 P4 G& W  w  J
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            % ~$ X& O1 r. R7 U' l; e. z
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              
    / f- y1 S! [. t
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
    / D3 X4 y5 ]( X" ]0 L* E- b/ C
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */2 G& W  ^* y2 r! X4 n
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码

( W5 A  x4 L: g5 W# y! w$ O4 n3 n  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:% J9 l* f, m1 W$ U$ B9 A. ^
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */( ]4 X  t+ i* c
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */5 J* Z. f) l/ }  ~! z* v) \/ J
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */; I# K1 p! w. m
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */6 F3 |  c/ ^% H5 W
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */' V% @3 P- B, Z: o- j$ m7 x3 C
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */
    , Z. f+ H( s# K: I( q
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */
    % c& B# T8 Z& i3 }
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
    ; g4 C2 M! ^8 b( b, ]) V) q6 \0 ^
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */
    : G9 e: K& k) x+ G: u
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
      I. R& a0 w9 w
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */( {5 l( P- d- [
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
    : C( q! }/ g8 f
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
    0 W0 F- X, y# h( c
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */% g& w! ^  a* G. @! D
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */9 n/ B  B) W& O) B. s
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */+ f& \; O( ^, g0 S
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    8 s3 ^! B8 K9 b2 ], _0 f# [5 a
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
    - R) n7 Y" X0 S, T
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */  N8 `  m$ }4 {: t+ P
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */% v2 S' a7 A3 ?7 z
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    3 D, e0 {$ _+ b
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */2 ~, u0 G. p! k5 @) K
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */: ?( K1 n9 U9 ?$ ~) N) _; S9 y! b+ q
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */" U6 ?9 g% \- z* u+ u
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
    ! |5 U; b3 k2 F. {. Z8 G" N: ?, F
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */: e1 ]9 m. e; q0 u- B/ x
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
    3 {$ J9 G. t$ E* X0 E, m) E1 N! ]
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */$ s$ E1 Y) L. q) X1 v$ _
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */4 D( s6 m4 b. X! D
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */- y6 v0 K( }4 i( D
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
    , Q4 X8 h/ o1 s( ~7 v
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码
6 P0 |  ?! U9 H1 L+ N. B, i7 \$ H
如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。6 d/ a1 O1 u7 Y9 }

4 W, e7 X6 H5 h8 F" d4 I6 @, p! R" R  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 G1 S  e5 X  E
使用举例:( C% _, V) k; l5 @; ?

8 z1 c; x# _! VFDCAN_HandleTypeDef hfdcan1;
' I3 c0 w% w" }4 O3 n
( E/ {, {6 ~/ v' T* Z/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/: ]+ [: U5 b+ h7 D' X
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);( B7 e+ ?' ]% `; l) R, U6 l
91.4.6 函数HAL_FDCAN_Start" }) L* e" x& ]
函数原型:
- n3 z* s) D  @, w0 I
, W' P6 P; L8 A7 L& z( z) T
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)2 k8 n& P& |3 ]
  2. {
    4 r+ y8 b3 R* E. b7 X5 T5 n
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    ; n8 D$ b+ h0 t( E0 I- Q. A  Z
  4.   {
    2 W/ z8 P/ j8 H4 v! j% l
  5.     /* 设置FDCAN外设状态 */
    / \: k9 Y& C7 G0 x
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;
    ) l: I, ~) _9 e5 t! K8 |* a

  7. + x9 Y* g9 D. W! [5 @
  8.     /* 请求离开初始化状态 */, I( [2 @7 b" [$ i9 f9 c! w7 b
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);. `; l, S( d9 Q5 _; G
  10. ! `& b: K* `5 F0 R3 |
  11.     /* 设置错误码 */
    ! D) }7 y9 E# T) q
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;( x7 T  m. i5 }- H
  13. % a# ?4 S! T% F% C" v8 a1 Z1 }
  14.     return HAL_OK;
    . u9 n1 d0 [3 J  {
  15.   }
    * k4 d$ a' i7 d; M' j% V5 d
  16.   else7 U) @9 d+ N4 b( I) O5 s
  17.   {1 e7 M4 b$ ?: Q; f- r: h
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;& ?0 i$ L1 U" j3 D/ D4 a# Q5 ~

  19. 2 K2 }" M. B' N3 S8 o5 ~; Y
  20.     return HAL_ERROR;
    % U5 e; \  i% F
  21.   }
    ; h4 g* r$ R9 P
  22. }
复制代码

, Z% `! g6 T& x0 S  j8 }函数描述:, }- b+ |. w: H1 Y

$ }+ i+ p( l- Q1 J" O! }3 i: ?; @% Z此函数主要用于启动FDCAN。  |# Z9 }8 p3 `5 [% [; D0 k
( Y. q$ \; W/ j9 C
函数参数:0 }7 K/ ~% `% `' O

8 ?" q! ^3 A( @; x  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。3 R& U/ G, r/ }1 |1 v3 O7 N( U
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
% k$ Q6 H/ \' {' i; G+ A6 I使用举例:
7 A! R/ _* L+ b( @$ K1 X5 I& G- S( m9 I/ E7 F% }
  1. /**. a% M& M& w0 Y7 n6 c
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.5 [* @8 }4 O, A! S
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit6 A% s, n* B- Q
  4. * @param  WriteAddr: Address from where data is to be written8 U, S& D+ F. z. f4 \$ N; Z! L# J
  5. * @param  NumOfBlocks: Number of SD blocks to write! Q: J; D" ^; S) d
  6. * @retval SD status
    , p6 e% G* M3 S# G9 J
  7. */
    ! k$ g0 h" d# W1 P- ?
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); S. M* S9 M, t% n) C0 H9 w' F: K
  9. {, b- \: \+ ~3 ]  ~+ u
  10. 8 ?% M6 J) U. h2 O
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)$ G9 ]" k' l( s2 |4 S9 \
  12.   {
    ) G4 X/ n" ?% I; H0 }0 K
  13.     return MSD_OK;' N. w! H5 o7 m  N# `+ s/ R
  14.   }
    8 G9 z- t( ~+ x: ?& a5 V0 k$ U; M
  15.   else- t) {8 D* |" m0 V
  16.   {) D/ t! U) n/ V# {- u
  17.     return MSD_ERROR;
    + N7 p8 @0 b8 F/ Z+ `/ Y$ G/ j
  18.   }- b3 w% ?* g3 u1 ]8 c
  19. }
复制代码

2 E9 G! k+ o3 ~+ a3 w& F0 [91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
, P* B& T- F: r! H9 o函数原型:% `; }  |7 [" k6 v
, n- ^) t) P! ^7 o
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)# W: u. L5 }) a) T$ k) ~! G" y
  2. {4 P; p- l  }) n! }' b, x
  3.   uint32_t PutIndex;
    2 ]7 l' K4 w4 J3 X
  4. + x4 v: q+ p% K5 `& A$ ~
  5.   /* 检查函数形参 */
    9 f! r: k7 L' d& k
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
    0 ?$ {$ [8 F; w% C' B) ^
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
    4 M, R' Z+ I0 E) f
  8.   {
    % [2 q) X1 U8 e4 s9 S
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));5 C6 a7 R) `# g0 Q, W" Z/ Z+ K
  10.   }
    1 u* U8 }7 Y6 P) y  j! E
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */5 w( Y: r/ v1 ^: n7 d! i( S
  12.   {0 A) C+ E* C2 a
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));3 n! F  m6 x, n/ H, N/ ?$ ?( D
  14.   }
    3 j0 B- `" S" b0 B- }, n
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
    1 T( a. o  J$ u
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
    1 \- ^. Y4 V2 T- L# z' g, r
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));9 x. z+ g/ l# t: s( Y; K7 ]
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));1 ^2 S* C# N3 W: R
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));, }& T  M* a" W; \
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));4 G& _" z+ c# a. H# E
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));% t, F6 B3 U/ [/ B

  22. 0 z6 E/ [7 y" @& b8 P
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
    + {7 Y+ k. K; W( \
  24.   {* M7 ?% Z0 k4 X# H9 v
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */, j- R* N+ N$ S4 i; O: ^
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)# e) A. z+ Z( ^/ i0 |9 U/ y' u
  27.     {1 m5 {* |& ^( Z
  28.       /* 更新错误码 */* p2 }4 V0 J" j- N% ~: _) f
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;& u9 m' B6 N# J$ t' N/ p# L9 B8 |
  30. $ f  e8 n; _& W$ ]+ G" H& `% U6 g
  31.       return HAL_ERROR;2 H, Z. o2 z! r# T  Q
  32.     }
    5 f* \$ G9 \& b; Q; _
  33. 8 R. q3 c* q8 h! ?8 ~2 g
  34.     /* 检查Tx FIFO/Queue 是否满 */; J6 E  l9 |8 e
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)4 \: b. ~/ s" {9 ]0 H$ Z$ W
  36.     {
    * B, P+ p. j0 N1 c8 f/ _5 ?
  37.        /* 更新错误码 */7 F4 [. G( |. v8 Z4 O# T% A3 ?
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;
    ' ^/ Q9 B8 C0 }- Z6 _) d& x- ~% w
  39. , U  q% n  m' E! Z! C) l# \
  40.       return HAL_ERROR;
    ; A+ h# c* H$ E' ~: x, U. ]7 P
  41.     }
    5 B1 `$ a2 ?# g$ l( Z9 f
  42.     else
    ( e  i# U2 m  D3 q! [0 x+ j
  43.     {! K# Q9 ?' I4 _2 i! N* i
  44.       /* 获取Tx FIFO PutIndex */
    - Q& N3 `# F+ z5 b7 a& r- L( [
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);
    - W7 P; H* |- _" K) H/ o
  46. & R/ s- j% B9 |" k
  47.       /* 添加消息到Tx FIFO/Queue */
    . `0 _* U$ V3 c3 x
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);( L$ \- E, {( b0 {6 F

  49. " r4 y: X5 l: H$ M% X/ T: B2 ?
  50.       /* 激活相应的传输请求 */! n* h; d: M+ @6 Y4 Q
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);" E) ^# @4 u8 Q7 Z
  52. 6 i4 h; o" @/ A' }
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */
    + k& }& A- g1 c+ S, C0 N
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
    0 g8 ^0 m3 A% R5 ~" }; U( b
  55.     }
    . W. A; w, ~, O( z' _
  56. # g" v3 [% X9 p, m2 c9 O5 `
  57.     /* 返回错误状态 */- W, c7 P4 S0 }3 q/ S, g7 R
  58.     return HAL_OK;2 B+ l2 F" C# w- h+ o' q: C( x7 `
  59.   }/ z+ V$ b- j8 S' _
  60.   else% e8 v! ~3 v* `7 P. Y7 _  ^
  61.   {
    8 r/ v/ ?  x9 g4 a
  62.      /* 更新错误码 */; @, \( c" A1 m6 A4 r: d5 W5 R  l
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;/ ^2 O$ D; U: `/ f, d( O0 k
  64. , l9 n" S( O2 p; q! }
  65.     return HAL_ERROR;8 q7 R  i; i( x  z7 w6 F
  66.   }+ @* W6 c9 Y/ ~
  67. }
复制代码
% |5 o5 y% M/ J& Y+ g/ z
函数描述:8 x, f; M0 Q! n7 R

1 [" W- }0 |1 ~" s2 p- m" q" B此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。
# s# K8 V& a' M: D( j% P
0 @; ~$ q. F! J: V5 c函数参数:2 g6 r' W7 F, P( S

$ T2 Y/ ~0 U/ `7 E" |  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。2 J. ?# h; S: N, ~& Q
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
& e! n: o/ ]' Y2 B, W  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
# i  C4 M8 c4 u- z! G  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
# ?1 o, X! n6 T4 @! \使用举例:
3 F1 I' Y- n$ q5 d8 ~# a0 d1 s) ]2 _' B4 F7 A$ W; s3 {4 M
  1. /*: {5 c1 p) M  |1 ]" v
  2. *********************************************************************************************************! u' z8 C8 C+ u6 I; a
  3. *        函 数 名: can1_SendPacket5 U# G" Q  e! x; _
  4. *        功能说明: 发送一包数据, Z1 J3 L4 J4 h8 U
  5. *        形    参:_DataBuf 数据缓冲区/ t! |( @/ J+ i  I* Y
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节; n. k* n6 `# T" G3 l! Z- x4 n+ {5 E
  7. *        返 回 值: 无) C4 w( H; p; I$ G2 Z8 p5 ~
  8. *********************************************************************************************************, l$ [+ R* ?, h1 ?/ w
  9. */- d8 y6 n* E7 [) E
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)* d7 b# Q& x7 _/ |3 w4 C& l# s
  11. {                5 O3 K& h6 B' w8 o6 |2 }$ o
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};5 B& L/ n* E$ b& C, e0 E/ p+ H  a' d
  13.         
    ) x; b7 g9 @+ \& [+ w
  14.         /* 配置发送参数 */
    / e! d; b2 z& R
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
    ! [. A6 b& |& }2 N0 t. f) a
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
    " N7 K. h: H% D  k# Q8 ?% }) u
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
    5 {% a* `" \2 g) x9 n
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */3 G/ P" i1 w* a0 E
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
    + H" X: `3 _/ z  l% S
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */
    1 @* E# n+ U/ f# p  j) _# A
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */1 u% s' s; C. n/ u/ m
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */5 [+ X3 @/ g- g$ H) Z
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */; Z, i, d4 }6 z) s. b* p0 J
  24.         $ w0 O, I& A% J6 ~2 y
  25.     /* 添加数据到TX FIFO */
    2 O. z' w7 h" E6 V
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
    1 d) Z! }$ `+ I
  27. }
复制代码
% i# `/ T8 t9 y+ z) b9 T
91.4.8 函数HAL_FDCAN_GetRxMessage
* x( D: t, Y' n6 V) \函数原型:# z; [5 b3 x7 ?; l! d
9 z3 ?1 M  T" r- D9 B
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)* ]+ u7 I. I2 o- @0 {/ V4 X  G& p
  2. {& S) K7 N* H, O( p+ Q
  3.   uint32_t *RxAddress;
    4 x6 }# M! y4 k; }6 l
  4.   uint8_t  *pData;3 w8 X8 P, c6 ^" N
  5.   uint32_t ByteCounter;% d0 q" R3 }- j3 v
  6.   uint32_t GetIndex = 0;9 {& u* J7 S; f. m/ L
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;' B% b3 Q, ]7 B0 d

  8. 9 z3 B3 @. U- N( g
  9.   if (state == HAL_FDCAN_STATE_BUSY)
    ) h+ O0 d4 O- P: M7 k. a! h
  10.   {
    9 p4 d- j" @6 _5 p
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */7 G% e% |# k2 y0 N" ?" g& [  I) T/ K$ q
  12.     {
    ( o0 c$ E& M0 }. E- n2 F
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */3 f7 E  p' w# m& w- y+ j
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
    ) n/ @+ k9 O( i' b2 C* g
  15.       {
    3 Y' Y* ^" F8 h( n3 x0 z* O
  16.         /* 更新错误码*/' p' C4 j' M1 ?! a4 T  W! _
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    . {, d0 r* [/ f, _! y+ X, H9 h
  18.   n4 t+ q* }  W; j
  19.         return HAL_ERROR;4 n* _/ L  l6 M2 L, [  ]( i
  20.       }% v6 r* K# q4 z% g3 w

  21. + @: O& ]4 u0 a! W8 W
  22.       /* 检查Rx FIFO 0 非空 */
    , C6 c1 p% w7 {$ @4 `
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
    , @  D+ @5 M3 k  R4 g- K1 o+ ^
  24.       {! {( Y4 M5 }. y! N/ l
  25.         /* 更新错误码*/
    / U5 u- Y+ ^8 h& ^  E9 s
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;, V& G# g5 z) ~/ t1 X. {- l* f
  27. , I5 m/ @' N0 o- R0 H
  28.         return HAL_ERROR;
    7 N- o, ]! n& m7 z8 x. Y5 E- v
  29.       }9 z6 z; h) x, r8 D) W% t# R
  30.       else
    . D) T" Q; ]$ U% O  [
  31.       {
    ( W. y0 P% D1 `7 j/ G, I. W
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */1 E: R! b" Y0 u
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
    + |. k2 {- _4 U+ \; Y4 b7 k# |
  34.         {1 N$ Y  b8 K: D* i5 J! z
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)) h. t: T( o* v* j9 U! m5 m. I0 y) w
  36.           {" R( i# A6 a1 n
  37.             /* 开启了覆盖模式,丢弃第1个数据 */6 m6 ^  M( N9 l' T/ k
  38.             GetIndex = 1U;
    / }; P& K" @# T# Q: f$ a
  39.           }# K3 X' C* k( E  I
  40.         }
    4 |/ h4 m3 r( m* m% ?6 D; y4 ~' ^
  41. , I9 ?. B2 Y+ h; k% S
  42.         /* 计算Rx FIFO 0 element 索引 */9 S2 v! P4 E4 R$ ~4 o2 ]: F: H# ?
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
    / b8 S( M, |  \( W; F0 q7 N' p: X; m: I
  44. , E; `4 E; |  I- i8 f
  45.         /* 计算 Rx FIFO 0 element 地址  */  P, ^$ ?' `  y1 }# O8 _
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));2 s  R' y# W/ u9 q. w+ [9 n
  47.       }2 T  @) ~& w! {" L, s
  48.     }
    " T0 p3 O5 E& z* l. W. R
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    & L/ I0 A8 L& U- c- A% q
  50.     {
    9 f) |$ P) ^2 x  g2 E
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */
    9 U) B" Z3 f# _: d9 w: h
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)8 J/ K* Z* M2 s6 |
  53.       {
    & n0 o* d! e  l0 `% w- }2 I" z
  54.         /* 更新错误码 */
    * X$ K6 \" N# l1 {
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;% Z$ z# G3 v* M2 U" b1 x, p

  56. ; h0 x9 m! i+ Q% P* `! H$ C, ]& w7 m
  57.         return HAL_ERROR;
    7 n+ X/ P. V5 `' k
  58.       }* B3 A) g- N$ w1 s  k
  59. 5 P5 J( w2 b7 A3 [' p/ M
  60.       /* 检查 Rx FIFO 0 非空 */2 h* p) J5 x7 X' O8 n7 Q; c
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)2 ]5 A7 v% z5 }) I1 j3 s9 l
  62.       {
    ; m0 y$ p' Z. U; ]# e
  63.        /* 更新错误码 */
    ' s1 O( C$ f+ i% c
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;5 L( F+ A7 r2 |' `0 u. c' y

  65.   B% H% \6 _. U, H
  66.         return HAL_ERROR;
    & x- ?+ e6 K8 X2 a8 j
  67.       }
    ) D% n, }0 D8 p0 A+ A9 g
  68.       else6 K  t1 Y  P7 U& A5 @4 A( \
  69.       {
    : C2 k7 ~/ j/ [! U% `
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    1 E/ ^1 K1 {# a  H; U+ T
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)1 C1 L9 Q+ K+ q& K7 m- ?- [& ]
  72.         {
    1 ]# S: m' A) V5 x
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)8 Z7 P0 p( r3 c( N1 T% M
  74.           {
    / a: _1 H. t& ~
  75.             /* 开启了覆盖模式,丢弃第1个数据 */
    0 n% u2 @) {. s. ?
  76.             GetIndex = 1U;
    6 C$ C8 E5 }  F7 g4 p
  77.           }; q  O  D4 E$ L& T( e: S
  78.         }+ d4 ~7 U# G8 {5 _- m  o
  79. 6 v- A, {* {+ o3 ~; D0 `3 v
  80.         /* 计算  Rx FIFO 1 element 索引 */
    & X8 L, V  v# J! q9 K6 K1 H# J
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);2 F" D0 Y/ A0 ]* t7 \
  82. $ R1 a" x- z2 Y* D$ U1 O4 h
  83.         /* 计算 Rx FIFO 1 element 地址 */$ o0 \' H) H. V( E
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
    $ c% u, _% L" u% D* S
  85.       }
    ; _' t8 T3 O& X1 ^
  86.     }
    ' c7 D3 j  M# X0 w
  87.     else /* Rx element 分配了专用 Rx buffer */" n) R5 g& L3 |) t; b  Y8 G
  88.     {
    4 S/ o2 I% Q5 }/ [0 m8 J3 v
  89.       /* 检查选择的buffer分配了RAM空间 */; R% i$ n% }7 \( G
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
    5 @- A. O0 V- A1 }5 J
  91.       {5 K4 q6 g8 _8 O
  92.         /* 更新错误码 */
    % R$ D5 h, D% ?7 \
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    # B4 J9 }& v2 D4 y& q
  94. 7 ~+ ^* _& E* O
  95.         return HAL_ERROR;; L4 Q9 G% h  T" s- G+ b2 p. {
  96.       }
    ) N' ~2 \8 `: p8 j
  97.       else0 m( L6 y5 y# K! N
  98.       {. c" S: l/ @% g) s" P7 T
  99.         /* 计算Rx buffer 地址 */
    : h2 {: y. \6 u6 c5 C5 \) K
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));0 r! n9 s! L6 q
  101.       }
    5 w& n- y# D2 P! q+ Q8 D5 O' z
  102.     }
    . d) Z1 l" @8 G8 R! c- \: P6 n; d
  103. 3 d7 Q! n; J+ f1 f1 o
  104.     /* 接收IdType */# [. S7 v# B) d: H0 V- ~( Z
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;& K7 i1 T$ M' X- P) e, Z
  106. 3 }# d$ F3 P/ ~
  107.     /* 接收Identifier */
    8 i0 f5 f' p" H4 T
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */- W. N8 c2 Z9 L4 v& N
  109.     {# t7 R! k6 G' _0 E* K' a
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);7 O+ S1 v  H# V; o! w! ?/ H0 ^
  111.     }
    ( G5 K; i  E9 y3 @. P
  112.     else /* Extended ID element */1 G7 @! i) u& q
  113.     {1 m9 E( W5 ~* v
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);  L* v8 g8 m# k
  115.     }5 J4 P3 }  G% Q" Q, V1 k
  116. 7 H+ g8 F) }' L0 h+ o
  117.     /* 接收RxFrameType */
    5 n7 u5 d7 X: I: D$ I  V
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
    : K3 f/ E. W! ?5 A) ^2 X1 w& b
  119. & e8 U: m$ n# ~, Q* Y/ h
  120.     /* 接收ErrorStateIndicator */
    : y3 n7 A$ v9 Q% N3 W9 ^
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);: G+ g8 a9 r* z+ ]5 R+ c
  122. 5 s. ?  F9 f* @7 b
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */
    & c5 d6 m; M4 m9 I5 g
  124.     RxAddress++;
      H7 u4 C! z% f1 B% V, M6 m( {+ `
  125. ! ?5 K, q$ i- S! A, n9 }4 p, U" m" o
  126.     /* 接收RxTimestamp */
    $ I! P4 i" X& g1 }% I1 x# ?
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);
    " B% X: ?; n: _4 \3 D
  128. $ N8 T4 q8 ^2 i9 d9 o
  129.     /* 接收DataLength */* b( c# J  k& E2 v  ?* i7 ]
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
    9 \- u, S. L/ w" d6 P
  131. 1 S0 A1 O; ~1 ?+ k' X
  132.     /* 接收BitRateSwitch */
    & D6 ^, M' i* p
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);6 p( s) i; u8 B/ Q. ^
  134. + L, `; I+ x+ `3 O" K" o! v
  135.     /* 接收FDFormat *// A! u+ d8 f- S4 w, }0 N( k3 U
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);3 X2 ?8 n# y* h( i6 `

  137. : Z8 ~7 c( O) m" z& P
  138.     /* 接收FilterIndex */
    2 U5 [( {8 v1 r  g! z& f
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);- i" m# }6 I& {, }3 V$ w8 G9 A; E3 ^5 ~

  140.   N. i* F3 j. v, I* {/ e
  141.     /* 接收NonMatchingFrame */
    - K" T' [& W! z  m8 |
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);/ f% {) S/ v7 [( x- z
  143. ; X8 z' W* a$ i( K
  144.     /* 增加地址,指向Rx FIFO element的payload */' R+ O1 }$ [% _4 i& v9 g
  145.     RxAddress++;, e) q6 O3 @0 e1 N- Q0 d& Y$ x- }
  146. % S4 m9 N" I: {3 E& k6 d) R( A
  147.     /* 接收 Rx payload */
    - m6 ~. p0 d! \* ]' W5 p0 B
  148.     pData = (uint8_t *)RxAddress;4 K' h0 p5 p, q5 K5 M8 y
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
    1 f- F3 p$ L4 g
  150.     {
    2 n5 c6 D2 j4 F
  151.       pRxData[ByteCounter] = pData[ByteCounter];* L! k8 ]; C4 u1 J( ^/ M' G
  152.     }
    - I! W3 i# }) A5 w, y+ G

  153. ; @7 j+ @  S  T8 M# }0 C
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
    : `$ R9 q0 M7 E6 A+ z4 d
  155.     {
    ' g+ \9 M3 e! o5 B/ l) n
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */# y9 _0 g! k# n7 `
  157.       hfdcan->Instance->RXF0A = GetIndex;
    1 e8 |" L0 d; p2 F9 A- o) q4 L
  158.     }( Y! `1 t. }3 V8 a8 q
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */. Q+ \6 G$ {# Y
  160.     {/ k5 f, K  P# ~3 G. ~0 B) l" A6 d
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */
    - ^1 B# Y* T5 P6 i* v
  162.       hfdcan->Instance->RXF1A = GetIndex;
    " I7 H& j9 u' b* U
  163.     }  w& D4 @8 K5 e6 u/ [+ T4 Q9 r4 o
  164.     else /* Rx element is assigned to a dedicated Rx buffer */7 k4 C) |6 M4 K/ i! R% I
  165.     {
    1 e. a6 B/ w0 B3 k  G2 G6 S' B( b. j
  166.       /* 清除当前Rx buffer的新数据标志 */" R- u9 ?7 T  d# @
  167.       if (RxLocation < FDCAN_RX_BUFFER32)" N% l( A# [4 a- v
  168.       {
      N, e' g4 d* _' D2 r) t8 A- ?9 [
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);) s; y# {1 s" N6 E! y6 M* k
  170.       }
    4 A$ ?. f3 A" x5 ^8 p2 S% }. x
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
    0 Q1 ]4 ~+ k9 c
  172.       {
    ( |9 n* V( P/ f  G' [; j
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
    8 v' b9 @' T1 f. G, l
  174.       }! P4 o: ^& N1 v0 b
  175.     }7 u  A& s* @/ {7 C* x

  176. : k  u4 C0 B  y/ r
  177.     /* 返回状态 */- F9 j6 ^& G% K& |& k) ?
  178.     return HAL_OK;
    % a" L' e# F/ o& q1 U5 S
  179.   }
    / M9 N& s9 v+ M
  180.   else
    5 ^0 i5 N  ?- K4 x* O7 ^7 N, F
  181.   {
    * e/ ^2 E: C: g2 B
  182.     /* 更新错误码 */
    / X" ~& d4 x9 B2 x4 b
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;& y( t4 I% Z( H* P) d

  184. 1 ?" ^% }- A5 `3 X( Y3 l1 _
  185.     return HAL_ERROR;5 s; r$ S% a6 n: e2 `
  186.   }/ t$ K" b9 ]3 h) C5 v: p3 z
  187. }
复制代码

  O3 }9 s1 z" _* i, r函数描述:
$ X9 m1 L  I8 m* P' r* F* N) t2 E% |- F2 Z* A
此函数主要用于获取接收到的数据。, E# S) z3 n; ]0 R
" ~6 S) Z4 m! ~$ [
函数参数:8 ?+ y& F& }( k" g
+ B1 T  n4 G1 ~; E( `
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。3 l- c! f. Y2 D. ]& e# t- F6 e
  第2个参数是读取位置,支持如下几种参数:
6 ?' X- {+ g) ^( f; X
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
    2 w' H3 X) _: |$ Z) \
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
    % `8 I8 i5 U7 A! m0 l& Q
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
    % ^5 C3 y8 I' a' \. S& B$ V
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */% Y1 u! R. c( s
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */
    - A" g: D1 f- ?) Z5 x
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */
    * q5 J  e) V% u8 c0 P/ w
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */0 E- Y# R8 q0 F5 y
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
    5 B9 m! O5 s; r5 C
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
    ( k4 i% r3 {/ J
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    6 l$ u8 ]; I9 n. f- u
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
    " O- C5 Q% F1 ?" q9 v
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
      Y0 @) `' `9 s" z, b# S6 |
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */$ D: `7 p4 n) }3 W
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */6 X2 }: i. j& Z  B; A
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */- p7 }9 N9 |# n( b. n9 s, d
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */1 n. p! m# O" r9 j, u
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */. y1 p( `4 U/ C8 E  E
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */) {: R6 F$ q% V: Z1 L
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */0 {2 O/ {. S: c. L$ N; o
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */
    & z9 x6 d9 I: u! k6 ?
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */  e4 D% D3 I6 J, K' X8 P/ [9 b9 n
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */$ C* I+ @# V5 Y! e: P# ]/ k
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */$ m7 M5 Q' e- a
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
    9 e" T5 J7 `! Z; [3 Y4 p" o
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 *// a  z* P! I& k
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
    9 j$ B( T) H7 p2 k0 s2 {) b# B
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */
    2 L2 u9 H) `2 Q8 [' h
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */- o! L+ M3 E6 s5 o8 U3 }" z
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
    + `7 M/ c# @5 o
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
    " ?& r  {7 h, J, \
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
    , o4 b, A# [" H7 s. F8 j+ w
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */4 A- ?7 G; |; T
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
    6 T" a; E' `# j! \+ \, P
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */; W) ?) Z( e' B! K& m
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
    1 I% \# H0 V5 `: i- U
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */3 [# l0 v# i8 K1 u$ t+ J7 O
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
    . m0 e$ V' I' f" G# l
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */: H8 z7 [, Z$ e6 I( G) a' m+ q4 h
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */. _0 O0 f+ f; R; a1 d+ W
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    & f/ r, m% @" F7 s2 [
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */: v4 a9 `- k: _2 L- \9 X
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */0 P: r5 q0 E) h- e8 w0 `! ]- }. N5 j
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */6 L) y+ i# w% y' G
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
    4 m# |. X5 ~6 z, N/ o2 R4 s5 ]% Y9 y
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */8 ^, X7 T+ @0 o: I5 m; ]
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    . ]/ U0 `; O/ j# P1 W
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */2 _, B2 c: L6 U! P
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
    4 |4 q" l. m2 z* S- \# n6 a
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
    6 \3 [( C4 f; J' }
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */2 \) {/ Q& P% k
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */& O, a- X5 D* s& g1 K5 D/ s' Z. {
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */8 F9 A/ E% F0 O. B1 i1 b, K& [
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */) R8 z' `4 L) |2 H5 }4 ?, d
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    & q1 ]! ?2 ^( i! u2 Q
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
    $ B* K8 L" U4 K( a
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */% h* M5 x8 D& O% w' D/ s1 C% X5 ?
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
    ! m# W+ t/ y, |. G* a0 L$ d3 C
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
    " `0 U7 ^  ^1 ~. r) x0 E
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */4 H) F4 E  [$ s4 g" M2 k$ R1 {3 D
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */- y# O9 o# J2 p# w% [
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */* N8 q2 F1 E+ l' D5 ]" u4 b
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */5 A3 n% S  x* b4 k, M! S2 e/ \2 u3 f
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
    0 Y7 C# n5 @8 g' j' T5 [# S. t  q8 V
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */9 R$ I) h. S2 ^+ W2 q% k! n! C# |" _
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */) s& d' A  x$ r* _. Z  u0 J
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码

; b8 `8 \+ b% i# A: X/ _. v  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。% l) E, N2 V# w) n, F" Q9 k
  第4个参数是数据接收缓冲地址。
5 Y" a) {1 _9 H7 @, V  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
7 ?: O  w* Y" u. _9 ]8 p2 [( f. j使用举例:2 {) c" u( N- J3 B0 Q+ Z$ K7 a
& [) z2 v: i) D" e) h. k1 V
  1. /*
    5 c+ K, h% Q, f! T0 E
  2. *********************************************************************************************************  L0 w9 |/ a8 @& p
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback) b9 i& H1 W% o, x$ f
  4. *        功能说明: CAN中断服务程序-回调函数
    / a) v' Q3 o( j6 V, E4 m4 ~
  5. *        形    参: hfdcan
    $ d9 K4 `# c+ Y1 y% t
  6. *        返 回 值: 无
    " {1 \: h3 |) {9 l( `
  7. *********************************************************************************************************
    5 ?1 i: Q3 _& l7 A
  8. */9 P! |( @+ i; G( g; w
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    # m/ U' r0 R) K3 j) K1 e" p4 A/ k
  10. {% J* g& N; e+ x* x" E% b$ N
  11.         if (hfdcan == &hfdcan1)
    & Z: H9 t  j& l% t+ L$ f& ]. G
  12.         {
    . z( e" T% K, Y% I$ Q9 V9 G. w+ x
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    5 x( p" Z: C! U8 ^9 n4 y
  14.                 {
    . F$ ?4 }7 A4 F# U& K+ D7 }
  15.                         /* 从RX FIFO0读取数据 */
    " ^  @; u, q- F
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    - Z  g' Z! n: m4 m7 E" ]

  17. $ b* `# w% P8 q8 |1 M6 i+ f" U
  18.                         /* 激活Rx FIFO0 watermark notification */: K: y5 H- D( n- L- ]8 ?3 z2 c
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
    7 F# ], d. f+ e7 O" F+ g
  20.                         6 L* d. r: I8 p3 E
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)( j% E  K' _6 C( w# N- o" X
  22.                         {
    " A* r- @6 N9 U" V
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */. R( C7 X, c/ z! x2 F, N2 }8 u
  24.                         }, G% Z; a6 G/ P& ~' f
  25.                 }
    , o7 x: ?4 s; P5 b
  26.         }+ j$ H" c/ @0 c$ B6 t' }; a+ N+ H
  27. }
复制代码
1 G; |+ h* B, v: G; N, ?/ M
91.5 总结' |* P: n5 P4 e" T/ k0 y$ N8 y; U
本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。9 @/ q/ y. j: \" q) a9 y0 }/ E; k
0 s7 @9 B' I: ~4 l
1 Q: ^! s+ A0 A! `: n7 M7 g( S
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

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