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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示
+ |* s7 C9 p- A4 L; n  FDCAN基础知识点可以看第90章,已经进行了详细说明; @) [" k' P" ]8 {' G# R" _. ]) C
  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接
$ w+ u: P) z7 }* Y0 f( J* _) A91.2 FDCAN基础知识
% h  `3 b9 y2 EFDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。
. f% E; |' n7 X& T4 J: w4 c6 o. j
; ?( d5 H' X$ g+ b8 u$ e; _91.2.1 CAN FD协议介绍
0 @, L! L7 v! L# f% [. o/ USTM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:4 K0 t) S( I1 |

2 t( K* t$ `3 V+ g(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
. L1 X: L+ Z$ e' u  _2 h- t1 ^- R
(2)可访问的10 KB RAM内存,最多可分配2560个字。
& x' j% H. l7 y% l& ?/ U0 l: {' K% z
(3)改进了接收过滤。
' S& T/ L; c" d5 x& P) @& p$ `: P9 X
(4)两个可配置的接收FIFO。" L* W; P* Z) m" b! f" X

" M& K6 x4 s: f: Q% k/ K; E(5)多达64个专用接收缓冲区。
0 o3 r* p. p8 Y, y4 ?! L& C; u2 h, ^0 s" `" b. w/ I, _( b5 M9 `
(6)接收高优先级消息时的单独信令。
0 W  f, H8 N/ g  V2 k: {  {. c  a5 k9 Y4 M; W
(7)多达32个专用发送缓冲区。: I* K- a3 o# T9 a8 i9 V8 ~" i% |* B

, W0 B3 s7 g; p(8)可配置的发送FIFO和发送队列。$ Y' T( q7 q. m, m. T
  I/ D" t; g& x% |1 f: A
(9)可配置的发送事件FIFO。, |: S+ M% J& U

1 g1 {3 o% J8 _" [. t8 B(10)时钟校准单元。5 a/ w) C6 x' M9 Z+ c* N

6 Y8 ~8 y+ u: o% Y(11)收发器延迟补偿。
4 h8 L5 p% b/ O/ I3 e0 F3 Y4 m8 y& t$ d) ]! N# e( Y5 J9 W! A
下图说明了FDCAN框图。
  u2 U7 c6 }& ~
- f& M( B/ \5 V
' M' G# Y2 G1 T: U4 G
f4f1d5cd872648458911e8be8ddfffe0.png

$ v3 r9 |# t* j, G1 A' J
' ]& F, C* q/ [. H- F9 k3 a* {
* r0 R% r  K- a$ s0 o通过这个框图要了解到以下信息:
) {: c# |6 p$ x; L# g( |- J4 j- b; d# F! j* l
(1)CANFD1和CANFD2共用一个RAM空间。
8 }6 q. \9 t3 X  @1 ]
1 A* q! M9 I1 T% \8 x. W+ ?(2)每个CANFD都有自己的内核。
' Z* {) w3 p6 r3 Q4 B7 A& c+ K* I
(3)CAN内核实现协议控制和收发移位寄存器。
, ?/ |3 A6 v+ {* G6 K# {0 g1 G# ^; e$ J0 _
(4)Tx handler控制消息从CAN消息RAM到CAN内核。
6 ]; g. Z+ Y1 H6 V
; k7 [7 G7 V0 N' c4 c(5)Rx handler控制CAN内核到CAN消息RAM。
) J" R: {* c. m% @6 u# X4 Q4 n+ f- O# ]8 ?
91.2.2 CAN FD特性3 R) x! |( n: Y6 x
(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。6 q& \8 Z/ y  [% q' K' c

, n/ Q- J+ D% X. w& w! j# v7 L(2)提升错误检测,支持高达CRC 21位的校验和。
1 i! _) @& T% [3 m1 s( X& p4 ]2 ~
1 h8 h1 H# e6 Y3 A/ Y(3)消息优先级。
) \% O' ]* K, E* `' v: p7 U, n% W% M/ B# k5 c+ n
(4)保证延迟时间。
/ ^$ L, u/ [/ P0 A' R. I8 {2 c; p& J
(5)配置灵活性。
5 g( n6 j6 e) U3 b
6 r0 B' ?7 M3 r9 X% P(6)具有时间同步的组播接收。$ b6 R8 I8 w$ t6 S3 p

% X7 i4 q$ e& Q! ]  V" O$ @(7)系统范围内的数据一致性,每条消息最多64个字节。
1 {# _0 g, n) K" o0 R4 H; ]3 s
" _7 U+ R' g$ V1 j( Z# ](8)多主机。
( C( L) m( q5 @0 G9 L6 y  `* U% c% O" s. F" r8 m' \* _
(9)错误检测和信号。3 Z8 M# v) Z/ `' {5 M: E4 B* O* L
9 r7 q2 N0 U1 n% N
(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。9 I8 S, ]8 p4 ^; @& O

# s/ W, _8 i; K: t; c7 P: X( T$ C1 Z91.2.3 CAN FD格式
. u1 y- o" h0 [6 J4 J& L: Z
  W! {# z6 ?$ G; t" L
c692adda5a1149b0a6e3d8a30745fd62.png
9 N- n5 ~; Y  ]7 Y+ r6 x

7 H4 ~* e$ J% R' G
& E  ?- j6 B, G7 Y; B第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:
3 K3 P( l0 }7 h9 F
7 F2 e; t, j3 v% X5 M* N& y. ~% u(1)帧开始(SOF)。+ `" z3 J, I+ h. A- ]

8 M$ \8 Z& i' S8 P# ~- {(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。8 _- o* Z1 y* r) }. T& r- i, `
6 O! C: |; T* l
数据传输阶段(The data transmission phase)包括:: n! D% j6 m) ~; W9 H4 h

% c) p& a! v. U' G(1)数据长度代码(DLC),指示消息包含多少数据字节。- c6 I, c% }- [: A& M8 u- R
9 R: D# }+ b5 O# j7 d; H3 ^5 }# w& Z
(2)用户希望发送的数据。& ]& ]# e! o# R# r, m5 {& H$ e* x

6 m" ^7 v4 D" k8 c2 H(3)检查循环冗余序列(CRC)。
( f1 c0 w9 u/ N, H/ o8 K: G
( \8 g8 `9 n8 w& Z$ M9 ?, k: \(4)显性位。
" k& {) G5 O1 b: X) J% ^( V% Z0 v* u6 r  J; S/ c& |
第二个仲裁阶段(The second arbitration phase)包含:3 y" W: R! t$ X& w8 K
/ W: w4 W& @* ?) H
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)
+ ~# v2 n% u6 i5 t- f% ?
  `  v* B5 n6 M& p* ](2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。! B, C$ v5 \+ ^" |* o7 v6 s: b. }

8 X9 `3 Q6 V- P- A% h. a' s注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
. r4 m2 n, `3 T- ]1 N: y2 K! w" R* Q2 V" [7 l+ A0 B( v
91.2.4 CAN FD相比CAN2.0的提升9 O8 u1 S: v' T3 B7 o+ t
CAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:
$ T1 g) ~0 N7 W6 k2 n# B
4 @: s7 f; T5 p6 R+ p9 g8 v& D3 w(1)17级多项式对最大16字节的有效载荷进行CRC。* J7 `7 v* z& i5 ]" }

+ R4 R/ E8 ?- M. u' {" e(2)21级多项式对16到64字节之间的有效载荷进行校验。
3 h- I5 N* H! c: y4 r5 h" N# D# L# k: z: x
标准帧和CAN FD的区别:% B6 c( E: h# |% M! i6 s
2 M8 X3 n' J* c% N' {  S( J

% \2 L9 j$ ?3 N) W8 f5 F' z2 B
050433e4b8fe4f4d91de7eb85d5e6bdd.png

$ q  y  B7 y. h+ u& q/ z% @7 p0 a9 Z9 S4 e9 @5 D; E
! v$ J7 q% K. ~7 M7 J6 m
标识符后,CAN 2.0和CAN-FD具有不同的作用:5 B! U: @2 M# d% C% W2 p: k

' [0 ?0 Q! w8 m5 \- I- L/ v(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
9 b! u  {* _6 `" U4 `) H2 m$ t. r+ ], k! t, A1 B7 l2 e. F* I
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。& }1 J  V% W" l3 ?+ e/ x3 U% s$ P
  f8 x# f6 B$ f% _: w# `
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。$ P- I! S$ N6 H0 ?
2 f" E4 r0 ^; {1 U! I, u7 K1 E6 b
与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:  z" }- N. f" f( I( v
( s4 o5 O8 U" P: [
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。% j, O& k; c; H8 b4 }. G: F8 V# l" S
3 v5 [+ I  ]. R/ Y! G
(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
3 k2 W' l  G$ h9 P* P, [4 S+ f6 m; C: n" u7 a
(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。
5 x$ w* Y  s" p" c- ?, @- z' R* e7 i, Y( k
控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。
7 x* ]6 d( p1 {2 x' f, _4 ]. Z. S* r& k
* P4 l% f8 W3 s8 v0 G* ?# ^
c4fbc9fa3f184422a77784de5280382d.png
% v+ `4 f9 V0 ~" X
4 o2 H2 o( P' F5 M8 i% g. }/ Y
+ k9 G' o% v: e
通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
, i$ S& c! M/ k; ]/ |; h: \) W1 T+ p' ]6 t
(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。! R! c0 B% N! D6 A& Y

. O: z9 X" V, g8 Y: ^(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。
8 B6 M; ]/ W8 g, e) Z3 f) y$ {) |, m  ^4 i) I4 F
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
0 `; f( y: ]" s8 S7 W9 E5 \: W1 L. S1 k6 r( l* k

+ P; a. S2 z. K7 v6 x  ]# m
a00dca8056bf40dc860b52366afa5197.png
, d, v% r' K: b$ e3 @4 p) p
3 E/ o3 {( w" {) L' @1 K' S$ r. G: z
! y5 p. p' `. E8 F2 ]% R
91.3 FDCAN总线的HAL库用法! G! ^2 n8 \  c& @, X  l
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef
. M% ~- E4 w3 M4 u: eFD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
+ r! m" l9 {% \- T5 \% u: G4 H! E, o# l8 Q+ y
  1. typedef struct
    * H& k- v: f$ C8 }( N6 e3 O9 B. i
  2. {1 w, f, A" x9 f
  3.   __IO uint32_t CREL;   
    9 `0 C1 T6 E  E
  4.   __IO uint32_t ENDN;        
    ) N: |# g& R# Q; V
  5.   __IO uint32_t RESERVED1;    4 O) G4 u0 ?4 m3 r$ {# o
  6.   __IO uint32_t DBTP;        $ k( _( o! J: O) P/ A: o
  7.   __IO uint32_t TEST;        
    4 N6 X( f0 S1 q" M/ Q3 a# C
  8.   __IO uint32_t RWD;         $ n/ }/ I! ?9 f
  9.   __IO uint32_t CCCR;         
    $ b4 x3 |+ o, e& N3 W6 e( m/ ]
  10.   __IO uint32_t NBTP;         ( M+ B/ c% B. r3 g3 u
  11.   __IO uint32_t TSCC;         + a, U$ n* U8 N( \
  12.   __IO uint32_t TSCV;         
    0 q$ u7 |' D/ y1 b7 J6 o3 q8 X
  13.   __IO uint32_t TOCC;         
    + ]$ r) ?! R* @" o1 k
  14.   __IO uint32_t TOCV;         
    # ~6 R  [% g: J$ |
  15.   __IO uint32_t RESERVED2[4];
    * A  v0 g2 U4 L1 v- t  ~8 h
  16.   __IO uint32_t ECR;          7 Y/ n' M1 N* y# e' b9 K. W; S
  17.   __IO uint32_t PSR;         
    8 y# @- T" ^; T' v4 M4 j5 M
  18.   __IO uint32_t TDCR;         
    * A" P6 f) r( M/ h+ {; d5 b
  19.   __IO uint32_t RESERVED3;   
    2 P9 T$ n: \3 k& {, {0 R
  20.   __IO uint32_t IR;           
    ' `8 f. O8 m" @2 i7 V1 F
  21.   __IO uint32_t IE;             i& b( H& u# D+ v  i) D( m4 x
  22.   __IO uint32_t ILS;         
    # k9 U( b5 O) v9 z
  23.   __IO uint32_t ILE;         
    1 Q, A6 _6 _  a) @: G- S
  24.   __IO uint32_t RESERVED4[8];
    8 Y! M& {' c& f, p; c$ g5 B
  25.   __IO uint32_t GFC;         
    3 s6 i) X3 I. [0 |! h
  26.   __IO uint32_t SIDFC;       - ]# @+ L6 n3 h+ U! l, e5 X
  27.   __IO uint32_t XIDFC;       - }7 A! d" Q9 o2 Q( _( |0 B
  28.   __IO uint32_t RESERVED5;   * {% X( O& u( b- X3 m& P" V
  29.   __IO uint32_t XIDAM;       ' u6 x$ d8 E1 ^# |
  30.   __IO uint32_t HPMS;        
    - v9 S7 n3 s' i$ [$ Y9 o
  31.   __IO uint32_t NDAT1;      
    / i, d2 n/ S* }# \7 j5 J  U% B
  32.   __IO uint32_t NDAT2;       , F4 k. P. f5 z& M* J
  33.   __IO uint32_t RXF0C;        
    $ h8 B- ^% y1 B- s! G8 M, I. W
  34.   __IO uint32_t RXF0S;      
    % f" r! }3 A8 {4 k9 h
  35.   __IO uint32_t RXF0A;      
    0 }" j; S. y* B
  36.   __IO uint32_t RXBC;      
    + n9 Q2 V! l$ h! `  G
  37.   __IO uint32_t RXF1C;       0 V* S* K! e5 N/ K
  38.   __IO uint32_t RXF1S;      
    2 e1 c& v8 u. V
  39.   __IO uint32_t RXF1A;       ; Q9 J0 N& B. G* H
  40.   __IO uint32_t RXESC;        
      T9 {( F" y) K" v
  41.   __IO uint32_t TXBC;         
    4 Z: r! d, j6 @. B8 d
  42.   __IO uint32_t TXFQS;        
      Y- A2 ?& Q8 k0 L
  43.   __IO uint32_t TXESC;        
    / y! e9 [4 [- R; F5 A$ Z
  44.   __IO uint32_t TXBRP;        & Z3 X) U- o4 ~. U9 K
  45.   __IO uint32_t TXBAR;       : p0 c, A+ i/ B1 p3 `4 n
  46.   __IO uint32_t TXBCR;        
    4 G5 S& [# Z+ T+ u' y: M
  47.   __IO uint32_t TXBTO;        
    9 b) M2 a$ I3 `0 D  Q9 J/ k
  48.   __IO uint32_t TXBCF;      
    ! J6 S9 C/ D0 N" d- S3 Y
  49.   __IO uint32_t TXBTIE;      
    9 I* y) U0 P: v( p$ ]4 g9 g  Z
  50.   __IO uint32_t TXBCIE;       + Y: F! x3 |5 X2 ^
  51.   __IO uint32_t RESERVED6[2];
    6 w& B  V1 D" K( p6 `
  52.   __IO uint32_t TXEFC;        ) l* r, S4 a% Y( L7 [3 P, W! o
  53.   __IO uint32_t TXEFS;        
    7 N8 H, _) W: v/ }+ d( _
  54.   __IO uint32_t TXEFA;        
    / z" E& g" Y- O- n; q* Y( U
  55.   __IO uint32_t RESERVED7;   / p2 Y$ |/ p/ M- W
  56. } FDCAN_GlobalTypeDef;
复制代码

$ ^7 Z& R( {! [' ]* f+ S这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。4 o2 ?3 O- @2 s  `1 T

9 c. v8 n- m+ T: N# B- `  ___IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
6 s1 A0 \& g5 q, r* L; M
7 s$ i/ ?; ^; }" P
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    ! v6 r# }$ E4 b& _5 g( u( i% c( x
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

1 ?4 ~% P* S9 f! `) [下面我们看下FDCAN的定义,在stm32h743xx.h文件。
- H; l0 A' r% m* B
8 h9 {8 F* l4 S
  1. #define PERIPH_BASE           (0x40000000UL)
    / j- B4 H/ [9 C% `( |! |
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE% r8 f2 b  U1 S4 f) e
  3. 5 r& L8 r$ A" R. y) q
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)
      b8 M  j8 N5 }/ `# P3 u; \. c
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)" w: M3 o$ E7 u, Q
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)
    % q9 b; r+ I6 U/ _

  7. 8 E! u$ L8 ?/ @% ~
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000. N( _" o4 B0 }2 B% {% H0 B' U
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
    & X0 P+ {( {7 W: e  q6 P; E. q
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码

( z* r! m7 k& v我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。9 N: [# L; @" j) `! z2 n; T/ r
2 K1 Z( i$ Z  Q1 y! ~+ J  M& @
91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef1 n2 q- Q5 C( T( t' B- F
FDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:# X: R  c* w* Q5 }6 M# e/ x' u

3 g  E* D7 G5 ]
  1. typedef struct
    ( p0 u7 s$ b( b7 L' ?
  2. {
    " d6 M% ~- J6 i; y
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */
    2 w3 y, j. A. \  M& D
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */* t& J3 l' n. i7 @
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */
    1 L' y/ ~& J4 b, x& K4 a- P3 t+ J
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */
    1 k9 @+ S% `: A9 {
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */. D1 j; o: Z9 k" U) J. `0 t* e
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */2 u9 Z0 a7 V! L$ T
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */$ I2 g9 N' q3 X
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
    * k: C  N0 }2 G  i
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */4 [6 I/ n* ^8 y& g5 V; ^" f4 b! m; g
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    1 O: F: h4 Z/ o& L9 Q7 B, A
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */
    # n) ?, `: ]; z% ~
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
    ) u" k% a: E! y0 `
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
    $ p: q3 O- h+ T0 t+ a  L+ v2 e" S
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */
    * n8 K" p: K  R5 h
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */* d1 `2 s* i! A' y: t1 ]( ~/ g
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */  J* e( F% Z& l; F
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 *// i. Z- A9 A* N2 @
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
    / i: ~  ~8 {2 G: H9 J4 Q4 L& ]
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */' s. u  s& W9 @, }
  22. } TTCAN_TypeDef;
复制代码

3 k( D' L, m# L2 ~& V  \: j, C91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef; c  z9 ]4 Z9 `; X. X
下面是FDCAN总线的初始化结构体:
, V2 M- t. v0 z' ~& i4 Y% h/ Q0 Q+ s5 }6 E
  1. typedef struct
    $ {! Y  @6 X' F% a) {
  2. {
    1 {4 H5 B3 M# ]  b% ^& F" t
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.
    9 S2 l2 S1 \/ T: T
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     */; G: h/ k" r5 A

  5. % \: R6 ^6 {) y) S  j5 j* x- X
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.) Q7 v, S7 S. N# d$ {
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */' k* U2 g6 i* @6 c1 [

  8. 2 r; V+ |) r' e% }
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode." g4 h* Z$ `4 l; M. C- d
  10.                                               This parameter can be set to ENABLE or DISABLE               */
      Y4 b( t  f$ w* h2 O

  11. 9 M. Z9 O  o4 e: M
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.2 V  I  A6 A* s2 O, g- b
  13.                                               This parameter can be set to ENABLE or DISABLE               */5 }: Z9 w5 [/ v) S6 x/ V

  14. 4 Y5 u0 S. P- b
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.$ C& b2 s, O: [
  16.                                               This parameter can be set to ENABLE or DISABLE               */
    4 T9 M& c: P" b0 p
  17. ! [/ _" G7 n# h" v1 N+ `9 o! o
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is* o$ h: A1 b3 V( r$ h5 s
  19.                                               divided for generating the nominal bit time quanta.
    ; x- e- b8 z3 u4 P; K0 z7 I! i) p
  20.                                               This parameter must be a number between 1 and 512            */
    9 t( V% k! [1 w
  21. ' G4 a% ~6 T3 F% E3 k; j8 g4 A2 T- {
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN6 T5 x# k2 X& G1 c# _# D
  23.                                               hardware is allowed to lengthen or shorten a bit to perform. ~% U3 x( D( k% t9 d% m, q; U" k3 n
  24.                                               resynchronization.
    6 R8 Y' q) B* h( `: A
  25.                                               This parameter must be a number between 1 and 128            */$ y. ^+ X, f2 S( _9 M6 ?2 D
  26. 2 H; z3 }8 w3 z. A0 J3 H: l, q
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
    5 ~5 z$ C8 z6 e# r1 y
  28.                                               This parameter must be a number between 2 and 256            */. I- b: Y% z  x" T  y' B8 Q5 T, t

  29. - n$ }7 x. S4 P  ^8 Z, m
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.
    6 S5 H& t7 F( i( t) u4 `
  31.                                               This parameter must be a number between 2 and 128            */& r; ]+ K: `6 N4 j
  32. + Z  S. k3 H  V5 T1 Y
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is- G( N' H  E+ ^3 e/ f8 ?
  34.                                               divided for generating the data bit time quanta.* k. T4 f- z$ C6 H3 U* c4 v' \
  35.                                               This parameter must be a number between 1 and 32             */1 ~& S+ |" A+ O

  36. & c" T. |0 ^& [
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN! ?& y! A0 I; K1 N
  38.                                               hardware is allowed to lengthen or shorten a data bit to
    6 L2 h2 a( o; M8 |& r4 S3 P
  39.                                               perform resynchronization.
    2 L) D2 ]6 T9 B/ i7 R: @. Q
  40.                                               This parameter must be a number between 1 and 16             */5 l& v  q+ i; c- F) i1 P3 `1 J) ^: ]

  41. . p. U/ H* X7 \3 w1 c
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.: ?$ q$ Q* W  |! n5 ^" V2 a% |
  43.                                               This parameter must be a number between 1 and 32             */
    , H) G5 R* d/ ~3 q8 J

  44. ) ~$ P, F0 t, A% H; q- O; J5 U# N
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.. z  [+ R9 p2 X7 I$ A0 W8 R- p$ j$ E
  46.                                               This parameter must be a number between 1 and 16             */; |$ {) S$ d' E1 G7 k$ l0 Y
  47. / d& `$ [4 }. ~& q* Y4 j; t2 C
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.6 `( C* o7 F2 B( x7 P4 G" H: }
  49.                                               This parameter must be a number between 0 and 2560           */! v: P; j" O. H# ~+ y+ Q" Z
  50. ! ]/ a% L0 a5 X/ ?7 D2 R' y
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.- S5 |5 n' x( V; P0 @1 a1 N
  52.                                               This parameter must be a number between 0 and 128            */' a1 c  q2 w' e( J% ?, F( R( ?

  53. + ]2 k- u6 L! F+ ^5 x$ D5 {
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.
    9 B  U, M7 Z, m
  55.                                               This parameter must be a number between 0 and 64             */
    4 z$ O5 k0 d* i

  56. " |5 a( I6 v1 p- C7 ?& h  O
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements./ C% d5 B, p9 L" x1 {: J: @" p
  58.                                               This parameter must be a number between 0 and 64             */
    3 a! k( m! t! X/ G0 r, o

  59. 7 F- m( Z& @8 X
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
    # Y8 V- z6 b5 L
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */) E5 V4 D7 \' t5 K5 I9 M
  62. , v+ X' T1 t' I
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
    . h+ U& o/ N2 j, W
  64.                                               This parameter must be a number between 0 and 64             */. L6 f% O  a: X3 x- L6 Z; w+ B
  65. . u9 F% v# N3 F) \
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
    ( l: U/ H6 c, n! z9 Z
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    9 [! o1 m* N8 O( {7 r% ~

  68. 9 x' ^* Z$ A5 s4 a! L
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.3 c  c1 u, s; G+ E9 T  K
  70.                                               This parameter must be a number between 0 and 64             */: X4 e% B" t7 m9 S' O
  71. 8 y" d# M( K( p' p' u
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.
    2 [, K( _/ L6 C/ ~7 L# S' X
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */( Y# o( `7 R( L2 ]+ I& W) I  k6 d
  74. # E' ^4 @" b) P- z+ r
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.! D5 R  T) Q! A% ?) \
  76.                                               This parameter must be a number between 0 and 32             */
    $ c) F' @/ e7 E. j9 Y' c
  77. 2 g- n' G( [! F) F. f
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.
    % V1 C  l1 s) z( A1 h" F8 B; [5 A
  79.                                               This parameter must be a number between 0 and 32             */
    0 A" t! d) C) |8 F7 a6 v9 p6 w& A
  80. + @4 C; J8 t5 z$ |
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
      I4 k7 W. j( X6 @% W% d
  82.                                               This parameter must be a number between 0 and 32             */
    ' {, t2 W8 z- w: N- O1 p( N, u9 p

  83. , v  c) m  r, s  k. ?, o! _. _/ t1 T
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.1 B: a7 Y# c2 _' k* D0 _0 |
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
    - S4 F5 [2 c9 X: t* z( L

  86. / p7 B) [) Q/ M
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.
    ( c# K( ]/ c2 ]
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
      T+ n2 g9 u3 L$ M- y

  89. 9 a1 ^" ]) g7 B7 f
  90. } FDCAN_InitTypeDef;
复制代码

7 Z9 W2 W; i2 _, Z6 J. a! z下面将结构体成员逐一做个说明:
# u- q& E( N. Y! `+ ?+ A- [: ^) ?: M/ ~/ G0 D
  FrameFormat9 i- S3 N" i+ u2 ]! m5 I
用于设置CAN帧格式。
' d9 P6 N) x$ d4 e
, R' U& l4 o6 a# H6 z; P7 F
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */9 M3 b3 _. {! u
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */
    2 e' f6 r3 R7 O: k# J5 n
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码
4 ^/ W& ?2 r2 ^  |
  Mode4 l: v% O' p: N# v$ r8 |
用于设置CAN操作模式。
6 \- B* d! W- w; O; Y& h8 x1 \4 Y3 k, q* r4 |
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
    2 ^, w( C  M3 j: e5 q2 \
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */' e) ]  q8 ]. O; x' a6 s. f
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    8 }0 }0 }, p  @7 o
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */
    % n# h. `5 ]/ @& E$ q
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码
4 N# @, l0 v' ?' A5 ]! p
  AutoRetransmission
! z3 |3 o% A6 U/ y7 L使能自动重传模式。
2 ]7 a) j9 h- s* J& L
* o* ?) H. L1 p. ^4 c使能ENABLE或者禁止DISABLE。
+ m& @! _- U/ N3 W+ y! R3 }/ [
7 A0 D4 v" K6 d0 Z/ b6 O3 h! m& z  TransmitPause5 J5 l/ g+ z' B+ @# b
使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。
+ |' \, G$ s" m* z. X, L9 l+ M8 y9 v( ~% l; y1 `
  ProtocolException) I! S* K5 d# [2 A; R
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
9 Q, Q: d8 j: G) R7 F6 R/ ]
9 U. I% J. W( T! J# v& t' J  NominalPrescaler
9 L0 s$ Z: F  i用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。
1 V( {5 }$ A% w- j7 L$ S6 h, o9 f& T3 D* R# @
  NominalSyncJumpWidth: g; H' [/ E8 H
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。+ a& i3 U* X3 J" Q! x8 u  i
) v7 @3 z% }# g) D9 E1 d0 l
  NominalTimeSeg1% ^! C0 N* W' a1 m( b/ W0 I9 V
设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。
3 S" M" z) y) q) j
. E# C. p. q8 M  NominalTimeSeg2
( l: c0 ?. B6 N/ x设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。
. w+ f+ c1 A' o/ o
8 c: z( s3 @# Z. k) L  DataPrescaler& J7 n  I2 n- z
用于CAN FD数据阶段分频设置,范围1-32。
  j1 T: }! B# k+ r- [  c; M+ J
: N8 l, d- r4 @& O& f  a- w2 m  DataSyncJumpWidth3 Q6 r- |4 Y% U+ c7 k! |
设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。
- R! z$ ^1 C: Y# |2 a
0 E+ S( v, c. m7 `! @# n* N  DataTimeSeg1  F" d7 u& a1 M4 }* d
设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。; H# ]9 C- q7 R8 p+ g) d  |9 \

6 Q, w: P( z8 V0 P& y" w3 y# a  DataTimeSeg24 v# X- E" r$ J* M7 i
设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。" V' p% ~/ o) @* P* G

( U2 _8 ~' i5 ?2 H. h! B  MessageRAMOffset
  M+ L! h: W0 `设置消息RAM起始地址,范围0到2560。1 B; O  z. x2 J! n; i

  }9 }! V+ w8 c: }- V  StdFiltersNbr4 e% s8 ]2 f/ m; G  V8 T" `
标准ID过滤个数,范围0到128。
7 K: T. P/ x, |9 N' ~( \" c) B0 X  s7 A) c% r4 p; H+ T4 S: o
  ExtFiltersNbr% Z* m! u. f  x4 x* o- s6 a' I
扩展ID过滤个数,范围0到64。
1 ]) A2 e2 q9 g# ]: N5 q4 A: v; v
  RxFifo0ElmtsNbr, k/ \0 m) G1 n9 d6 B! X
RX FIFO0元素个数,范围0到64。  F5 h, v: U+ `7 q6 L" Z
, K4 D5 D' b. c( e+ y" R* F9 S" _5 J
  RxFifo0ElmtSize
7 y3 ^0 G4 G6 n9 \! H" D% a3 tRX FIFO0每个元素中数据大小,支持参数如下:
6 P- H: c! K5 ~2 x
* K! b% Q" h" u+ }) Q1 }
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
      [& K( U) A3 [5 c* R% N6 P- A
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */3 H; {# _7 x/ Q: M. B4 N
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */* S( {" V5 d" N4 p* S1 k
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    3 {. i& i/ Z; y$ K$ Y: f9 L8 ^* x+ e( H
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */' H& X9 q3 Z, l
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    , `, j, j3 s6 V9 I* `% j  v6 _
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
      I6 I! d1 L& r8 I3 N: E8 ?. {# X
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

  C$ l% ^0 l4 h0 F5 @5 S* ]" t  RxFifo1ElmtsNbr
0 E! y& P& F' D" F, z0 g- }6 V0 C9 xRX FIFO1个数,范围0到64。
4 I8 ^9 T; H2 \# _5 M- m: d8 F
# q  L4 G9 t. B$ f. \  RxFifo1ElmtSize) h5 [9 ~: N+ B- k9 V' ~6 @
RX FIFO1每个元素中数据大小,支持参数如下:% S1 p% t+ d1 N) |) N0 o' u

* j1 }! Z+ `8 w* ]( {- i) h
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    , X3 N9 @6 r2 C7 i8 D4 f
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    9 q6 y+ p! N- g$ I
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */& g* V  I. P, e
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    . r8 a; u1 c7 r+ u
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */( n) Z  ^" V0 {: D* m, I
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    " u- |: G# _* \/ Z
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    ) S5 L9 l: Y4 w2 @: |( y
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
- c; k9 F; ^) {0 U4 j7 I  P& s* [
  RxBuffersNbr
- r, m3 I' j( p( g1 i+ j6 F6 c设置Rx Buffer元素个数,范围0 - 64:
( m0 m6 }6 x. F$ Y8 G
" B1 i( X, \: h: h- {& c  RxBuffersSize. x1 _6 [& x2 H% _
设置Rx Buffer元素中每个数据大小,范围0 - 64:
  |5 v3 }& g/ ^4 W, v: r2 K: b" W5 J& f9 s
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */3 P1 [. z; s% e/ V0 T) z, B0 }6 Z
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */. a/ [. f1 P  L# j8 {8 {
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    : O9 A* j; @* G
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    : [$ x2 A. Z( W' T2 c0 f
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    2 j3 h6 {" v+ c$ d& e
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */8 {' Q# t1 E6 p- N
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    0 ]$ |% J( ~/ l# O' d6 F
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

) Y" U: D, x; y, `6 K  z* {  TxEventsNbr
, h; w6 J  u7 zTx Event FIFO元素个数,范围0到32。
1 E* u# C/ O4 H0 J8 t. K
7 {6 I% l2 i" K6 R, m* S3 I2 Y) Y  TxBuffersNbr
% _9 V" B& G0 B2 p3 g' V' ]9 C设置专用的Tx Buffer元素个数,范围0到32。
1 B- z1 P4 J" B9 i8 K4 i; U
1 ]; B, j, Q! E$ I6 a. b" d  TxFifoQueueElmtsNbr, i' p2 l0 c+ ^
设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。! ?7 J1 b, o$ N) R, h8 N" d
  g$ x5 K' O# R8 ?! G8 Z
  TxFifoQueueMode- ]- N% {0 |" f4 H, t1 N
设置FIFO模式或者QUEUE队列模式。3 e: E$ L1 G1 O6 V+ n6 R7 m
: F; }$ {5 T' u- T' z
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
    9 ]3 S3 b6 K8 z0 L
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
8 f+ A( W& V. x' v3 i0 e1 J
  TxElmtSize
+ G7 }6 H$ U8 v设置Tx Element中的数据域大小。支持参数如下:) I% r+ e- e4 H/ T
+ w% W& x4 H. ^- |; \: n$ f
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */5 o* J/ `- L. D+ r9 {
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    / g) j" L& j8 f+ B% k
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */, z- s/ b8 }& s- [3 R- v; c; F1 P
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */$ z+ N" W3 `2 s
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */8 h$ D2 }! |1 r/ A7 D& g4 j
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    9 _( F% v2 X+ Q' g  A
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    8 o* ~, @, v) }
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
% G  V% `; a9 W# `6 |4 |8 Y' p
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
6 Y8 I4 S& _7 o$ `5 I# P% [4 D下面是消息RAM结构体:* R* R5 G, z2 I
  1. 2 h8 V$ }4 P( I9 {" E
  2. typedef struct3 C" H1 L& R$ I1 V2 E
  3. {
    & x" C8 d1 |& t, ~1 }
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
    7 f7 C3 [8 R8 a* x- n0 V% O
  5.                                   This parameter must be a 32-bit word address      */
    2 \0 o7 U% Y& B: j
  6. 0 Q% Y6 _1 y8 m+ E' T
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.; n- X; j0 G0 J9 T* h  J
  8.                                   This parameter must be a 32-bit word address      */
    : Z+ c+ R) Q* B" Y4 N5 R6 ~

  9. 9 y/ E2 z) D5 W% V5 @
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.
    ) }% i# I) t/ V! j  s% O9 A7 ?; ~" r
  11.                                   This parameter must be a 32-bit word address      */6 O' b0 \! J' d( F% d" }" V2 l
  12. 3 N( J( e3 I& l/ Z
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.5 r6 }- K1 v/ ~7 c2 v; ?7 B
  14.                                   This parameter must be a 32-bit word address      */
    6 X% j5 r  `* ]. [

  15. / _3 v* Z& D3 J/ v3 Q; p
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.9 {0 `% @4 s/ I# G
  17.                                   This parameter must be a 32-bit word address      */: ~! ]( t" X1 E* W2 B

  18. : q: J& K  k' q: X$ L' ^6 z3 l# G
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.
    4 w- y  s7 u3 s' D3 m
  20.                                   This parameter must be a 32-bit word address      */
    / @; l) U( v. b( `3 k4 W

  21. , ^6 H- G' z; A7 y1 `# m. K
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.2 h3 Z2 j  T. }
  23.                                   This parameter must be a 32-bit word address      */0 Y( P7 j1 G1 a0 h, ]" F. r

  24. . S  `4 [9 n" \9 E* s
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.
      N% u' S2 ^  Y* k9 K
  26.                                   This parameter must be a 32-bit word address      */
    2 K8 f0 n5 K9 ]  i

  27. ) K* U7 \2 `0 w0 U$ j+ m
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.
    $ a9 m2 e# C. t2 @7 @, K. ?! m
  29.                                   This parameter must be a 32-bit word address      */. y1 z# I! ~' R0 ^3 n

  30. $ K+ ^9 K# z2 T0 E
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.
    9 r2 p5 x) a! J% b* y
  32.                                   This parameter must be a 32-bit word address      */
    3 N8 n  `8 P! C7 n$ k7 }1 E

  33. 5 P0 G' P8 g1 z" x; \
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码

. }  C3 z& w( J3 P# o& `2 d下面将结构体成员逐一做个说明:
' t  g5 d/ [* v! O" G- a0 Z# G7 c
  StandardFilterSA
! J9 Z7 z! t% v$ H) O0 R设置标准过滤器起始地址,必须是32bit地址。
2 t. t7 h* m( ]$ U4 c3 L9 `" }, V' O4 e) P6 r3 E
  ExtendedFilterSA4 i8 g! G# q1 p' s
设置扩展过滤器起始地址,必须是32bit地址。
! b( b1 ^, U! w, A# @
1 E7 {5 h2 D+ e. G  f' K! k3 \  RxFIFO0SA4 d/ e& H7 h% t: J1 m. J
设置RX FIFO 0起始地址,必须是32bit地址。" F7 m- d3 ]& }  F
0 |  O- F. D9 ~2 Q8 k) i
  RxFIFO1SA% F* R2 B7 I; u. L
设置RX FIFO 1起始地址,必须是32bit地址。8 E' ^6 F+ e7 o7 N  ?
# K1 T$ I( H! m9 i& }, P
  RxBufferSA
0 v6 C3 Z2 c5 S# b设置RX Buffer起始地址,必须是32bit地址。3 \+ p+ n7 ]- ~

: L0 D% Y" ]9 W' P; W, R& H$ P! k  TxEventFIFOSA7 _& k9 s1 l) ~7 y+ u" g5 M
设置Tx Event FIFO起始地址,必须是32bit地址。
# z0 T4 c' o7 _$ g8 j& d1 P, Q; O' V  C$ N% ~2 H
  TTMemorySA
4 K+ u6 Q6 D  r9 ^设置触发内存起始地址,必须是32bit地址。0 A& E. E. E2 k8 [

" O1 m3 l! _3 g+ X6 k( J# k  EndAddress
9 @* A7 M8 X  j设置申请RAM空间的结束地址,必须是32bit地址。
) I# ]/ U  n& r7 \! I; z1 Y: c" a& J2 L
91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef+ Y: \. H, ?% B! a1 m! ]
下面是过滤结构体:9 ^; a* e' Q6 _& a# _& z

7 }& [$ ^4 @( P
  1. typedef struct3 [: T! Z. H# l* P3 w) A6 Q
  2. {0 w. C3 ]) d+ E/ _4 [2 B2 G3 w- A
  3.   uint32_t IdType;           /*!< Specifies the identifier type.$ x) o8 O3 ?8 A; n5 }, b
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */8 s, ]1 a. F: j/ ]) k

  5. . r; q4 m; v8 z( [
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.
    : j/ C  ~* R) m. N; ~
  7.                                   This parameter must be a number between:
    7 L9 U; n9 s, \  @: y' }
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID
    2 D! x1 ]" i; L, ^, J
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */
    6 J5 \' a! d9 [2 {* W/ i. R
  10. ; c- x9 p- T7 b+ ^) a0 j/ \
  11.   uint32_t FilterType;       /*!< Specifies the filter type.: ~+ Z$ W% e2 n) J3 C
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.0 |+ n, \$ G5 i1 Y8 z. V: ~. g
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted
    ! t, X! n  y2 u- G9 F. i
  14.                                   only when IdType is FDCAN_EXTENDED_ID.
    % X5 E6 X% c8 o6 w9 j  E
  15.                                   This parameter is ignored if FilterConfig is set to; Y9 G% P9 M( i' X, K2 D& B1 W
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */
    4 R0 H$ ^  s' B6 ^4 f
  17. 1 J0 q) v. a  I: i% i
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.
    6 B' P; N% N9 {' O" g6 f
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */$ B2 q  r. _3 f+ c! N8 ?

  20. ) B* {- T5 p$ c4 w. G; l
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.
    # [+ [$ }9 M: n
  22.                                   This parameter must be a number between:
    9 ]* [0 s; s# r$ v, \: j9 W
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID5 M( x" u" y9 t, @  J1 c9 V
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */5 d- V7 z6 y& g9 ~) Y
  25. " T1 u5 M  F( n' {" D- {, L
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.
    . T& j  j7 T9 {* [4 `9 G  J0 \
  27.                                   This parameter is ignored if FilterConfig is set to
    4 @3 i% n# `7 g
  28.                                   FDCAN_FILTER_TO_RXBUFFER./ D5 {+ \" i) s& j7 [* C
  29.                                   This parameter must be a number between:
    2 D! ~9 m% \! Z. U7 S
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    9 G2 Z1 |1 q' n- @( |4 c9 u
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    ) v0 Z$ i) r$ q4 P1 p
  32. - `: d% q2 ~6 X
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
    * z" u3 D# T2 p+ \' a/ \5 G  J. ^2 o
  34.                                   matching message will be stored.
    # o" c( Q( X, F" X+ ?
  35.                                   This parameter must be a number between 0 and 63.
      L4 T  z& r8 b9 N/ f
  36.                                   This parameter is ignored if FilterConfig is different
    $ K; c( p' \9 u6 M  s4 T8 M
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */
    ' q3 Q( D$ l, }$ n& d0 _
  38. ' q, d8 }0 ~0 }
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
    1 v" Z4 r% k% u$ y. ~
  40.                                   calibration messages.
    * L* d) t. K' t$ F% l" G7 \, |/ L* a
  41.                                   This parameter is ignored if FilterConfig is different
    6 @; S3 t4 P2 o7 G# [/ d" P
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.+ L2 D5 X0 R3 V
  43.                                   This parameter can be:# o3 B9 ]& ~8 K4 _  p, Y) D
  44.                                    - 0 : ordinary message: F9 j2 j* i- v9 n( m3 K
  45.                                    - 1 : calibration message                                */, G7 Y9 J6 O% w! ?; P+ @2 a$ y
  46. 0 p8 a1 R* s1 K1 d3 M
  47. } FDCAN_FilterTypeDef;
复制代码

5 ^4 K9 {$ Z& w; F' V  IdType
" F2 t' R) S1 L! z) X& O用于设置标准ID和扩展ID。
3 ^- ^0 p7 j# |  k/ T! l9 n6 ]
: y6 `, m* Q% o9 i: K. `
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    8 Y2 z! {- Z$ }; v
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

  H% F) \) e+ E% T  FilterIndex
+ n# ?: D$ C4 H; L' w用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。, M+ }1 @% ]7 O

0 N3 W0 {8 V( h$ H' g7 \* b  FilterType
5 ~) Q. {1 [  w4 s" C用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
/ c6 E: q% [" H$ J5 |$ H3 q  G5 p! J
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */
    8 [* y$ O7 D# B# e. I1 E
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */6 R5 I% R3 q- b5 N; n

  3. ! e% X5 I% v- p9 D$ `) }4 h
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */' W* r( l! O9 A6 a
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U) # @5 n9 P3 K, @! a
  6. ; \5 T  e) x$ }, Q8 U
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */
    ! s$ S6 k" G) F# Z" d; ~
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

+ ^( `6 }0 c. b& M& M2 \  FilterConfig
. D' s* T" z" p  M用于设置过滤类型。* X! G' I0 \( O8 Z$ ^5 `8 n- T

4 B& {& |* [  b0 e; R
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤
    4 W/ H" G3 h1 q( p- ]
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    5 {! b+ Q1 M! Q6 j# S
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1
    + o$ ~3 W5 a" ]6 |2 c* s4 _
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID2 d/ y) ^9 M' q9 r1 j6 ^$ }( C
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
    6 F, N% Z. o% X: a( ]! s. K
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0$ Z: E, ^" c; N+ Y
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1  c) v" E0 H% q9 @# E5 v6 h
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码

% l) X& n! y+ g0 U) L; j配置
6 l1 I4 _" \; @3 T0 S; K  FilterID17 s0 j2 D. [* M/ g* Z
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。! l! G8 l- i: L
$ x$ o$ c8 L1 ]3 M. }' x3 [* C$ }
  FilterID2
% @0 ?0 O! [/ C9 C2 v用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。# P; @9 h4 M" S) w+ V, W4 A2 n. M

( c2 V( K/ ]. ?% ^( h) n6 |  RxBufferIndex
( h7 E$ g! p' _* i; _3 N匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
0 Q$ s. j+ V  ^, Q# Y& n" D0 A
8 f6 K; i7 j: l5 A5 B  IsCalibrationMsg' o/ [, M% i' I7 c4 n; B5 m3 a
用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
3 G, u9 u; Y3 `9 _. d* N
- a1 h- u2 m) X3 L( v4 O0 : 表示正常消息。
6 `8 Q4 L0 U4 T! _# L9 y/ }
- E; D. z. E5 i8 G! T, r5 f1 : 标志校准消息。# ^3 l: [& N6 a. `
6 O0 q/ V9 p$ w4 q! r; p  G
91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
4 w: }4 ]+ `5 v% a/ h5 h下面是CAN FD发送消息结构体:
+ w, |, I* _+ T( h* \5 Q% Q3 ]6 u1 P: H' q. f
  1. typedef struct
    4 Q6 f/ C" v. V) _
  2. {, p$ d- s3 E! p* W0 d
  3.   uint32_t Identifier;          /*!< Specifies the identifier.$ m  x+ i' F. x
  4.                                      This parameter must be a number between:
    0 I. P0 \8 J2 I6 `: x" H8 Q9 ?5 C
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    + X# b! r* G- l$ m
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    # ^5 W- }& w5 ]5 i
  7. # }. B. o& s& l" ^( {
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be# U6 Z% l) ^2 u% O: v# c, u6 [9 \
  9.                                      transmitted.
    + x  y+ A2 U' o2 b7 y9 T
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */
    ! q- P) x& B9 f3 Y$ ?1 t4 n. W
  11. ) O; l+ f* h2 z0 ~' F
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.
    * S  O2 M# R+ I4 \! x7 w
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
    9 A. U& ~; ?9 S7 o* ^& i

  14. * K3 o% S: t( W* R0 w( S* k
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
    . L. Q7 ?1 n2 Y3 s' _
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */
    ' U2 ^2 O% J' U' [6 f

  17. $ B8 H. y: N4 Y' g  }' \
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.
    7 }0 N/ S; @3 f& M+ S' f! _" G
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */
    " u$ q( e2 B" W$ F8 b# P

  20.   P8 ]- M. G" o
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
      _3 W" \8 e7 @. o
  22.                                      bit rate switching.1 A) D2 \" R( S6 |: j
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */8 G8 R7 d5 d7 u4 R' Y9 h. n
  24. 9 X/ l% i! f! T3 N3 h( _6 I/ Z# G
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or' I" \0 j% {4 V/ y) P2 o# m3 N
  26.                                      FD format.. T* e' B% p3 [- s- ^4 R3 T+ \/ t
  27.                                      This parameter can be a value of @ref FDCAN_format                */
    2 W3 B( B/ k9 l" {
  28. . A. Z# E* r3 o1 x
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control., h7 {# x0 _6 e1 \
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */
      u2 a# W( @& [: w% I7 _

  31. ; Y# k  F7 y" B
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO* g. X( X. q0 I5 X* W
  33.                                      element for identification of Tx message status.
    $ T, V6 Z0 u9 F  y# P" B! u: s+ U
  34.                                      This parameter must be a number between 0 and 0xFF                */9 f, M8 b8 ~/ T$ V

  35. 2 S5 f# _6 X. ?
  36. } FDCAN_TxHeaderTypeDef;
复制代码
2 V+ e' T+ ~  `, @: F/ z
  Identifier" ]6 q* b& n8 G4 ^, W7 O
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。) ~1 o% M$ z! l) [# ?
7 r/ e+ z8 |. Q. |, j% o  c/ f9 s% J" L
  IdType, i3 z5 h; j5 Y" }' a' Z# s
用于设置标准ID或者扩展ID。
6 @9 Y4 [! n$ b- K2 z% l* F1 U: I
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */  |5 m; |$ ]7 I- U+ A& U$ q2 A/ |
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

/ ?! O& ]7 U0 j1 _  TxFrameType
: `/ I# U6 ^' Q  H! P用于设置帧类型,数据帧或遥控帧。
6 u; q6 F, y0 _3 n" L* F% k; M* j) [5 z  W/ z( p: ]2 U( i1 Q
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */( ]$ u: n; C: `1 K; s
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

$ g3 p! u: n  ^1 S0 e- z. ^  DataLength
+ Q- I1 H4 S9 X/ T用于设置数据长度。/ R, Z/ l5 c) g' }+ L

8 D8 p7 s  ~# }
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */$ x3 H+ i; W" _5 u( G9 q
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */! t2 {  ]5 v* f3 [
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */  ?. w: @& S' f/ h
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */. E+ C9 O5 c" B9 v
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */& [8 Y, a9 E3 a8 c2 T
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */& M1 P7 F6 c+ P3 r
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */# W4 @# k) e% v. q" w
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    2 ?/ `' D5 ?9 X
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */7 g  V  I' i1 q
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    6 `: ?8 n" g: ]& j
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
    & |' r* V$ I1 M  k
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
    - Z$ E: f5 ?& B' T" D; b
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */1 H! P8 C$ b1 Z" \
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    , P+ X+ X6 l* z, v  W7 v$ c
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */1 P# v6 r% x7 Y
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码
- ]5 L  f' x1 o# q
  ErrorStateIndicator
5 u/ f% q4 K) s9 J1 h5 W" k用于设置错误状态指示:9 [/ f1 B$ ]$ j7 }4 l9 g8 T3 F" e

; N: O. {# t2 D& e/ l
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */6 P6 t' w+ [1 ]" r3 e3 A1 Q' _
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

0 j7 e8 l5 C0 C  BitRateSwitch
+ W; Y( M: s9 I. r7 h0 q用于设置发送是否波特率可变。
" f2 b' A7 \0 F- s& I; g0 v; Z
2 e/ E4 I3 A. V8 p9 C; p" i
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */, ~3 [$ Z" }1 d) \3 e8 c% ?. V
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码
; g; \; b% h& m7 A
  FDFormat
- T- R0 \) a4 `0 S用于设置发送帧是经典格式还是CANFD格式。
* X, Q! e+ ^& N

  1. 8 M4 U+ S% _, R0 A" y: M$ F0 A* O
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
    # x( \% Y) l" k% Z6 m
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码

) n, J) E1 w8 U, R" H" n  TxEventFifoControl( q* ?9 }4 M* |
用于设置发送事件FIFO控制。/ X9 ^: ^* `5 y2 Q$ I  `

& \  t' x0 O+ t, W7 g
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
      ]$ H% p0 B7 a3 d/ H
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码

5 q* d8 S9 u' l$ V  N7 M2 p9 c  MessageMarker  B$ |3 x9 J- G( V$ I
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。) v; s, r  L: ^. ~8 C! {

& c7 {; V" ~( S/ t9 S91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef1 e+ C' ~7 T6 |' @- a; T
下面是CAN FD接收消息结构体:
0 G1 c: F" e" f6 q* z; H+ X8 F
6 \  u, V9 p3 z8 i7 e
  1. typedef struct/ B6 |+ O5 \& H8 s: {7 W7 X: P$ F* e
  2. {
    . @' j. y) Q( I3 v; y  h9 v3 s1 C
  3.   uint32_t Identifier;            /*!< Specifies the identifier.
    3 J% t) |9 E) S
  4.                                        This parameter must be a number between:
    # }4 D$ M; ?( `4 \0 R
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID% t/ `" D9 g$ l
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */* K6 ~4 [+ \+ P3 k+ n* `

  7. ; d6 X' j9 E: M
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.
    + x3 R: S7 {* R9 G" s
  9.                                        This parameter can be a value of @ref FDCAN_id_type               *// J' J+ s. U& G$ ~) A4 u: K; I) z
  10. - M8 ]( J2 m& _2 o
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
    1 U- c! x  L1 y
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */8 ]2 B/ U5 p$ S6 y( N/ H3 \* g

  13. - U; a# l0 e2 |* k4 D* h4 ?0 ?. y- S
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.
    6 [' k: l; r! u! q0 V
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */
    ! |0 t9 [' S4 K- i$ Q2 |
  16. ! l2 Y  ~  g& Y' h9 Z1 x( A
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.5 g! |& T$ i; z* b, H
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */2 z1 y5 ~, d! a  p3 d+ c) G( k
  19. 0 q' K3 M8 B( e; J% D6 b
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit" H: L( y: U& B. j1 W/ T& K$ w
  21.                                        rate switching.2 L4 j2 T/ B4 n$ O8 ]* T; ~
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    0 ?' X. o) {( k4 S* e/ a

  23.   _) O# W1 g, w% w- `: Q3 G
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD
    % k3 `# q8 k: Q+ p) N
  25.                                        format.3 f* _* U/ }" ~" b# u/ L
  26.                                        This parameter can be a value of @ref FDCAN_format                *// L: J$ @5 v; m. D( S3 Y
  27. , G7 T+ D+ H/ }3 K: c$ @2 U8 \; Z
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame
    1 }9 U/ {+ `, a2 R4 I
  29.                                        reception.
    8 \4 X1 n1 O5 C( ]) V9 U3 H; s" j" n
  30.                                        This parameter must be a number between 0 and 0xFFFF              */: x$ g, ^1 \0 G6 g

  31. . ?% x0 a- G3 R8 n6 _1 g3 Q
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.
    # t5 S2 Q" C% B( }7 }
  33.                                        This parameter must be a number between:, h3 V! K, G* X3 t6 ?: B; G
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID
    * E+ V" L# ~3 `9 m5 Z3 H3 Y8 B
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */
      e  Y# }0 T) x, w, Z8 s
  36. $ _+ h5 L4 V) Q6 q4 Y
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    - y+ O/ c6 O5 Z
  38.                                          Acceptance of non-matching frames may be enabled via
    : J: v. Y/ R0 }
  39.                                          HAL_FDCAN_ConfigGlobalFilter().
    0 z$ f+ ?- Y- D. h# T9 d
  40.                                          This parameter can be 0 or 1                                    */
    % w, V% c2 B$ U. g8 ?8 ]" C! L) G

  41. 5 R4 e0 E& z, o' X/ _- D/ d
  42. } FDCAN_RxHeaderTypeDef;
复制代码
( V; s: m* Z; X$ j. u+ ?0 q8 K6 L
  Identifier* e* j4 k4 L/ A8 C3 E
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。2 k8 V3 T# s9 B+ A0 A. N0 Z3 k/ M! a

7 ~( r3 Y; u! [- K$ _  IdType6 I: g' ]' `) G& a8 d+ A3 g, ]
用于设置标志ID或者扩展ID。* ~0 J4 g) O: s6 a- C
- c$ Z& `- }! N' D
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
      x. H3 B" w+ L5 Z5 @8 {# ^
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
4 q' w) M! H+ M# r, v
  RxFrameType
+ N: g) ~5 }* Q; R& o用于设置接收帧类型,数据帧或遥控帧
) [( j3 k/ C' ]: Z" f) P5 j
* K. K6 `: d# a8 N9 x
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    8 w( F/ C: A. p7 A2 I2 d5 x  E
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

9 F% G& k6 z, I; e  DataLength
. Z8 }) d. T! T/ k& I2 B% m用于设置数据长度。
1 N2 Y/ h& l1 e/ J9 F
7 d; T1 c+ k: T& M! i
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */1 h! Y% m: E2 C; x6 p6 B0 ~5 s% S. \
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    % \, e+ M0 k1 ?: [
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    * V. J3 V! D# U1 s) N2 y" w
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */- f) M8 i% s; e  l7 `
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */: X+ |8 R/ s- T6 k* i
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    8 j- Y: d3 ~3 {
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    ' `9 k  }- {+ I7 s6 m( A
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */8 L9 U5 X' O4 k" o" C
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    2 T* c5 r* \/ U* ?- q: S
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    ( T/ ]) ^! [3 B$ f5 f& S8 \
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field *// _, \* t6 y5 h( Q0 n" [
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
    . D# g; s3 _6 N
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    # k; I8 `2 q3 g. D) [
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */9 I. R9 ~3 E2 X& D7 Q' ?
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */) N# c* q1 d! m/ t9 I! N3 ?
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
    + p( _5 n1 d. Q& `) p0 V  ]
  17.   ErrorStateIndicator
复制代码

, Z- C: j1 G8 m9 A用于设置错误状态指示:
, n# A8 Y) d" Q0 ?5 D- @( m0 K, O1 R4 N; V1 R1 I
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */
    : G& A5 \% |4 X" B
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

$ v9 a  X* C% l7 T  BitRateSwitch
1 t, C& `* C1 o1 W  [8 s1 M用于设置接收是否带波特率切换  }- S. L/ Z2 e7 ]9 T, r
) G: @* V! j4 E! w) B) S
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
    , l2 J, `9 o- H( r1 \+ x  [
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码
0 d+ O0 M5 X1 f7 |0 ^
  FDFormat
' `- m& W/ R6 V$ J$ S用于设置接收帧是经典格式还是CANFD格式
6 q$ v; Q& e0 M5 e2 N  J( K! ^9 x! \" y
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
    * U1 Y! f: }  p; P8 m7 t8 F6 U
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码
; ~0 Y& D- W/ a7 ~: y7 w
  RxTimestamp3 [) n- d0 \0 R! T
用于设置帧接收时间戳,范围0到0xFFFF。   ! R& z1 t6 S  F/ p" O

* \7 p% t* Z5 Y7 S; X8 b( B  X, U  FilterIndex+ e- N' o* t+ ]/ q% G  `. _" J4 q4 H7 n
用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。
% Q( d: p3 Y' p. k$ [
# B- {$ V8 ]( i' e* q0 S8 r  IsFilterMatchingFrame6 g! f: N9 b" I
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。# l: k! l6 d# L0 S! \" y# h

3 H& p  |2 N2 o% y0:表示不接受。; D% J" P% _1 N! y! W3 g

  s( _. W3 f7 j$ j3 w: K1:表示接收。
6 k/ x9 x4 b7 P' Y0 }  t6 E1 t$ z* e. S5 S
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef" @2 W5 |" }+ Q8 k# w
下面是CANFD句柄结构体:
7 L8 N$ K+ l1 z1 L1 f
6 u3 n  Q! J; p( H- n' H1 o
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 11 f( l2 t3 h5 B/ T* k
  2. typedef struct __FDCAN_HandleTypeDef
    ; j/ D, ], m. ?6 k& \9 A
  3. #else; A, |; r+ g* h2 U& ~2 \
  4. typedef struct
    5 U# O+ M" A) l" E+ y5 Y- n
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    0 M! q: Y* M- ^% x3 _
  6. {  t4 R: E6 a$ L3 J$ X- g1 z
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */
    - K( I) L: A8 [; k
  8. 8 F% r& S) S4 u  ]" p
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */1 q' r4 W; G( v' @. K4 E( x8 @" C) C

  10. $ L7 c: p, ^. {* `
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */
    5 a+ h$ H- K3 c5 W  e1 m$ t4 m$ X; k: Y. i
  12. 9 H% u- R9 m9 F7 e1 g8 W6 J
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */# ?+ ]1 K0 |+ [+ E: B2 U
  14. ; V! x5 F2 _5 I2 b
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
      k, |7 P" ]6 i5 u1 i9 Z+ `! h2 [
  16.                                                of latest Tx FIFO/Queue request */. ~! C: o- N; j# R9 J( F3 `+ k3 M9 Z3 d7 d
  17. 2 c+ m+ c9 U( L: v( X
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */% F' ^: `* M6 O5 Y; E, h

  19. 1 \7 Z$ D! ]8 J1 e0 k/ l& j
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */2 H2 e$ u9 \% d6 S, J+ k5 v9 l# d
  21. 7 Q) J+ x# Y' d, Y
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */
    8 h6 D) ]/ _3 j2 M" J

  23. 9 X" i/ B+ c# Y/ {% Z' i, R6 F( x
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    , {8 W$ S( k! a9 m6 I$ J$ R
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */! F8 d, q; }% I  n
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */) L. _1 I# g4 I, D. G) c- i
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */
    $ }& R" X/ ?$ R# v
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */
    ' z) h) J+ l8 M1 O
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */8 P/ Z" ?+ o4 |4 D2 D4 ^, j0 ^! ~
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */5 t' F- d" }6 e$ {; P: u+ Y
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */$ E0 ^( H; u# `* Y" {. n7 W/ ]
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */
    % k0 ^+ D' Q$ ~8 c: O# h7 m: |
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */; R/ t! J7 T( r6 c, g5 Y9 B
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */7 M. |1 i$ _+ L' |& H* X4 w
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */$ C  @% T" F( _4 n
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */  T% q6 J2 f* t' D  j
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */
    7 J' J: h# X* {  ], x+ o
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
    & |! E  k0 }) e6 y0 P3 r
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */
    ; m: {- A, i9 u$ Q( Y
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */4 P; x/ |/ m$ D: H
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */
    5 R* h+ p- n7 h8 ~
  42. 3 r2 E, I& G) C
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */) y0 {! x6 j) R7 `- a  m
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
    3 ?4 j0 \0 o1 y+ E6 |% i& E
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    $ E2 Y0 w, ~# P6 S& o) h
  46. $ F" K  p* v% `% b+ s+ w
  47. } FDCAN_HandleTypeDef;
复制代码
; \, P! W/ z, j! d2 z# C% ^* `% z: c
注意事项:
( S% z7 w/ H2 R( ~; {8 ]
5 ^) x4 K' u0 i条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:+ c/ j/ ~3 A& c) p
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码

0 a% @( h1 J4 L$ }+ |
. L8 k; h! A" H$ }2 I& C0 d函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。" f8 J' e0 ]" a& J: y: h& C

8 Y7 i9 h8 ?# i& d; F这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。+ h  c! a& t8 \6 ^8 E- k

% A" P) s8 _( `# r7 t3 }  FDCAN_GlobalTypeDef         *Instance
; j; U! i. `1 S- y) X) Y这个参数是寄存器的例化,方便操作寄存器。
3 _1 q' ^! [7 L* y( ?5 }, t7 W( {' ~% b8 g& {% W' ^7 e1 b
  TTCAN_TypeDef               *ttcan
( X% y6 h* q  U! o+ ~/ [8 hTT CAN时间触发寄存器基地址。
; [6 N( g$ g* z( a5 }0 G9 Z( e) S! c2 ^
  FDCAN_InitTypeDef           Init+ i3 H" J- c6 G) I3 p8 @% l
FDCAN相关的初始化参数。0 ~/ L7 u# U& |- e
- ~; j; S6 L* i. a1 M0 k9 W
  FDCAN_MsgRamAddressTypeDef  msgRam
6 d) w+ s& q- o消息RAM地址。
4 d1 e# _% {" }4 d, I7 n' C3 F1 Z# w/ w: D( d' Y5 I
  uint32_t    LatestTxFifoQRequest
3 B7 T6 N1 A+ L* X$ s& p0 F* ITx buffer索引最后一个Tx FIFO/Queue参数。
3 @# k% n( O, Z/ S  X6 U. X: g5 p8 y4 l5 D# p/ n
  __IO HAL_FDCAN_StateTypeDef State          ! s" c. s. I( Y4 ]0 \
HAL_LockTypeDef             Lock          - H4 ?  y6 p% p$ H

# x% u& ?: U' _/ Y__IO uint32_t               ErrorCode
' ?& [/ |$ {0 K! Q9 R; c% V
7 Q1 d. _  z2 b9 g+ ^程序内部使用的状态参数。2 V: g8 Z: z) m7 b2 B# [# X# j1 g

" C5 {5 p: l! y/ V  剩下的都是回调函数
8 @) V4 s) p- W% m2 O0 M' [& k# r91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
% w6 j+ Z' [# m此文件涉及到的函数较多,这里把几个常用的函数做个说明:
6 E- W3 X  j, h/ P# {7 t" y. S# L1 q' B9 K& F3 q0 J! ^2 o
91.4.1 函数HAL_FDCAN_Init
  _2 i' F: \) H. }函数原型:
/ t/ Z( j) ^% ~# i2 K$ ~( T" f$ b: B( I+ y" J
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
    * d# V! X% n2 p7 J  ]) B2 A
  2. {
    ; d5 V2 B, z& X$ u+ T
  3.   uint32_t tickstart;
    " h: N& `  N# E, J1 `. ?
  4.   HAL_StatusTypeDef status;2 x9 B1 I9 j" k) B" s
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
    % W& ~: N5 p6 z( e3 S  q

  6. / P) R, h2 a7 G! q
  7.   /* 检测FDCAN句柄是否有效 */. @( y5 N% R4 s6 s. i
  8.   if (hfdcan == NULL)
    + q, y8 @8 I/ d$ G6 s  b" }  z
  9.   {
    : E% i' O/ v# p, V3 _' Z3 ~
  10.     return HAL_ERROR;
    ' D" t. d* H( A' |; d/ e/ T, b+ f
  11.   }
    6 H$ P. n$ X0 e" g# ^
  12. 4 t5 h  ^( |6 S/ U) l8 O  T/ d* f
  13.   /* 检查FDCAN例化 */: W) Q0 x0 P# ~" Q  C
  14.   if (hfdcan->Instance == FDCAN1)" S1 {& R( ?, n4 \$ v
  15.   {
    ; R) @; L& H- i6 {$ n, m
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
    " k- c' w. z& z1 l. Q
  17.   }
    , ~7 Z# E- C% j
  18. ! E$ j3 V: e0 I. }; v0 G
  19.   /* 检查函数参数 */
    8 a4 Y# y) e$ }2 e) b  ^
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    $ r5 k# A: ?$ T! L- a  K% M
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));$ S; C2 ], v2 X" R) p4 A
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));: @! }: O9 X  f# Y
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));' O# W% c: _  Z) g
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
    5 H* S, G7 L* c: i$ i
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    + z- s! m! _8 P, Q1 |
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
    ! s& u9 Y5 s2 E% L1 H5 i; X) R
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
    0 ]7 u: n7 g9 X8 v) L; J
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
    - n& @; l" }* s7 J( x# I# B! b. W
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));
    $ @/ [$ _* k" U
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)/ J. |# C9 k8 |/ o7 @, g& U1 Q
  31.   {
    ! S4 c' l- \( T6 F/ j7 I2 m
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));2 {/ b6 o; }: D+ C
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
    5 n) D% c' z* i! \  X
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));1 @6 F% [! c2 d7 E- d
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
    # o/ w( Q' @; j( T0 M; K
  36.   }
    : s* L+ j7 @( f/ n  M
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
    , i: n5 K+ C2 }
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
    5 {; d: y+ F& Q4 D3 d. D# r; k
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    % E7 j( w/ r) c: U9 T' c! u. v
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
    ( a& i% T% c/ G, E
  41.   {
    , j3 Z1 ~8 Q0 L  Z0 y* O
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));# v" ]% N1 n3 \
  43.   }. p& [+ I8 p2 T) t" H( E3 k. w$ H
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));& |+ ]! x, k& U/ U# v% u" N
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)% K( ]  B& K- O" P! F# {: _
  46.   {
    7 B, \# J& |3 T6 |( c
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));; h& V+ c4 X$ n9 L2 L: }" Q# o
  48.   }, q3 P( z3 B$ u
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));+ H: t/ d$ o# w  W; y1 K
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    & \9 I0 R: e5 k- k/ p. X
  51.   {
    ' m3 {. P& H# l9 `
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
    # Z) Y7 @  @4 y: J" T9 ]+ g) U
  53.   }) m  ^& j; C9 O% F
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
    , }0 J: |; p3 V
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));& c/ \4 y) l  F8 x) t( g
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    : q4 o2 N$ G: O2 J$ f
  57.   {
    + F7 Q& a$ A3 X2 I0 O! |/ _: o3 Y
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));- L: v) S7 ~$ W, }! b1 N' o" C$ d1 X# B; s
  59.   }
    , Z& o1 G( O" [# d. u% M1 [+ I) \
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    $ O3 ]6 @0 w; c) M  b6 v- c
  61.   {  n5 g6 E; P" y; V3 h3 @
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));) C/ D( B2 c* \, ^# ]
  63.   }) w% o* U0 Q2 {/ \% x
  64. 7 P; Y& f4 z, t5 W# @6 B
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    ( ]# y; G( G9 A1 X4 G
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)1 w- j+ Q/ Z5 K2 l  @: M7 c0 ?
  67.   {8 S# n: S& B" w4 i( d: R5 G0 M
  68.     /* 解锁*/- m7 v4 k8 M* `, ^2 W2 ~
  69.     hfdcan->Lock = HAL_UNLOCKED;5 |& a; g, w  W: B- _: P$ S0 O3 U  r

  70. : X* d# v9 J6 a. c1 g- T9 K# S; U5 Q) M
  71.     /* 复位设置默认回调 */
    ' w" o/ r  z: w$ K- T
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */8 ~2 d* r0 e* E
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
    % Q! F) ?/ ]9 [5 c1 D; q) \
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    * D% D* i% L% m, P
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */3 G, g, Z8 j: ]7 v
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */0 }. {) `! Z6 Y) r, o) \7 t3 u
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
    % B, s( |+ Y. L! z
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    : x. ]: h6 Z; c' {
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */4 K9 o/ Q- S- ^; V
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */- @; e" E  T9 J! n: y3 r' d
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
    5 [7 y8 R; U6 B) Y: a5 x% w9 I+ ~
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
    3 n: b( L9 J0 S* h) c
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
    " C. U3 T9 S$ c6 o0 w8 K
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */* E5 S* b$ k% L/ l, L. R
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */: K' Y, |9 a2 p. f2 k& [
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */: h8 ]$ f% M" `$ y. s0 e! X: p
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */
    ! i1 g7 P3 |+ B3 N9 [. [8 \: o
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    & W5 \9 f4 C3 @! z$ j) F9 r6 e

  89. * p0 H/ p, `2 A: y3 u' m2 D
  90.     if (hfdcan->MspInitCallback == NULL)7 o2 `  x4 |9 G; I% J5 E
  91.     {  X4 d( D. y9 c0 N% ~# N2 Z# m% f5 q
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */0 E$ r9 Q! `+ ~7 Z7 i: Q
  93.     }% J0 Q. T  D# e5 w
  94. ' E1 B' A+ x$ {2 s
  95.     /* 初始化CLOCK和NVIC  */
    7 z6 K0 O, @( z; Y0 `
  96.     hfdcan->MspInitCallback(hfdcan);
    6 O' S$ T5 h& r1 A0 J- U- T3 n
  97.   }0 `, O0 u! i* y  `/ j
  98. #else1 t0 U8 Q' q( k* G8 r/ m
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    6 `# A2 L0 L' D0 C2 p
  100.   {
    6 t' v- n; o  _: E8 s, s8 i
  101.     /* 解锁 */
    / P, I, v4 X4 u; A+ t
  102.     hfdcan->Lock = HAL_UNLOCKED;- P& X. a; j8 h6 M! P0 ]8 D
  103. 3 b3 p$ R  q' t
  104.     /* 初始化底层硬件 */8 k! @- s# |+ A$ ~$ t/ n& `
  105.     HAL_FDCAN_MspInit(hfdcan);
    6 w4 ?  p2 ~/ @( Y
  106.   }" @, b8 g) u5 W+ K# i$ o3 I5 p
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    8 W6 o' N+ s8 t, Z
  108. " Y! |' Y' e2 O! B* F: [
  109.   /* 退出Sleep  */
    " b- a6 G7 p, s7 v8 |: I* K" K% q
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
    ! ~! S  e9 i) w; h- W
  111. : P/ x3 g9 n, p! G
  112.   /* 获取时钟 */
    * g) t5 e; ?& w
  113.   tickstart = HAL_GetTick();+ R% T* y9 R" U$ }8 A& ~; f

  114. # S. A" x7 J& E! ^4 R
  115.   /* 等待Sleep模式确认 */
    ) o' a  n; Y3 v+ g6 W9 }  W
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
    ; x1 U6 U* b, M0 |6 }, ]) g% Q. r
  117.   {- L  P$ V1 z9 ]+ s* }' C, A. V
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)& r  _! m; t) r6 `, u* J, Q
  119.     {
    ; I/ r$ b2 q: Q3 T+ L1 m. t4 }
  120.       /* 更新错误码 */  b3 T5 \+ d! \3 Z: }( |
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;0 ?- c, z0 R" s# L

  122. 7 `! i  [: V& r' {' _# [
  123.       /* 改变FDCAN状态 */" F; D- A: ]9 x- [7 B& g, q/ k
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;
      i) Z7 I  b% S( h$ b4 j+ f
  125. ! h/ c6 z% k( Q- b. u
  126.       return HAL_ERROR;* L, o6 A8 z8 H# M2 x- N, }
  127.     }
    ; g* w& C6 d$ o! |2 `, W
  128.   }
    ( p9 l! \% T* h+ o7 k; N

  129. 4 F) W6 q- {0 g7 j# A* r9 l
  130.   /* 请求初始化 */- X# y" W( q/ c/ E3 x" g
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    ; K. t  c. }6 s% Q: Y& C

  132. 8 A! c  `: A, d1 Q
  133.   /* 获取时钟 */
    6 U( ^: e6 N. s/ q" D& l
  134.   tickstart = HAL_GetTick();
    & p- J& v( q+ F) m
  135.   }, o# p. O; n- W
  136.   /* 等待CCCR寄存器的INIT位 */
    4 `' ?' B4 j- |' {  G
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
    . Q* l* Z0 s" L  c/ |
  138.   {
    ; s. _' H4 ~: S" g$ c
  139.     /* 检查溢出时间 */
    ) X4 p+ @  t+ t  \6 M' H2 s
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    7 V. _  P4 y0 @+ b: C' H
  141.     {
    2 s4 m6 G6 ^- y$ r! |9 ~
  142.       /* 更新错误码 */
    & z3 \/ t' Z0 L" N; ]9 A0 s
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;' z+ I" p- I0 |9 f, n
  144. # T% ?4 ~$ q. a. d5 S
  145.       /* 设置FDCAN状态 */# @1 k7 D4 |% R* C. O) c7 ?% W
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;
    5 T- K! e' V9 F8 O. d: F) U2 e* E

  147. . [9 l/ S$ _% U# b$ b* [
  148.       return HAL_ERROR;  Y+ o# i7 a) k& w2 a
  149.     }  L" T9 b( [: t# ~
  150.   }; B: p7 r2 F( F! \0 q
  151. , l$ [& X' \1 _: `0 l7 j3 @: O
  152.   /* 使能配置修改 */6 ?! W" }2 Y. S4 |' c
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);) Y& N# C4 X  }

  154. ; P: R# [7 o1 L. X7 w
  155.   /* 设置是否自动重传 */# s9 ~+ A& N, l* J, L
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)6 N: ^4 A* ~5 k# u
  157.   {" a. L8 a" P$ R! N3 ?! O7 x
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    6 d) o' g2 g9 y
  159.   }+ e+ x3 z* o- x8 k5 t9 [
  160.   else
    6 g: b! \; o: l1 B
  161.   {, u- z$ u% w  Y. j+ Q
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    3 J# q* V( J2 U
  163.   }
    3 [( B4 U& R8 m, h
  164. 8 y+ G2 g( Q/ j7 G0 ~
  165.   /* 设置传输暂停特性 */
    1 H$ G; B, y' r0 l3 Y) p, I
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    7 B: R8 d% o# _7 ]. H
  167.   {$ g0 x% A2 d) B9 R: j
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    $ I) {5 u1 I# y5 g
  169.   }4 \5 l/ `. y* n& M# V
  170.   else9 B. @  k5 y1 t. [5 Q$ ?
  171.   {
    $ d/ E( h2 ^5 u# {7 p
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);, _7 N5 e& G) D
  173.   }8 [4 Y  X; X' ?3 n. n; m0 }$ P
  174. 4 C& t$ v% x! O/ Q% v  {% L) B7 D
  175.   /* 设置协议异常处理 */" r% D7 @9 r7 L  d. v  G
  176.   if (hfdcan->Init.ProtocolException == ENABLE)0 `' p: E: e! C  h9 L
  177.   {3 c/ M' Z& I4 X
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    9 R" T( c7 \+ k7 K$ e( l: X+ D
  179.   }0 ]* r4 I  b) ?  j" e" I# Y. ]
  180.   else. D  ?" w7 H: u3 O8 q. E: |
  181.   {
    9 O" d0 w/ k& c: V% M: {* k
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    ! ?  o+ n% m+ J: s2 e9 y
  183.   }
    5 m+ A2 S# O7 \2 l
  184. 0 U8 h  j* S: H9 w
  185.   /* 设置FDCAN帧格式 *// }/ T6 \) T( Z& o# y1 q! L7 W' c% G
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    1 X* t* v" {. L5 A* i. d% R0 N4 l
  187. $ d  o2 I/ l1 L4 ^# o1 i$ F
  188.   /* 复位FDCAN操作模式 */
    4 ^) X$ D" Q" _5 R. x
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));
    8 o; U5 m5 U7 C7 c- y3 |7 l7 A8 }
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);: |  ]& C* \+ G' S- U/ R- I" [

  191. ! n+ v. G: z. G1 P
  192.   /* 设置FDCAN操作模式:
    0 B4 ?( J! d; A7 |: W; z' @4 p. e
  193.                | Normal | Restricted |    Bus     | Internal | External5 F; q1 G* B" o4 t$ e# X4 n+ j
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack
    2 u% @! \/ e6 p& c! O$ c
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    1: p" {$ b) W' r/ z4 Y* j
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    0* }6 |  |) @2 J
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    1
    , ^$ ^4 E/ v& |3 e
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0
      z) t+ w3 P% ~) r, n
  199.   */4 L* R# [5 c; e* c
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
    $ x% k% X% Q+ H8 J2 c
  201.   {- w5 P1 ]! X6 q0 {
  202.     /* 使能限制操作模式 */
    6 h8 x7 X9 A. Y% i$ H
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
    2 l$ \, y3 U4 v1 m& h
  204.   }
    3 q$ n; m, Y7 h; J' L4 a4 I
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
    ' I$ a8 u' M' M7 x7 K
  206.   {6 E( x+ N! U7 v5 L3 Z
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    , `3 H- M: c( s) I. v
  208.     {- U1 r) o1 S1 A9 ?
  209.       /* TEST寄存器写访问使能 */
    1 A1 y% |5 j) m: c6 b8 d8 q2 l7 c
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);0 ?" G' [) \: S1 {& B  ?% z
  211. 2 {+ t+ q8 }( k6 j& i3 Y
  212.       /* 使能回环模式 */
    ( X7 s4 h3 q* |  i0 I- D' M7 T
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
    8 \% H0 X9 [+ h
  214. 4 i8 {: k4 H: k3 e* ?
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)7 Q0 V$ ]8 ~( x" M0 K+ R
  216.       {; Q9 J; p- N5 |
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
      }' m) e" U% [% W' t
  218.       }2 _3 ^; W5 }# _2 r$ a# a5 k
  219.     }# a( p' [  P/ [& L/ d4 }
  220.     else' M0 v# Q% y- K7 w) ?
  221.     {2 C- B- l* X" F: U+ Z$ B; d
  222.       /* 使能检测模式 */
    7 ^; ~2 E$ l/ c
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);! G3 A3 [6 Z2 l! g$ o
  224.     }
    ) W0 Q$ t+ F, X6 c9 U2 M
  225.   }
    6 O+ n# Q* Z1 S1 a- }. O
  226.   else( J7 W- o9 W* X' R
  227.   {* o5 K7 Y! k; z# e& l; r$ N
  228.     /* Nothing to do: normal mode */. G1 z. O2 k% T' e+ _
  229.   }
    2 y) Q4 I+ I, S: O: f
  230. 4 j4 H" L. P+ c& K3 }) x" F
  231.   /* 设置nominal bit timing 寄存器 */
    ( o; n( z8 e) v* h* c, ?. p
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
    , W* C* I. U- X4 |
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \6 n3 ]6 @. q% c, d: F
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
    + |) w* W4 g% [- m8 Z0 _
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));
    $ P) j$ N+ d1 \: y3 l$ \( W9 W

  236. * Z/ F4 R% V1 q. R. T: y7 V
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/
    & @7 _- e6 T  E- B2 D
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS). V% |: v% j. u/ ?4 T8 L5 N3 P
  239.   {' W( a, T* z: m
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \7 W6 e1 W; S8 ~, k0 g9 B) F
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
    1 F$ i  n$ F4 [! [
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \
    3 R* l. L% V  k8 V
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));7 E+ H' T4 V0 r/ a1 D
  244.   }
    ' O# W/ F& s1 ?

  245. & V# y( s; X' [8 n) a. k
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    2 Y& b# m7 s, }2 O; Y) l. J2 J# T# w
  247.   {
    , ~0 w0 v$ A* R: I- P  W" d
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
    " V$ m& |% e3 H7 N8 I) Z
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);6 T1 u7 e: t6 e% D# x' t( ?) z
  250.   }
    2 @1 c6 p- A7 ~

  251. $ |9 e- I5 J9 Z0 H% x4 _9 b
  252.   /* 配置Tx element 大小 */
    0 C- ]" F& v& C+ F6 _  x4 U! A
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    / v& v+ C: p. n3 @. x
  254.   {
    . E5 }, i. g# I  K3 E9 ~- f% |
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
    % x' J$ C" F0 j( u" ^( b
  256.   }
    4 Z5 A1 c8 \+ F% u3 h$ I
  257. 0 R. y* G0 T2 `
  258.   /* 配置Rx FIFO 0 大小 */2 y  p1 Y  f2 q/ U5 Q3 S
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)1 v' K+ ^8 D/ {( j& C! b
  260.   {
    2 u+ @+ z& I' `, Z5 f/ R
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));/ |) {; y9 ]8 W3 {+ m
  262.   }
    2 o+ u' k" x: t6 J

  263. & o7 K  _. D; g7 }  C- H
  264.   /* 配置Rx FIFO 1大小 */1 t% O9 ~. a; q: f' }' s
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)3 [+ X4 r1 Z6 ^" A
  266.   {! E4 y1 l0 P/ H8 w8 W
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));9 q' s( J! `" j( X" n% y
  268.   }
    , m* z# h  @9 S* h- i1 B
  269. 4 I$ u: J4 l- G; D% S# @
  270.   /* 配置 Rx buffer element 大小 */
    : B: o9 t4 \% w+ f
  271.   if (hfdcan->Init.RxBuffersNbr > 0U); Y* D0 z! R4 ^. S4 w# v) S6 x
  272.   {
    3 X; s8 F- v5 @% }2 i/ g0 J) ?
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));
    # z  Q2 T! [$ \7 G5 V8 \6 a
  274.   }2 ~4 V; R6 k. y* b0 i
  275.   O( q% \3 m  k* i
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
    8 ^4 O; Y! W1 h* N8 |  Y5 z: g
  277. 后调用HAL_FDCAN_TT_ConfigOperation */! T0 o# j: ^! t
  278.   if (hfdcan->Instance == FDCAN1)8 L# g) e. ~- |% j  [' u# L6 e
  279.   {: M: C* ]: i, b/ Z4 f! c2 h
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);8 c8 {9 K4 k) u& e9 ]3 [+ j& g
  281.   }* u) b% ~) M. u1 U3 \# t
  282. ' s$ V% I9 X: ]7 B4 O: f
  283.   /* 初始化Tx FIFO/Queue */5 S8 W* D- i4 N5 w) C9 [
  284.   hfdcan->LatestTxFifoQRequest = 0U;
    , x0 W) _2 y7 y7 p; A5 A
  285. % \6 A* Q' R( x
  286.   /* 初始化错误码 */
    . G4 O* K' b5 T" v1 A$ z$ {
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;/ q' G; F9 R1 H$ s  b; I! Y

  288. 6 T) T2 X2 X6 n/ {# v+ |
  289.   /* 初始化FDCAN状态 */* }& R9 ^( g: z1 S* u  [6 m3 A
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;9 U- T/ p: L: }- ~! `, m2 g) h, L0 e

  291. 8 o( U  m9 j, V- |  g% I
  292.   /* 计算每个RAM块地址 */8 M( b& o+ {$ v% Z
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
    ) j; J' I1 o$ M0 _4 a
  294. 1 a2 g! n' y7 _& X# R0 g
  295.   /* 返回函数状态 */
    ) E8 f: H# Q  F; d( K
  296.   return status;
    2 Z* ^; g% o( [+ K! h; ?; S0 i
  297. }
复制代码

9 M' e' k. `0 w' b! p函数描述:/ d& O) K3 l6 j# C5 r; z+ K' c/ ~

8 \. L3 T, E& e9 j( V; P- S此函数用于初始化FDCAN。
. |( m7 w; g: y$ |) `$ t
* T# a) v6 c- a; H& ^4 Z函数参数:/ i( E( P* u- Q- o9 U$ c

) [% ?# X  O4 |% I2 n+ U" I; N( `  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
! R9 ^# p( C' q: V. r  u9 p! j  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。8 w8 `* j% V6 t  e' |
注意事项:6 y, o4 R) j! z2 G2 @) o

7 A8 }2 K+ v) v  L% {3 p9 C) @4 t函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。( j- n4 x4 c1 z0 h* i' ^
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。0 F  P) ^' `5 Y  ^
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。/ @  M& I1 O; P7 S9 Z$ {) N/ a" ~
7 R6 t% S  C  T7 v
解决办法有三+ _; R7 e9 K6 ?  z0 J; I
9 [' R# l$ d; q$ d" W9 C, O
方法1:用户自己初始化FDCAN和涉及到的GPIO等。
/ o. [( X' A- o/ K2 [+ Y* i$ z, {' ^: w" C1 I
方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。
% u% ~% L) R$ z( [$ L1 \. I7 F/ ]4 M. X
方法3:下面的方法, h9 ~1 I& i/ ?: \6 n$ S

0 U# O# ?' V1 n, m  ?
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)
    - f" F( O. l. Y5 T* f5 Z* y
  2. {
    9 ?& P$ I8 l; t% k& b  \: i
  3.     Error_Handler();6 P+ t, i1 i; G2 G
  4. }  
    0 w2 l, V5 y# \/ J
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)- J5 n& c" p0 x% P; B' x
  6. {
    & X+ m3 B2 K- W: M- Z
  7.     Error_Handler();
    8 W" O! W7 q" _" R7 z) i7 D: O
  8. }
复制代码

  e% q% c) E6 W* M$ n$ W使用举例:
  e( @) O% `9 E/ @7 V3 w# T4 e3 A+ F5 n7 N/ u8 ]: p
  1. FDCAN_HandleTypeDef hfdcan1;) F$ R9 `9 j6 W2 D) L' T
  2. - F+ S+ l3 R- |/ m
  3. /*4 J' r$ W' v( u4 l% s: D4 B
  4. *********************************************************************************************************
    4 ?  b- |! H$ j" C8 g% L0 F
  5. *        函 数 名: bsp_InitCan1% {& B- D$ `  s1 n% H% |6 }
  6. *        功能说明: 初始CAN1
    6 g" Z7 Z' V8 V; t& z
  7. *        形    参: 无3 G( q% t: E8 |% c. W' A1 n: b
  8. *        返 回 值: 无# |% ^4 ?$ K8 k5 y# d
  9. *********************************************************************************************************& a% n4 Y# Q1 g$ \3 Y
  10. */6 w& e- ^6 X5 o( N. x, C: T: F
  11. void bsp_InitCan1(void)$ @; b4 J- ]! p: R7 K
  12. {         / w) I# G" T( W
  13.         /*                    位时间特性配置7 V4 i4 B" x4 i, j# `. H
  14.                 Bit time parameter         | Nominal      |  Data; d% X1 o. t7 H8 Z" @
  15.                 ---------------------------|--------------|----------------
    6 ~; K% S/ q9 Z" y2 W9 M" O6 b$ s  i
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz1 r0 I! @# U  H$ f$ S6 T3 M
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns4 k* b( ^  l. d. }8 i+ ^+ Z
  18.                 Synchronization_segment    | 1 tq         | 1 tq
    9 P* J1 y- y6 Z; i
  19.                 Propagation_segment        | 23 tq        | 1 tq
    " b$ z2 m8 X4 |
  20.                 Phase_segment_1            | 8 tq         | 4 tq9 n" |2 N& M5 I' X
  21.                 Phase_segment_2            | 8 tq         | 4 tq
    " m' ~" K1 O7 X$ Z  u1 p
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq! t, U7 q$ J7 z" H- x$ l
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us: N5 A- O, c2 A8 X& S
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s2 P2 A  ^0 [! @0 B2 d5 {$ |" Z
  25.         */( N  ], C# F+ E  o2 R. X
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */            
    3 U  j. S# l  ^: w! c. B
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  " t6 y$ V& `: k/ a
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */
    # E6 v/ r7 s4 ?3 i/ g
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */
    * J: F5 j- |! o6 ?
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */+ s; |" n/ g, q/ o4 U+ H% F
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */
    3 g# j6 A6 }! U$ O6 N$ P
  32.         % e7 s6 P! c5 L) Y
  33.         /* ! Q& |- ^9 ]# J* X
  34.                 配置仲裁阶段波特率
    2 l7 v3 K" N; P% M
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是
    % z/ M" \1 p$ n: `& v! z
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        / Z' ]8 A. k; v( P* l
  37.                
    % h. S. {  n7 H) K
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2. ]+ g- ], s! p  m1 |
  39.         */
    " t% [( @' O  U
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */! |0 }+ S3 G* J" {. q8 L- w9 y
  41.         hfdcan1.Init.NominalPrescaler = 0x01; 0 b& \' e* f9 E$ l; H- w
  42. - H0 ]# V* Y9 }
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */# D2 Q, s0 f7 a
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08;
    ( B" E6 H' s! O

  45. 0 L, d5 r+ O, \6 P) L3 M+ J1 }
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */' [! m/ Q& C1 J3 P- H  H
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;          ! M' m6 Y- }' H2 a1 `$ W4 f9 M/ ~" h
  48. ! R7 P6 {* @5 n/ f3 G7 }: d
  49. /* 对应位时间特性图的 Phase_Seg2 */
    ; r! Q( l& c1 V( @) s' u
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     
    0 o) }+ y( Q6 X! J9 `: B
  51. " e, U% W  T  K5 g, D% f

  52. 1 b! V* q8 v$ D6 ?# l
  53.         /* % G- x8 ]2 {* k: ]5 W
  54.                 配置数据阶段波特率 + l4 `7 I. h. E$ P) r! V
  55.                 CAN时钟20MHz时,数据阶段的波特率就是  W5 K9 }% n" e5 X
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
    " V* c0 l( X/ ~- m. \
  57.                 / C" F, ~8 ^3 H! ~+ |/ p: K( \: b+ @
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2
    ) @( M1 {1 H) i+ Z
  59.         */# Y0 b' a. E) T" q3 U$ x
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),# C- a9 E" R! v* J( @
  61. 范围1-32 */
    7 {, ~9 r0 O- W0 C2 f. n
  62.         hfdcan1.Init.DataPrescaler = 0x01; / o4 a2 f5 g% s
  63. ; Y# e1 K: m: c; W+ j, @% u8 l; Q
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */2 r, Y. z) t1 K) ?% Z2 h
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  
    1 M% W3 b7 y( G0 }8 N7 o
  66. / u0 Y9 |+ L& o, A
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */1 b6 _. k# i! P& A7 H" B7 |4 ]& h
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05; + T3 M- p; P% V2 I6 T  A

  69. ' H: ?/ O: g7 W
  70. /* 对应位时间特性图的 Phase_Seg2 */                ! G7 R3 ~9 o: y" M
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           
    6 v) y" ?! l$ R- Z$ Y
  72.         
    # X) J  F( A( w% N* `2 b/ O% l7 q
  73.         * e+ c3 c( a" e, M
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */) o0 z3 e6 s0 i; W, e9 d
  75.           {, ~2 Q" v# s. K0 ~+ a$ k
  76.         * h9 ~8 h* T# e' l. n5 {+ ^
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
    3 j7 U! Z5 S4 A4 x- K5 e* W' k  s
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   9 |7 ?+ y2 G. L! d7 V! d( n6 @
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  ( x) a* u; M/ k
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
    0 v6 E/ Q, ?9 z
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; $ v5 {8 r& X  ~) o) v# O( F
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */
    + z' G3 F0 d4 N  u& l

  83. ; T; c4 l: x: a% W
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        
    * B% F+ @, k5 w6 L0 p/ h. c$ ~
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
    / Y2 w3 o/ ~2 V& D
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
    3 k1 w1 q8 c6 V8 B$ x  I
  87.         
    ( z3 }% P; q  B/ v
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */4 {: |; s7 h7 M  l
  89. hfdcan1.Init.RxBufferSize = 0;                             
    , M. Z+ Z- s- J( t: n  u& C, w8 \4 y* S
  90. % ~5 G7 y. ^6 Q3 T
  91.   }! n% @% ~* K+ X3 q3 |! w/ T
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        . f! ^! ~! D+ r. x" c5 x0 t/ r4 U
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
    4 ^2 H; r- P6 {0 J' \. }- `9 X1 f
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */
    * S! f/ _6 {$ z' X1 i
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    - p# F7 ]9 E$ S5 i. G$ R2 d
  96. 7 l: {8 j9 L( H/ A
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */
      p* G' b% Q/ @8 \" i3 d0 Y9 h
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;          ' `) g$ G* A) N; _! P
  99.         HAL_FDCAN_Init(&hfdcan1);
    + M' R  \7 ~( |' s3 F! a: V: U

  100. % x5 ^- Q3 J3 ?1 H& `6 H
  101. 1 t4 S* w8 {1 e  ~  w( r
  102.         //省略未写' M' G+ p! R7 B% H' I! j- J
  103. 4 L8 q1 Y3 u* A1 L
  104. }
复制代码

; {. Z5 w' I* M/ \91.4.2 函数HAL_FDCAN_DeInit
, t# @9 ~" i/ U5 B函数原型:5 ~6 |+ _1 j+ k! p7 E/ S3 q9 o9 V( f
. C" ]+ ?" m& o7 v; s9 |& a
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
    1 u+ n& I1 e6 K2 u( g: t
  2. {2 X4 H. Y# d4 C$ V& p# a
  3.   /* 检测句柄 */
    # X" {+ l  ?" F+ `4 N) u* G
  4.   if (hfdcan == NULL)- s. r0 G$ H# i+ k- Y5 v
  5.   {
    8 P3 L7 s# B4 \; M
  6.     return HAL_ERROR;
    . I1 e5 j$ k( ~6 W; r
  7.   }" I  C: n# N& U
  8. 0 X; s3 V7 s( [
  9.   /* 检查函数形参 */
    % c6 G1 C' [% p6 k( l6 L* g0 I
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    4 N% V4 H( m% ?: q# e

  11. - n; K) i' }. S7 V! e
  12.   /* 停止FDCAN */3 d3 R, H+ q3 W% A, N2 a
  13.   (void)HAL_FDCAN_Stop(hfdcan);0 j' i" g8 ^. L/ I+ V5 U
  14. % K. @0 e/ c' z8 j! w- q. I/ N
  15.   /* 禁止中断 */
    0 o# D$ s/ o0 _: Q8 q
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    6 Y4 I" t/ r1 \. f
  17. 1 ~+ D; _6 |! a: s0 P$ ?) R+ L
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    0 B. [( p; N( k
  19.   if (hfdcan->MspDeInitCallback == NULL)
    - M" V; t/ B& @3 _. i' I1 H
  20.   {
    " Z9 ^7 n& l  B7 f# A  f$ ?: ~$ G
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */' L, ], u* \! O. ~" r3 S' V
  22.   }
    : J6 r/ B9 L& G! {2 L5 j! T% [

  23. 0 Y& ^; D7 ~) V9 F/ ~, {( Q+ T
  24.   /* 复位底层硬件,如时钟,NVIC等 */
    ( N- Z0 s. \# G2 B9 v0 f
  25.   hfdcan->MspDeInitCallback(hfdcan);% w- C( U: P7 c: s# j; P1 M! _! g
  26. #else
    ) p  y3 {! ^5 w# `7 ]
  27. /* 复位底层硬件,如时钟,NVIC等 */
    ) ^& }+ m6 K* K2 _1 K  J9 I
  28.   HAL_FDCAN_MspDeInit(hfdcan);
    $ [3 ^1 R6 q; m  P8 {2 H  P( t/ D
  29. #endif
    6 T* D; R7 P3 N& {; M- u1 j; g* _

  30. 5 `. G+ S/ P/ y$ Z; ^2 C: ]
  31.   /* 复位错误码 */
    4 [* ~- y& O' u3 v7 \3 Y& S8 y, L
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    2 u+ j5 e$ Y9 g' x2 K# L5 I) z

  33. ( V9 P9 j! h* b7 ?
  34.   /* 设置FDCAN状态 */
    5 p9 e2 N% c, p8 t
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;0 R2 z$ |2 x- C0 c

  36. * `( ~  b7 B3 T/ s/ ^( M/ [! {
  37.   /* 返回HAL_OK */, z& ^% x4 X5 S3 b1 A# w
  38.   return HAL_OK;: B6 O) B0 r, f1 [: {, m
  39. }
复制代码
1 I. O8 @6 u9 w
函数描述:& f: S) n( V) X0 m% l& l; x: j  I

/ }) E* L& K! y3 U, {% o& g. R4 J用于复位FDCAN。
. |$ v# _# N/ Z  j4 u
/ W( G" x( F) K" H函数参数:
; ]+ R4 Q, A9 x* J/ d) K+ V0 {8 W) N  }2 I
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
: g1 u. W7 I2 |# @  O6 }7 @, _6 a  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
' e0 Q! W7 G+ D91.4.3 函数HAL_FDCAN_ConfigFilter. B" Q8 y2 l+ t1 J: H- J1 o1 D
函数原型:" ?/ x7 b/ E3 H, a9 B. o1 D
6 E) ~4 C* v* _
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)  J6 N7 G. e- ]$ E9 e
  2. {
    ; l3 J, x2 i' t* ]( s& @/ ~! J) @
  3.   uint32_t FilterElementW1;
    9 p  w8 @- x: Z, p1 I6 Z
  4.   uint32_t FilterElementW2;6 o4 h* h5 @9 N, H+ d6 S
  5.   uint32_t *FilterAddress;  m+ j4 I4 m& i* f! ~+ v' O
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    , a( x  |+ O$ V9 ^
  7. ) t9 K2 c3 C4 r% d! ?  s
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    ' x0 m$ C) t/ b; D! o: W
  9.   {
    7 R+ x7 f# z- T' i
  10.     /* 检测函数参数 */
    4 [' \7 J7 t  m# C/ W# n2 q  u: b
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));$ A3 l9 c6 W2 I
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    : z2 w3 i$ i) v7 G
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)$ H5 K* L9 h2 ^/ c4 ?" b# i% j
  14.     {" G) f! A( B3 ?0 k( n
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
    3 O2 G8 R+ ^! H) M
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));) V( I& S! h) c, I. J# Q
  17.     }5 m2 l+ D9 N) \
  18. 1 y$ @2 L8 z2 ]' K/ S
  19.     /* 标准ID */4 T& a0 O/ l/ @- m6 e5 @! H/ g6 q( ~& Q
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
    : H6 \- i2 V5 j0 H% t6 v* ^
  21.     {
    , v* `6 \. Z5 {8 W# t- V
  22.       /* 检测函数形参 */
    2 o+ w4 u* [; ~/ b, A: i
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));1 S: S6 Q& F6 j
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));9 O# i" B' U! W" B
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)) @" A+ {  w7 N3 y$ s
  26.       {
    9 }& m; ]" }) p2 H# |" b" a
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
    3 j1 d$ E5 }* S) }1 c' N% ?# J, e
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));; U+ v: [9 n" H$ N8 `. Y4 B* e
  29.       }7 H; @* F+ q1 J& R; t9 V

  30. & y6 X8 f9 _! {1 O" J
  31.       /* 构建过滤元素 */
    3 ]% L2 k; h* E  O8 g
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    5 i/ D8 p( q: v
  33.       {3 v: F' l' Y% G4 _: ?6 _
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
    / y$ s+ Q  Z& b# q0 A
  35.                            (sFilterConfig->FilterID1 << 16U)       |8 q0 B0 J# N' L% u: e% _' `
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |! B9 n1 M" x" U4 `
  37.                            sFilterConfig->RxBufferIndex);
    9 m" I# y- Y3 J! i
  38.       }6 V+ T3 w7 U. W. b8 T
  39.       else$ R* C  u; ]3 `1 u2 ]* i8 G1 x
  40.       {$ i3 x& ^$ C# h9 S, y
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |
    1 }* R2 b. h0 e' c+ m  S$ U/ T
  42.                            (sFilterConfig->FilterConfig << 27U) |& n& f$ n; Y& p
  43.                            (sFilterConfig->FilterID1 << 16U)    |0 g% p% ~) U" g* M7 L. f* J
  44.                            sFilterConfig->FilterID2);
    ; @7 i6 |) e. V  b& i+ M
  45.       }/ j. f& z. Z# G( B. k

  46. / k+ t; y- H6 @7 Q6 u5 r
  47.       /* 计算过滤地址 */6 x$ B6 l( Y( l" H* n
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));2 M: [" _! I3 h' h/ d- e) U0 ~& t' K1 f

  49. 3 ?+ S3 L* K5 r! n- q0 ], O6 ^
  50.       /* 将过滤元素写到消息RAM中 */
    ! G% K* j  N" Z1 Y
  51.       *FilterAddress = FilterElementW1;
    ! ~# h" r2 Y' ~. g6 ^$ J
  52. }) ~5 W2 b4 c' e: U/ T" ?
  53. /* 扩展ID */
    3 {8 H/ J3 `) _7 x6 C2 |
  54.     else / }/ r6 V1 F4 ?" Z0 q- E* U" J
  55.     {
    : x* {6 s  X5 K# U) @9 D' @0 O
  56.       /* 检测函数参数 */* y9 W4 w3 P6 @+ T9 e8 S5 ~9 p
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
    + Y/ v' Z0 G- q6 m
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));1 U+ J# e9 d; _
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)' M$ R1 c  ^, L) d) A1 G4 ^. L
  60.       {9 k3 P' ?9 X/ d8 M+ e/ g& n6 a
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));' T3 o* n4 `$ B  H7 Z. ?
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));* q8 h5 `( c% K! r$ R; U1 m
  63.       }9 Q( m$ |( X' R& l3 E! q
  64. % z, `1 x3 {% [9 Y5 y
  65.       /* 构建第1个word的过滤元素 */, A# h) m; t0 b& u
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);5 ^# m( z& z% T% @

  67. ! L5 c) z6 l# u8 V
  68.       /* 构建第2个word的过滤元素 */
    ; V# m: V* y0 s* |. b# ~
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    9 O, }; `/ }! j" S3 e- e  [0 o9 L
  70.       {- I- A4 {) l' J/ o  X
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;
    % i  _" A' U% D% F: Q
  72.       }1 ~8 l$ X" o7 g) T; f* T3 ?/ z! f$ Q
  73.       else. i. U/ \& V) O
  74.       {7 J/ u6 \- W0 W4 x+ Y5 v; [
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);1 E0 O+ p6 S" v( A1 F- V" y% E
  76.       }  h% O, L, e" k7 z$ Z1 j2 c& o

  77. ) l  G) B( Y: e) X: a7 G/ x
  78.       /* 计算过滤地址 */+ U  z# x$ z+ z9 w* Q
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));
    6 c+ p8 k' Q8 A' z& x
  80. 2 G) V: t1 F$ e9 c, q
  81.       /* 写过滤元素到消息RAM */
    8 V0 {6 V  m( _1 A
  82.       *FilterAddress = FilterElementW1;6 D# @3 w. p  Y4 @+ K4 E! c, F0 n. ^
  83.       FilterAddress++;
    # e% w9 A+ R0 E
  84.       *FilterAddress = FilterElementW2;4 ?  z, n0 ^) x* ^& x! a
  85.     }% |5 \6 I; A/ P1 v2 T1 M
  86. * e1 K- m7 I* X9 y$ }9 @' \
  87.     return HAL_OK;
    ; S9 K0 I. c3 I
  88.   }4 X4 |! F& y! ^' C
  89.   else
    / ?# p3 h) w6 y2 W( A# j# d/ H
  90.   {
      u% w$ A# V; u* w0 n5 y& V
  91.     /* 更新错误码e */
    1 O: _4 q1 V+ g) T0 K, {9 s
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;3 z6 t) n( |! ?7 `

  93. 2 ]: V; l3 I/ h! K1 |
  94.     return HAL_ERROR;
    % j' m) a6 r  U
  95.   }; a& b, C# \" H, [
  96. }
复制代码
0 ~' e6 S5 M' q# a+ _7 ], z8 q
函数描述:
1 |0 {3 ?: w! u# A4 A# t( Z8 n! |1 U9 b  m$ _/ m. r
此函数主要用于设置FDCAN过滤。
6 E3 X, e, [5 W3 S7 Z; S. O; ?. |1 x
函数参数:0 N7 H; c6 V. b  u" _
, v! G* w8 g' C- O
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。/ R9 X+ S- d" }
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。' }. H- `4 T3 H& F+ P
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。7 d% Y% s" ~+ a& K9 _0 Y
使用举例:
& W% h. W; j1 U( T0 `: M( _0 ~. M" \& }% K
  1. FDCAN_HandleTypeDef hfdcan1;7 K1 m+ ?7 |2 [9 D

  2. ) F% w0 P$ ~7 Q* ~' S& j7 k# @
  3. /*% t; _% J1 h9 ?9 m
  4. *********************************************************************************************************/ N" ^) e, {5 ?/ }$ c" d
  5. *        函 数 名: bsp_InitCan1) i' t1 R' @: f# ~* P0 y, C' W
  6. *        功能说明: 初始CAN1
    0 r2 I1 b. L/ _" n& K# M' S& ~* V& @, v
  7. *        形    参: 无
    & l$ ^: G, l! _8 h/ V4 |
  8. *        返 回 值: 无. ?* C9 m- s' M8 q0 k& W, {2 v" Q+ ]
  9. ********************************************************************************************************** i* X, i6 {$ A/ C/ A
  10. */" O) q7 P; K/ |4 z6 v! L
  11. void bsp_InitCan1(void)' S9 d5 }. |% h8 K# U1 a
  12. {         1 d' I! d1 w4 J* n: N3 t9 m# i
  13.         : g3 s  [8 v# |: d1 m
  14.         /*
    * O0 i  w. R( k' ~" r5 r
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。& ]1 [0 ^7 E1 [2 M; h3 N8 [
  16.                 FilterID1 = filter' p2 W, f! g2 O1 }6 D) H
  17.                 FilterID2 = mask/ k' i; o; `# l% _9 W8 E8 z6 [
  18.                
    8 o0 K, K) `8 ~3 j, k' \0 s
  19.                 FilterID2的mask每个bit含义
      e" p$ H0 {5 i% Q7 [& a9 K
  20.                 0: 不关心,该位不用于比较;: J+ b$ O. q; |# X
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。
    , h7 {/ k% h: `0 n5 |
  22.                
    - R/ Q: U; s$ ^' _0 J
  23.                 举例说明:
    6 _5 n6 C+ p  U4 i- V& Q
  24.                 FilterID1 = 0x1116 p( V" K4 B) p, g
  25.                 FilterID2 = 0x7FF
    1 @) s9 P, `+ E6 u. d7 O
  26.                 表示仅接收ID为0x111的FDCAN帧。
    1 J% e" H3 c! D3 {* X
  27.                
    * b; N0 s. H6 l- b& B
  28.         */
    4 b3 |8 w( r; i( S
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */. v' f" i; W+ |: v, t* d
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
    , h0 @% a- N) R, q0 J
  31. sFilterConfig1.FilterIndex = 0;                                                   
    + v! x( ]3 H1 w. Z
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */% o+ r6 r. _6 z* R$ o
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
    " x% Q& K2 I% q; H
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
    8 d* D, N7 M2 T' H
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
    1 v: q0 u: U0 f( G- s5 `8 n6 R+ t4 O0 S
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    & p+ p$ E: A$ g
  37. ) N. k! s2 Z* `" _; ^! ]
  38. }
复制代码

. l5 Z; |  L$ {" I91.4.4 函数HAL_FDCAN_ConfigFifoWatermark; o; Y- a) ^  u7 z* r) k2 R; ~
函数原型:
. y; v3 X; K  o/ y& }" m, J, h: ~8 o
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)0 c0 D0 C( z# g
  2. {6 |" L% T- ?4 |+ n
  3.   /* 检测参数 */7 f8 C+ m  u2 ^! S& \
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
    ; R, ?$ Q) F0 h0 Q- e* v7 i- s) Q
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    5 g7 J; f( ]$ x/ S8 e6 y. h. F
  6.   {
    / W+ t/ K/ I3 e+ n
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
    5 K, l+ L9 q3 y3 U
  8.   }7 B: |6 q3 a( D/ i) J" J0 a1 ]
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
    0 j, o9 i( Q" V/ x0 o2 k7 _
  10.   {
    3 P0 w- ?. E5 G5 c+ n% `
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
    # ^2 `$ W# r+ W% X. d* J
  12.   }6 z; t' O! t: C% [9 U

  13. * a+ J1 k6 t. n3 w
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    . ~' f9 j1 d5 w1 S2 D
  15.   {: c1 H! V8 X4 s2 x1 l. \5 Q1 O# i/ H, d8 n
  16.     /* 设置发送事件FIFO */0 j% ]* y! _: ]+ Q% L% u2 o# H7 t/ h
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    0 i  U% T7 O+ o+ x9 e) E
  18.     {
    8 [$ @, R+ |5 i+ C8 \. Z
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
    : K; M$ N( l0 c' X" [& k
  20. }
    0 B# \# @2 W8 U1 F! c2 s
  21. /* 设置接收FIFO0 */8 v3 x" y, Z4 `* h
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)" ^. I* A- o/ C: ^
  23.     {
    9 a1 B+ `0 W9 N+ B4 v
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));' W1 \% P$ A8 T! e% d2 c% I$ y' c
  25. }3 ~- G% a' C# P# Q
  26. /* 设置接收FIFO1 */  Z7 k! Y# v* y, {7 [& ?! f- U! r- V
  27.     else
    / a2 `! e7 e0 L+ {
  28.     {* h! C, k3 p$ W' i1 [# Z
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));: L  U1 {; u, @$ \* s/ d: Z. l
  30.     }
    ' ^1 n* N% A6 R. q! l. ^; V, }7 R
  31. 9 ^( _% V- O* v( J8 l
  32.     /* 返回状态 */
    2 O2 H8 b# w/ r
  33.     return HAL_OK;
      P9 x) E& z8 r% G9 F8 F" I  ^
  34.   }
    . Q5 j" g, ]6 V* O' o/ g
  35.   else
    # B, X" S. K4 N' @8 c+ r
  36.   {
    ! G3 v  O7 y* z. @/ B3 O1 ?
  37.     /* 更新错误码 */
    ! L/ t, c8 t2 h- T; l8 @
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    + }; ^+ ]0 l0 O; c* b5 J/ _, c

  39. - {5 Y4 G+ Q8 `; m
  40.     return HAL_ERROR;
    ; W5 X4 Z, [2 }+ a
  41.   }
    & o- H1 u3 A0 j* N
  42. }
复制代码
; Y% _% ?) A* F4 z
函数描述:2 V( U9 q/ K1 e, |6 F$ T& O% ]# j& l
' d% X' }7 X) x' `! R
此函数主要用于配置FIFO Watermark
2 M3 _: O' s' [' ^& P+ g! A8 a/ B/ L4 V
函数参数:. L& r6 Y3 o8 U/ |7 p# d
: H& }$ C/ \/ ]  P/ j' m
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
( e& o4 U# Z" l2 g! B  第2个参数是FDCAN FIFO Watermark
, Q8 t! B& y2 D
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */
    1 i9 B; _0 D4 l; F# n
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
    , Q; [$ }3 J+ g% n/ s' S9 c. m
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码
- p/ V9 Y0 _5 h9 _; c; B8 x
  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。
7 p/ _5 I. H" C  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 V2 I: D7 m: t  i7 K/ D5 }
使用举例:2 H+ Y8 ^3 Z# g) Z; e$ z* X

! r8 @% g$ D( X4 I
  1. FDCAN_HandleTypeDef hfdcan1;
    + |5 A1 y! L5 E& s# }) ^% F% B
  2. : m. |3 X3 u/ j: I3 e+ g7 {
  3. /* 设置Rx FIFO0的wartermark为1 */
    9 x9 w/ [) @! Q9 f) d4 V) `( h4 c  ~
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
" h3 q+ e% G  _3 x/ g
91.4.5 函数HAL_FDCAN_ActivateNotification
2 q% t5 Y; r% x# y0 Q. i函数原型:
% W% i7 B$ H* A" J% ?/ ?, K/ ^
4 t! |9 A2 B) I/ M( s
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)
    ! q0 l8 Z) O  y, n
  2. {9 I: o+ z" q+ T  [& \$ C8 d
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;& d/ s3 h! P: K1 W5 {1 j2 v

  4. 0 F  S! d' M' W  u* a5 P1 e( }
  5.   /* 检测函数形参 */
    5 E  K! y% t! W
  6.   assert_param(IS_FDCAN_IT(ActiveITs));4 X2 _* r! R6 I  t; F

  7. : h* s7 l6 O! W' Y
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    % c7 q' p2 V* ]7 x* ^! |3 X$ D
  9.   {
    9 O$ z" D. c% G$ S1 D
  10.     /* 使能中断行 */: V- ~4 O' N( Z! ^3 F- ]  h$ [4 _
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
    7 V# @3 ?: D# o1 n, v. \1 ?8 e) u
  12.     {6 J: h1 _% o) ^5 N6 h9 R
  13.       /* 使能中断行0 */# E9 [* t% l9 V( p3 `5 A# T. [/ ?
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
    0 Q0 e' u. a) O6 I0 C) y
  15.     }
    & r$ L7 z9 y) C1 O# @: q
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
    - c0 X, n( E5 g
  17.     {
    7 I* M8 z: N3 L0 q
  18.       /* 使能中断行1 */
    ( E2 R0 ~$ W* M  `8 s5 h6 R
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);; r4 P5 v1 c: E$ Z7 _
  20.     }3 ?( e) g3 j/ F$ z5 L; b: z
  21.     else
    1 G/ F0 o7 f" ?/ G3 }( B( U
  22.     {1 d9 y0 M6 A* p0 U+ s2 Z
  23.       /* 使能中断行0和中断行1 */
    ! U. G, B0 B$ J( ]$ U
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);7 `7 G. p5 M) m; e6 @3 J4 A
  25.     }& B, ?# [& m0 M+ u( G
  26. 3 S) ~8 Z, X, v; K
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
    # O2 r. V0 l9 ~1 Z
  28.     {
    ( M0 X! N. z! N4 m
  29.       /* 使能Tx Buffer Transmission 中断 */# D3 D) T, g: u8 H* A; J
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);/ Z& P' D  e) M* l
  31.     }
    2 o$ V: E$ T& @1 y- k% K8 G
  32. - q5 |8 @: g" V3 i, F1 Q
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)* T3 a5 q/ Q+ F. V; S
  34.     {
    7 }$ B8 l) M* U7 Y( c
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */# c( [1 L" M) s( Z+ w
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);
    , a; q3 S. {( K" Y
  37.     }" N- e& h1 K: W3 [% `9 |& s
  38. 2 f; g" a0 V2 Z9 @" T9 F2 `
  39.     /* 使能选择的中断 */+ Q' j1 O# k8 W5 t" F
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);5 \+ T" V- ?( T7 @& v6 s/ _. T# D

  41. + d7 r6 k( A% ]7 n" h
  42.     /* 返回函数状态 */
    % `+ @. z8 ~4 \6 Q3 X2 d
  43.     return HAL_OK;
    6 {0 W, m" M+ Q. n% C" J, m
  44.   }; N6 [+ D- v. |' L; V" j: z( A: q
  45.   else
    + w$ B& S! x/ b4 u9 [
  46.   {4 Q; S7 J; G$ y* F7 I
  47.     /* 更新错误码 */4 p5 |: A7 ?, @  I4 B) c4 q
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
    : p* r; B/ n9 ?% }1 E
  49. / k( S6 {$ {3 r9 k
  50.     return HAL_ERROR;, r! H. w7 l+ A, Q6 ~$ L
  51.   }
    * U; p6 l6 B: L. u  X
  52. }
复制代码

/ Y1 }0 y) l6 C函数描述:! F5 u" o" X5 ~1 q
7 u* P. l! U6 K
此函数主要用于使能中断。) h, D$ n; I" S/ F# j4 }$ N% h( F  d
/ I* `% `6 L( `1 F
函数参数:
& l: S9 A& A/ S! y7 [5 U5 u  |( b* y2 u3 y2 m, u5 `
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
. X* f" J: K$ G; Q+ `  第2个参数用于设置要使能的中断,支持的参数如下:$ f! K0 k4 y- ]% y
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  
      u8 u$ i1 p; Z$ G" y$ K- ^. p5 e! b
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
    ; Z2 s3 I( ?3 y3 g
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         
    - b5 p- U/ J2 r  x& z; o
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */, g/ u7 ^  ^% f
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer 0 Y6 H7 I/ y! E$ B+ G
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */9 m. c8 {  M) K8 O1 J& @3 f+ O# p* G2 k
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */
    ! i6 @: d5 L& _6 E

  8. 5 C. o, [% q" w! J/ n9 @
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
    # |, L5 C. ^0 c$ R0 f) x
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred
    1 B, d  ]; [5 R0 z" Z- t8 S$ A. j
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */8 j2 v% A8 J3 M* Y) b
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */  R& y: s  j* N! P+ J( L
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */
    " E3 t2 L- H, v
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */3 d/ m! Q7 I; W

  15. 7 l$ a" ^7 r, B" Q4 M3 F$ [
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */
    4 F4 `7 o- Y6 w& j3 I, ^* y& c* Y
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */5 n( _. |5 Y1 K. M$ b6 T" j+ r
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
    % x1 y' \* t/ ^+ M
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */
    2 ~# ^1 f* x4 `; X6 W
  20. % x2 w/ J0 N5 [$ x
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
    ; s! `* G3 b; D7 c! A- M$ o
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
    7 v4 ^* G' B( \! x7 s2 X7 G
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */4 m/ h- a+ |3 D) |* b. \0 l$ _' {
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */0 r3 H% L1 G9 ~/ J8 a- P
  25. 5 \0 d4 w. @( T' S! T
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              ; E3 x5 W6 X/ ^, i2 t8 H" c
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred - `2 _% D$ T; Z1 `+ X' z/ Q
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
    6 G3 c; u1 z$ j1 C1 k8 E8 `. H
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     
    6 @& X+ U! B5 R# I$ Q
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            
    ( F' Y7 G' D! C  k4 m! O
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              
    1 V( t2 ]) J$ }1 Z# ]' G2 M( R& q+ }
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
    0 ^2 z& K. {" x6 t/ C4 N% [
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */
    * ~- l# J/ r8 T) N
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码
$ r4 [- J  @! s! ]$ i  q! c3 f
  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:
3 d7 S. N3 t2 ^' U
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */3 c6 u6 x8 z2 O  U$ s2 L) g
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */" Y: S. z" m) D; Q2 K8 D- Y
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */9 p  A8 Y$ t; e) T( k5 q+ m
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
    ! q0 }: l) }( ~+ r9 o. ]
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */9 P1 E4 n; G& g8 a! C
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */
    3 ^$ b9 `% q: J. b! b! q
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */
    $ I: t/ d5 L& b1 H. T( |* w3 ^
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */2 A% h7 H5 M( u" Z
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */6 y# S! F( u! T/ G. v
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
    - l" }  [" e; x) I# j  ~5 W
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */8 l+ s: ~( S9 T2 `8 Y( a$ x9 H: v
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */& w& v* G( q3 O2 t9 F  \' |
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
      W5 t; u9 ~' A# l1 K3 T
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
    : V( ?! ^+ y# R  R, N! p8 L* ^" H
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
    / t4 @5 Y8 |: B* u  ^8 ?" p
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */2 O4 g* c1 E' ~$ j. J  v, \2 V
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    - t' G0 ]7 O+ x, j/ ^- k9 H7 i
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
    . k) ]+ ~2 U6 P) e/ F4 m
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
    ! }' N& B( J2 [6 n
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
    % {) G6 s6 h: S1 _
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    ; @3 c; s; l7 K  Y, r) }( Z6 T5 `% E
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */
    9 T. g  I; }2 R( h
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */
    2 v1 v3 `. U. `% d, c
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
    8 @. W8 A+ m' L* L& z
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */0 o1 j* Y6 w6 I0 V% H
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */) Z# K% l% J. N
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
    + v+ f# P8 R* @: C! X% _
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */. i5 }2 U: F' U& A" ?( G5 }  ?  A
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
    ( n: w+ r- K/ Z, k  \5 n; l2 ]. t
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
    ) u7 B1 H  Y7 v: h" h  _
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
    " m  u1 i& {. f6 p* m/ T' m. M0 T  v
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码

, c  Z5 U$ Q  I5 N如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。+ u8 M) f1 Z. y
* ]5 {" s: W+ x& j
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
  ^& ?5 R2 b9 f$ t& B! `5 n使用举例:$ A& F* }  h! [7 x5 {

5 L. L9 W" x8 t) Z6 vFDCAN_HandleTypeDef hfdcan1;  q5 `% v. }9 g$ R" j' L! T
  ~9 c' q7 m' F6 v
/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/
1 ~, n8 ~& ?% BHAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);5 k2 T8 g" I( b( s9 y/ Y& d
91.4.6 函数HAL_FDCAN_Start
3 [! d/ x0 L9 D. d- R+ L函数原型:9 o- v6 b+ V  O( R

) W8 y! n. b" h& o7 M) P+ }7 x
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)
    * B" m7 y: j* o5 o, [( _3 w
  2. {7 U/ E" l$ l- r% F3 @8 L
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    $ s5 @# E+ P8 H' S8 d
  4.   {% v1 J! j2 m- S
  5.     /* 设置FDCAN外设状态 */
    % b, r4 z6 C$ f% \% K- P( Q
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;$ g0 [4 o- W3 k& _2 l" \
  7. 6 W9 t- w8 a& Q+ u, b1 U' g
  8.     /* 请求离开初始化状态 */
    & ?% }6 V5 C% P1 b: |
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);+ ?4 u7 o3 u3 c8 z# ]2 T' R2 G5 |

  10. 3 b. j3 X% g+ C0 z% |; L
  11.     /* 设置错误码 */1 ~' ^( y/ @8 h5 s# T+ v6 H
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    7 I( J, _! E' H5 q( W
  13. " Q& N( k! u8 C1 p4 J
  14.     return HAL_OK;
    : R9 V, |! F: E& {, ~6 Y9 F' \1 Z) `
  15.   }8 ]( f5 f3 ^2 o& M- t& ^6 `
  16.   else$ I( {7 w# Z' Y9 t
  17.   {4 @, m3 p# h3 W2 ?; u$ o$ ^# D
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    # W5 J0 J9 ~$ F! x2 G' I
  19. 5 {1 S' X3 b% e0 r3 g( A- t3 |* h, N* C
  20.     return HAL_ERROR;* w. l/ U/ }6 C# ~2 N3 b
  21.   }; o$ @; U' A/ k. U& ~
  22. }
复制代码

; R( f& f5 x. \函数描述:
, m6 {. i/ G+ u* P6 L8 w: S( q  I$ q" k
此函数主要用于启动FDCAN。
! N9 n: U0 U3 F' L. J- y& O  z* V6 f0 Z# W! W
函数参数:& g  q0 t! q+ ~; i/ p
" H7 [" c4 d% J, G
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
9 O5 Q. [% d: `/ C( V8 {' X  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。& y. V. o$ C7 x) f" P
使用举例:1 N+ r2 z1 c4 A+ g/ F$ P
5 k$ g3 a9 {+ d" U' X2 G3 P
  1. /**
    1 M! e, u( Y: U4 r
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.9 j% t+ |" J0 s  D! s8 L
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    0 Q4 C+ q! Y2 n6 P
  4. * @param  WriteAddr: Address from where data is to be written
    ; f, \# M+ G8 E7 M7 w
  5. * @param  NumOfBlocks: Number of SD blocks to write6 q9 L" ~7 d+ T+ x
  6. * @retval SD status
    , E2 i0 c" `3 w+ d2 O4 s
  7. */+ H: N9 Y9 j5 v7 n1 ^
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    , B; \' ?& J& {: D' H( k
  9. {
    ! i/ a+ i" }# N1 ~4 g
  10. % p; ^& x' {' N5 w3 F  w6 h
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    % d  i# y6 z! N( K
  12.   {
    , _& }7 F% Z1 |- _) p4 t9 A: i
  13.     return MSD_OK;) ?' j2 f/ A4 a5 n" ^$ I: j2 H
  14.   }; @5 p% ]% ~: {, f0 \# b( G9 l
  15.   else0 w4 q2 L. r4 [, b
  16.   {
    # m' `1 B% b! J+ X
  17.     return MSD_ERROR;' l9 H0 J, L. @8 C
  18.   }
    + G0 g& ~6 ?( d8 c& V4 f; V
  19. }
复制代码
0 x% D! \3 u, `) c7 }+ s# d4 `
91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
0 {2 S& [1 D# C" Y  d' e& z# P, n函数原型:* y4 t( K6 k. b4 K' `

" `* F# \& c8 Z% G
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
    9 m$ b3 C! \& }  y) b: c
  2. {
    7 f! ^9 d, {. C/ r( {" t2 `
  3.   uint32_t PutIndex;' ]% e" x, Q3 |" B* P4 `8 W/ o- I! ]8 }
  4. / B$ r( P1 S% L0 Z/ K% r
  5.   /* 检查函数形参 */' D, M4 b3 u5 \3 E% ~
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
    ( Z# P3 @" U! G. l% Q6 Q
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)  j) ^) z. ?  p  A5 B) _3 N
  8.   {* B1 [6 v3 o$ n, \
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
    ( s$ X3 F: ]5 I% g/ S( i' z
  10.   }; C1 V) c& i* i- w2 K: g; `
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */# b0 B6 |$ Z* o% J2 f
  12.   {
    / ]6 p% A( S! m: Q! H& [* h
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));, q2 g( \1 x: N
  14.   }7 q5 |+ T" Z8 v1 i3 M! y
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));7 C! _0 R" U- A- u2 ~
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));/ a4 u# ~$ v* c6 J4 H3 D+ K5 C. E
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
    # s9 @# n* T4 r( q: V
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
    3 t8 l- J: R1 U3 s* m
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));, Y6 `+ k1 u% N+ x
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));% L9 W$ \8 H7 r' _( X
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));
    5 [0 g# W- L2 w# T- \. D# s

  22. ( u5 c& w' O! C9 f
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY): b7 }2 j1 ]- U
  24.   {! U: t/ l* p6 ^1 `" R1 W( H/ K, t7 j
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */
      l& M4 [+ _$ P% w; W& C% T
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    2 j9 F- A7 e, }" e; E
  27.     {, m4 j& X5 g2 L
  28.       /* 更新错误码 */2 n+ W5 Z, a) ?6 D* e, @
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    ( I1 b0 ^' X2 }, y2 p
  30. " J" r( M' T/ I
  31.       return HAL_ERROR;
    , u7 r/ d7 d3 P" ]
  32.     }
    & k! C2 ]9 S) r) ~/ G
  33. 2 |4 ~0 d) u# t# w/ \: [
  34.     /* 检查Tx FIFO/Queue 是否满 */' R6 G. q, s  x3 y4 c2 q9 S
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
      k! u3 W5 H% v! _8 e4 e. p+ t! r! e
  36.     {6 S/ Q/ `: s4 j# s9 @6 V
  37.        /* 更新错误码 */
    ( \8 w3 ^: H) C! U) D! T2 t1 \
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;3 I5 F" H2 S  a8 c

  39. / E7 H  H' z+ C% ?; {6 x
  40.       return HAL_ERROR;4 e4 ~& P& _) x0 D1 s& i6 m
  41.     }. x. K3 _. A  _! a, ^- Q
  42.     else
    7 k$ t( L/ s# w7 p9 E
  43.     {
    3 W! e( B/ F% C3 k) A% v; t
  44.       /* 获取Tx FIFO PutIndex */
    7 r. y( G8 l7 _" g0 f8 R4 U# [
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);# e0 i/ ]" y6 ^0 f9 @+ d5 h9 t7 Q
  46. , d& B1 u4 o- k4 b6 z
  47.       /* 添加消息到Tx FIFO/Queue */
    1 y7 E1 |4 q- O
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);: d1 H5 \! \! @# C

  49. # D$ G* V  Q8 U  P0 x0 E8 [2 M
  50.       /* 激活相应的传输请求 */
    3 f3 L+ E0 k5 }6 J; v) K1 N
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);
    4 W# F& w, E# s0 c7 Y

  52. / K: B9 h8 }. z1 X' d5 k/ ^
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */
    5 f% f+ J+ Q1 n# V; g& _
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
    9 i  Y8 d' `* m
  55.     }
    4 ^% [% b( m# F% G- n: R! o
  56. 5 G- E3 Y4 f) |9 {9 U" P
  57.     /* 返回错误状态 */) R7 y$ ^% a+ b2 ^- `
  58.     return HAL_OK;
    2 z) F5 t' E6 t2 r; n  |2 `- y  ]
  59.   }
    : [5 H8 }1 [+ O" f, m* A
  60.   else
    : k5 A: }" K- ]. N. d$ M8 @' P" [
  61.   {' K. n' c6 e* m4 n9 Y
  62.      /* 更新错误码 */
    1 U$ d7 M3 E/ @3 W& q# r, ]
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    . P7 E9 @, q$ y# I
  64. 0 P; E' _$ P0 p, j4 V
  65.     return HAL_ERROR;
    ) R3 Q3 I6 ~! {5 o! }
  66.   }
    5 }% L, B2 i0 ?6 W
  67. }
复制代码
2 ~$ z/ I1 @  P6 K3 W
函数描述:
4 I0 H8 Y4 E7 j# `' t+ B; P2 z
; M! L7 _- s9 t# R9 A此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。; A: A# K: C* E( W, b

3 }  v' F, a! `* w- p) w( P2 s函数参数:, L, n% M- k+ d4 e4 n

# Z% u/ c4 |1 p% Q! C) y  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
. `- V% \" }" I& e  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。. z/ l6 K5 X3 @: q4 q" x( w6 B- w; A
  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
; L4 O: r+ D. ]- Y+ ]  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
" M9 {3 G; N9 l8 s' h9 {8 A3 ~+ E使用举例:
4 u# _6 y4 x" p
- n% Y3 y: L9 a7 |
  1. /*$ k( p- H& R- G  T# \: y# C
  2. *********************************************************************************************************
    % h' x: }, c2 N) R$ i
  3. *        函 数 名: can1_SendPacket
    , s+ n0 t& ~. R
  4. *        功能说明: 发送一包数据
    / z8 N1 Z7 d$ S5 p4 b
  5. *        形    参:_DataBuf 数据缓冲区
    7 p0 }; P. ~. g6 w5 t5 I: x# T
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节
    9 C, o1 Y8 r- F2 y5 a6 f( ?0 [: n
  7. *        返 回 值: 无& p  ~2 a$ b$ P, ]5 P
  8. *********************************************************************************************************4 _5 L1 s. V2 s
  9. */
    4 b) p5 {" D' N0 B1 j
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)
    ( D$ u3 Q4 C$ G2 D9 R; o
  11. {                ! e0 N  ~3 k# Y$ T
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};
    3 L; H7 O& ~4 |& m7 h" z, O* w
  13.         ; g5 c2 L, z9 m; n/ C0 P6 z) |
  14.         /* 配置发送参数 */% s6 V9 h- Q1 _- e
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
    . {5 P4 ]1 ?1 l: S
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
    & J5 N1 H5 @; ?4 E& g
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */+ A0 ?! N9 z7 s0 k  x, K4 m
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */3 D& b, Z9 @$ H& I4 q2 r
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */4 Q0 W  R, N7 @' T9 ^. I
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */9 P# N$ a+ r8 X. R
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */4 m0 j5 a2 N/ [# w
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */! f. ]2 ]( K& _& Z- s9 q5 ?
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */
    - H2 y7 j0 N3 ~: e  m! K7 ]
  24.         
    ( a1 e, f9 y! B; M0 U6 H
  25.     /* 添加数据到TX FIFO */
    7 r5 z' f4 ?' g7 D8 C
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
    8 J& v( A% Y: `6 b) C
  27. }
复制代码

' G7 d, M2 t: I9 M, F* ~3 E91.4.8 函数HAL_FDCAN_GetRxMessage
5 Z5 y2 p; {% {4 C: b7 l2 O函数原型:0 ]  ~# |& N7 `+ j$ {5 S. b. B8 v0 ~
( k5 o$ y6 Q9 M5 k
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
    1 {! P' @" m; G8 v* p% i
  2. {
    , v3 }" e2 ~9 D/ c: V& K8 b
  3.   uint32_t *RxAddress;, t6 J+ ~  u' q0 R0 }" w
  4.   uint8_t  *pData;! ^) y* M- h0 ~4 S1 n! R2 L; S
  5.   uint32_t ByteCounter;
    9 m. |0 w- v7 l; ~' ^9 ]% y$ z8 A
  6.   uint32_t GetIndex = 0;
    5 M! f+ {7 E, H$ z
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    ' J/ U/ h* T" d& m: v# S+ x( d2 V

  8. : |+ S  @( B! j$ H
  9.   if (state == HAL_FDCAN_STATE_BUSY)
    6 I( b6 I+ N! R! M
  10.   {
    $ h) D% m  C! ^1 \7 ^* q
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    * A# T8 E# c+ l6 ~! d
  12.     {
    $ e3 i" c( I( S  H* q
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    % S9 t/ n1 U/ w$ c) y5 A
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)7 d/ S& }0 J+ P0 c* D8 X% z# r7 G
  15.       {. n! I" ?- v3 K4 g
  16.         /* 更新错误码*/
    0 v+ q- Q6 z6 }5 h  K
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    - k! L, K6 d/ Q+ r

  18. ) ^) \% C, N. k. x' Q
  19.         return HAL_ERROR;4 M4 v9 E) ]% T( o9 i" x6 O* N' f2 m
  20.       }
    + W# g' R: P# L8 E
  21. ' B$ P& V6 i" e. Q$ `  k" A
  22.       /* 检查Rx FIFO 0 非空 */
    3 m3 Q( V' n  T! d: E& H! Z: T) @
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)- e3 q6 ~8 G9 Q4 d
  24.       {4 A% [) s: b: ~: `: N$ @( J
  25.         /* 更新错误码*/1 {" M. I5 p/ B4 Y5 P2 }: R7 m
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;4 {* t4 u3 i8 P* h( x. d7 H. \) L
  27. 6 v4 O& W! i8 ?7 D- z
  28.         return HAL_ERROR;
    , J" o2 R1 {  a1 S. Q1 a, z
  29.       }& z; l' v; x! k' R) u4 M
  30.       else
    ; x8 L; x' G& {5 J9 b! |* v1 u
  31.       {
    1 E, X6 p7 Z  V" i( `' o
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */8 b/ E; p9 o: |: `: |
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
    5 x9 l. {+ ~% O5 `' G1 W
  34.         {% p7 E$ L; K- v+ q$ g
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
    7 n0 Z& e0 g! T, S4 y
  36.           {
    8 W  o2 u8 P' ?  Q" x
  37.             /* 开启了覆盖模式,丢弃第1个数据 */
    0 a7 C5 [( w8 P, k6 U. C3 L
  38.             GetIndex = 1U;
    , [4 Y: r% u) F. n9 R
  39.           }
    " j% @! F4 t# r5 Y* l9 D# n
  40.         }
    : r+ }5 j& {  J. w3 f
  41. 1 f- x) ], Z" N
  42.         /* 计算Rx FIFO 0 element 索引 */+ M2 R  [( ~) S8 V
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
    , P2 ]3 m) T  N4 V  [

  44. 9 R- G1 s/ J7 u
  45.         /* 计算 Rx FIFO 0 element 地址  */6 \9 l. i! d- o7 R
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
    . Y# w6 K( R- E) h% M# n, ^: q* j
  47.       }- J6 }, w1 t. N& C/ ~9 ?
  48.     }
    2 z, ~: Z+ K, g
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */) z9 m) C7 s+ F
  50.     {, I! q2 N) V/ z$ n& [+ B3 O& B. _* s( l
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */
    & ]( D. U1 z$ M
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
    $ I: \6 h- r! t8 b* Z. _
  53.       {2 q# i6 [3 `" o: u/ }. V" O4 G
  54.         /* 更新错误码 */
    ) j3 r1 j" U( a: u, I9 t3 ?
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    , |* {5 }5 C$ ?, x9 ~9 O
  56. % `$ g+ B; J8 z% f0 y: Z
  57.         return HAL_ERROR;
    + a+ g+ E/ V/ t+ S: Q
  58.       }* E% @+ D+ c' a* c- n/ Q6 m
  59. ) ]& c  i& a& l% b/ D
  60.       /* 检查 Rx FIFO 0 非空 */
    " P1 n. |8 ^2 w% l8 r5 L- O; a
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
    ; N" Q" d, O1 G; J  Q
  62.       {
    * f; ~& E# Q! i. c
  63.        /* 更新错误码 */: G6 M/ F" `6 I4 Q5 ^
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;3 H' g, ?. p3 l9 m2 M: N# g
  65. 5 O+ f" {4 {, e
  66.         return HAL_ERROR;
    8 ^& N# k0 C" m1 B+ v4 H: P' _
  67.       }
    # T; m+ ]# |* v4 t) ?
  68.       else
    - q! e  ?! g5 p2 W
  69.       {
    . [& P! C$ A5 ?4 [, x( ]( m
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    2 @! |( k$ `) F3 U2 K
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)
    ) d0 D4 Z. t" F* w  c
  72.         {
    / y6 C* J( B+ Z) b- s& n
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)6 G& u* }. g5 B+ t) ^6 D3 V5 E7 N) W
  74.           {
    ) [+ a7 g0 m' L2 M: \
  75.             /* 开启了覆盖模式,丢弃第1个数据 */
    ( O# u3 Z* r" q, I/ X
  76.             GetIndex = 1U;+ X2 J8 a* Q4 p$ j# ?, B" U1 r3 H
  77.           }
    # u& R$ Z) I" n0 R2 d
  78.         }
    : E" Z1 @+ [8 V' _' L* r5 N( `& S

  79. ; t1 t* P! V5 i0 C5 A1 a" e7 f
  80.         /* 计算  Rx FIFO 1 element 索引 */* B% r4 H; r( `6 U3 s8 g
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);
    ) L( N; S: M' X

  82. $ R) K$ b  e$ |4 i1 D
  83.         /* 计算 Rx FIFO 1 element 地址 */
    9 P. \# q  P% I6 |5 I
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
    4 m7 {- i$ V) r/ f: D
  85.       }
    8 t# h7 c7 f& @$ W1 _, P$ {
  86.     }
    ; p8 e9 p: Z  y) F( \
  87.     else /* Rx element 分配了专用 Rx buffer */
    % G" E& G/ f) C! {8 j/ k
  88.     {
    ' |+ z' M) v- |( N6 {3 U- G
  89.       /* 检查选择的buffer分配了RAM空间 */
    6 W+ n  u6 k: @: J9 R! Q- F' ^
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)' Q! i! g, l! p6 V+ x- x  u
  91.       {8 Q( O2 v# _3 Y1 ?: h
  92.         /* 更新错误码 */
    , g$ N$ q- e" J# b8 P: D' |
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    $ B+ i# O0 W$ k

  94. * D6 v3 V6 [  N/ S8 J+ H
  95.         return HAL_ERROR;
    ) }: H0 X# i2 u' e, J, r5 I- B
  96.       }: {4 p+ Z# f  t/ w/ O
  97.       else
    2 u1 i) [) B: i% U& s
  98.       {  W4 D* q/ h5 q( I7 Z
  99.         /* 计算Rx buffer 地址 */
    * B& w: |1 P3 p. `! \) i' O# N5 Z
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));; _( U3 `! T" Y5 P$ h7 f; J
  101.       }) ]- F# |) \6 |! P% w0 c8 O
  102.     }
    & B1 q: P. {1 K: @8 [
  103. 3 s1 I- x; s8 J0 A7 X  y
  104.     /* 接收IdType */6 _$ b, c/ ]) d- T9 v2 L
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;, ?- s* n! Z+ ?( \4 b6 b1 Z  T% F
  106. ! T& `# r  A! O: [" ^
  107.     /* 接收Identifier */
    . Y: P- q9 S* C7 s
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */; d/ H2 L8 ?1 i& u# w1 M" w8 A5 E
  109.     {/ d9 T6 u2 u9 Q. P% ^
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
    ; L* |0 ]: y* C* k
  111.     }! t- z* t* |5 {) C+ ^
  112.     else /* Extended ID element */
    3 {) ~1 E8 t( R5 m- f4 n1 C- {
  113.     {
    9 A% y: [4 ?1 U( v
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    " `" o! q: |% V
  115.     }  l0 n7 H5 M! a4 ?; F. |' C) O

  116. - F( s6 c8 k1 O, z
  117.     /* 接收RxFrameType */
    / l* }$ h8 \3 A) M* Y0 ?; ?# @5 Y2 B
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
    3 d5 |9 m% w% @  f, ^! L$ Q
  119. $ B: L: l9 [, L& ~# }7 X  T
  120.     /* 接收ErrorStateIndicator */
    # X0 s  Q. |0 f; `  z( ~0 ~% u
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);
    ! r2 \! Q4 N% P$ \/ G; [- d
  122. : P( ~; V1 S8 w6 L
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */9 E" {3 ?  |4 x' k, K, D- v& N
  124.     RxAddress++;
    # c* s. ]& C" Q# Z0 C8 }  g2 k
  125. % o% o& {0 Y, V& c
  126.     /* 接收RxTimestamp */
    + h1 S8 x- ^; P! ]3 o+ a: r
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);* Y1 x5 Q: E1 Z% t8 Q8 i+ `
  128. * m- N$ _: m- y- S! Z
  129.     /* 接收DataLength */
    ) {4 i2 S, M' ~1 F7 ^. w) O7 U
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
      ^$ y9 x( `- O" ~' {
  131. 2 o/ S8 D* A8 N8 c: ^
  132.     /* 接收BitRateSwitch */2 X3 i9 K  a, I, C4 m) I* _1 f( u1 z$ H
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);
    5 B5 c# i+ S6 N  U+ w
  134. 5 ^! w2 H# x% r6 Z7 A
  135.     /* 接收FDFormat */
    ; D& e$ X: ^8 }2 A# D- |7 g0 H, p- q
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);
    & H' x( ^/ D9 c1 e) j0 w/ L7 R

  137. 2 u; _# d. Z8 T, A
  138.     /* 接收FilterIndex */% R* \+ T7 _0 ]4 h+ M" X( {( k6 X8 R
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);$ `/ }- l$ R" F

  140. ; I. t- `2 H" D0 d
  141.     /* 接收NonMatchingFrame */4 Y  t0 b* y1 I3 H1 i
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);
    3 u* y) z& N4 s/ m) c/ s

  143. , J+ N* F6 Q; a7 `! {3 n7 \6 L; k& R
  144.     /* 增加地址,指向Rx FIFO element的payload */
    9 ?2 @$ ^$ E7 }5 Z6 R! [2 e  M
  145.     RxAddress++;
    2 ?; A6 ^3 H; l+ T! v- C& A
  146. 4 c; g/ d4 a; Y" U2 {
  147.     /* 接收 Rx payload */
    9 L8 d- A$ f3 o0 p0 r' E- k& \. k
  148.     pData = (uint8_t *)RxAddress;7 y2 Z7 q9 W+ b* C' v
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
    4 h0 ?2 l# O0 Z0 f5 V$ n8 _$ ~
  150.     {
    $ K) Z8 n. o( C
  151.       pRxData[ByteCounter] = pData[ByteCounter];
    / j6 @2 l& Z% ?  L5 z
  152.     }
    ( u4 `. u  s( K7 n: q7 H. D3 d
  153. 2 T' @9 K! U2 x  K7 o/ `
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */* l; T. O5 D5 l( x
  155.     {
    : N! Y4 s3 D& ^, b, l
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */
    6 {: X) L7 I! J1 p  u; k7 f; T
  157.       hfdcan->Instance->RXF0A = GetIndex;
    % }' D% J% U: a* A2 M' b5 ?
  158.     }
    3 ~8 V+ \* S/ E" M- _; D
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */+ ?* R* o% }' d
  160.     {
    5 N  \# I" q* Z0 j8 l, R
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */0 V; W, I. ~* |8 O# K
  162.       hfdcan->Instance->RXF1A = GetIndex;
    - Z' K% v- Z' v
  163.     }
    " Z1 j* q% ?' X/ r  R
  164.     else /* Rx element is assigned to a dedicated Rx buffer */+ l" T1 T' T, V* @/ s& g) s
  165.     {8 v( x% O2 `2 D' B6 h( y
  166.       /* 清除当前Rx buffer的新数据标志 */1 W3 U& v1 E5 @$ G
  167.       if (RxLocation < FDCAN_RX_BUFFER32)) w7 f1 P" M$ k2 s* O
  168.       {, t& W) b3 `# L1 C5 u
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);% f. l' I, W; O5 j2 o9 V; \: u0 J% F
  170.       }
    : T& |! E& F, z% X
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
    / U+ Q* x5 J" K
  172.       {4 X3 _4 `( s4 K' `; N
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
    ; R1 j9 M2 L: ~, W/ C: C7 M
  174.       }
    , j  M, @, |1 t  v
  175.     }
    4 y5 F* o2 ^6 i, U; ^

  176. 2 O! c* ~% ?. P! G8 S" O
  177.     /* 返回状态 */
    " z! P1 v# S8 Q" n4 r
  178.     return HAL_OK;2 y. p0 U! R  l/ `: \" ]8 B
  179.   }1 b, {# S. V1 |
  180.   else
    & r0 ~3 Y! G( {0 u  m0 m% o
  181.   {
    " Y- Q" C2 |( U7 K4 j$ X
  182.     /* 更新错误码 */
    ! t) P; z/ e$ f
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;% f; q, O2 n6 w: w; V# |" [

  184. 5 J4 w( p+ m( K& E. E( o8 l1 j
  185.     return HAL_ERROR;
    2 [9 z: w9 ^% R  ?- q3 K( P. K
  186.   }" @4 k# G- T0 i. ]8 g5 z
  187. }
复制代码

) |  t4 {. Y1 v函数描述:5 a1 G$ h: t1 J  y6 G

2 O  a6 I$ O' L8 L" I5 p, w' a; i0 f此函数主要用于获取接收到的数据。5 X- L* e! R* h9 ~( A" u3 N
: a( l+ L4 H" j% u
函数参数:
( ]. m$ K4 d3 @! r/ i) M8 x, ?) Z9 e6 u2 s  a
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
9 v. b% T0 j2 u. [  第2个参数是读取位置,支持如下几种参数:: q. V3 Q. I$ i/ q8 O
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
    $ Y6 |) _1 i0 |1 S! k" H/ C
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
    ( y8 ?- \7 Q- P
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */. Q' d$ ?) X& I2 l; W( j) C$ J2 O
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */: O0 N$ O. t  r. w# a2 y. v
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */+ m7 a# K  _" s, z- u  \; P
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */7 j4 w& T! I$ x! F+ v; ]) A: Q/ o
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
    + Y* m6 y( p  {& h# ?+ P8 e
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
    7 Z# ^( Z6 K! I# q
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
    * G. o3 V# q3 y. B( P
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    . b& l2 b( ~3 C& _7 b% ~& W
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */+ R! a" l2 n% |) K& L2 o
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */1 j  \6 f% c8 Z; t/ ^; i! {
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */
    ; \9 w3 W- x* E  ?: H. r8 n- s( o% D
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */) D( g' o, s1 G7 u; k# O* W
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */" D+ ?4 e! F: r) o
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */
    3 r' b7 W- _' O5 l
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */
    7 }$ l' }. z0 M6 |" k/ u
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
    * J! u2 g) E4 u6 m' [
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */7 g5 H; v/ x' G: q% B4 ~
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */' q. W& x& x8 a: q" i- I* u
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */: I, K- B. Z% W- n5 V
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */& m' V6 q+ ^* G
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */% m. ~7 d) G1 R0 d5 n/ Z2 x
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */' {6 a  q9 g1 E7 C* U
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */" r; m  d( \3 Z" E. ^1 X
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */- p, g& k( C" u' s6 Q5 Z/ e% u2 `" p
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */. F7 ~) E; H( b$ }
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */
    : s6 F3 u- y/ v0 Z/ j
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */  X1 h' h1 @0 {
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */* C+ J: j, |5 D- z& T0 I! L" u) x
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
    / w- y& j8 ?! ?
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */3 W5 u" ~! ?2 |& W6 ~5 ?
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
    8 r% ?0 O- F/ P& Z/ c
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */- ^/ a0 |, J5 e6 m! h. M0 v& ?
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */$ R% ?  P. r% L0 w7 y- s
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */* h9 M; l, }/ L9 U' k$ @6 {
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
    5 l) I. S, k$ Y8 k3 [" v& c3 l! Q
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */1 ]$ n+ [/ Q# P. D8 n* k+ y0 d
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
    ) W8 k; H9 S7 D' R5 p
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */" x7 e* z) M6 H1 c5 C( @
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */
    3 H7 b+ A, f# I+ [. P  m. t$ y& Q
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
    0 k. O+ M6 b8 \
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */7 l4 g7 s/ {+ F- V) f5 _$ g; ^; I5 C
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
    4 n# u' n' @/ W5 {
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */
    9 i: _+ p! f9 N5 Y& n( y  U
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    7 n" \9 E9 g4 U
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */8 d( g2 j6 T6 |( O; @! Z0 e
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */& p0 W: I5 N* R# W8 j" J
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
    2 x0 D: L7 n/ [- `5 {2 G+ k: Y
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */6 e1 C) R  K2 N% p
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */
    9 X+ R3 t2 `$ Z$ |9 K, ~7 D
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */7 T  P; H) }5 x7 s5 n
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */- Z/ ]/ a9 X3 m! j
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    8 n: l* S# F5 D) c* ^4 u4 U2 U. E: e
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */  [7 n- F$ |$ M! `
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */
    9 W& O/ l8 C, ~3 C3 `" _
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
    3 y3 M9 d7 y8 ~: D, r
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
    ! W8 `2 G/ T! H
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */. u# O2 B6 f# A
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */- E7 A- F1 i8 M2 _6 g! Z
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
    0 J. O6 l$ L9 L2 u3 l8 e
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */1 ~# C' B# p, h! L
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
    ) K2 t3 c; [2 ~, ]4 G
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */
    . n9 ]- p5 w- k* h& |
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */5 y' i, ]' a& r1 V1 t' N, s
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码
1 w! \% L& ]/ q. L/ N
  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。+ \& k$ |, O2 ?5 _5 N
  第4个参数是数据接收缓冲地址。- O; X! \) Z$ I
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 @1 t7 {7 p6 ~+ g5 m; ?
使用举例:
; y, g) O9 E( |% f
, i- f, ~7 p1 b4 p
  1. /*  q  O- \' Q4 C$ @0 i' f" n; F
  2. *********************************************************************************************************
    % c( @5 d3 O7 Z/ A" s
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback
    & U/ K/ @* k" B
  4. *        功能说明: CAN中断服务程序-回调函数
    9 B& ^, h: ^3 D, C8 _
  5. *        形    参: hfdcan7 b* B5 d7 B8 j) j+ ?5 Y) O  |
  6. *        返 回 值: 无
    1 z0 ]+ D; P' D6 A+ ]9 t9 L
  7. *********************************************************************************************************6 ~  m$ E" o/ v) r
  8. */3 J4 Q' x% [5 b6 y5 R* _$ C( f' a
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)/ ^. p, ^* b! ~2 e6 q
  10. {* E, s, v' p0 H6 t
  11.         if (hfdcan == &hfdcan1)
      L% ~4 \) {! J- U3 H4 I
  12.         {; m) l) Z, R) O/ Y. g
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    0 u6 M+ C3 e; R2 [3 w
  14.                 {
    ( Q+ T- C) D# P2 G3 h: |" g4 v
  15.                         /* 从RX FIFO0读取数据 */
    $ |4 b3 m1 \1 n4 ?6 n
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);0 B* X+ ]: t: g7 e* g# ]+ |' K

  17. . F& T9 ^, S8 G; T) `* Q
  18.                         /* 激活Rx FIFO0 watermark notification */# z% b% |/ a* O1 D' S
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
      ]5 o  A% _6 I6 F" ?
  20.                         $ P  [4 A3 i+ U1 J7 ^% C
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
    ) n$ s9 q& V4 g! i9 r
  22.                         {
    % C8 ^4 }% B: A2 Z+ d
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */, w& L( ?" r" q1 A! y' z( `! h
  24.                         }
    : W$ M1 U9 B! r/ s2 k  q
  25.                 }
    0 _" l( W: h- P, f- d
  26.         }
    & U) ^; Z( j! _, ~( d6 B' J
  27. }
复制代码

+ {7 t: q  r- {9 i. G& s: F( J5 i- ]91.5 总结5 N  T8 j9 K3 z# g. k
本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。6 ^3 p2 W/ N5 E. k* U0 l$ Z

! _" Q; y& q8 ^+ [1 |; f
0 h+ n. P) {( \/ u
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版