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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示4 b" v9 r* F* [  x
  FDCAN基础知识点可以看第90章,已经进行了详细说明' N, ?6 K0 |2 ^% R
  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接; i4 j- V. r. k7 ~8 t4 a
91.2 FDCAN基础知识" i! I1 i  D# O8 y) Q+ A
FDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。' P, |& J$ k; \4 h& k( A# g/ l

& h& v' m( ?2 Q) O( G4 n# B$ `91.2.1 CAN FD协议介绍* T3 c0 L) D3 {: l
STM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:
7 b, s2 r8 L4 J% _
0 E) [: j6 A- A, L5 x) U(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
7 ~+ ?) J/ t/ X( R, r3 b5 e; G- p" ~4 e% U! J, U
(2)可访问的10 KB RAM内存,最多可分配2560个字。& {1 U9 g) a' e" ^1 G! D- q8 e

4 f" Q7 X6 a& p5 o! L, I" o(3)改进了接收过滤。
, |- u) g; W9 N. S$ s; U1 Y& b& K/ M2 c. h9 k/ L# y7 W5 t2 Q# _" z- s
(4)两个可配置的接收FIFO。
( w( K2 m$ K- J% U
% i9 p* Z. L' p7 ]- W(5)多达64个专用接收缓冲区。
, Q, J7 q/ _  P4 G3 Z# [
- C2 }, U5 @2 v5 G: L(6)接收高优先级消息时的单独信令。: @1 \5 t- P6 i$ ]

/ F4 f; a$ j! I; L(7)多达32个专用发送缓冲区。
% Y' G1 E' U& O# d7 i1 m  f4 {3 H6 v& g8 }" Y* Y) d
(8)可配置的发送FIFO和发送队列。* a, x5 D; ^7 M1 O. F/ u9 X( D
8 B8 t# `8 e$ K0 E9 ^* q
(9)可配置的发送事件FIFO。/ M1 @) s  c8 e' Y; n
( P. L+ v- F& E, k( A( E2 b
(10)时钟校准单元。
% W' _# ^) u) M9 r. d
" V8 I: M$ c, I7 {  A5 R(11)收发器延迟补偿。3 |& @$ e* p  ?. I

% s' D1 F& l4 a下图说明了FDCAN框图。
- v4 x8 w5 S4 r3 c7 l: z, B* h; e7 {1 K5 w# I1 P

1 \6 V( Q& r, s# c
f4f1d5cd872648458911e8be8ddfffe0.png

6 Z/ I5 \7 x* V/ ?$ N  k6 m3 W* @0 k3 A  Z1 r& X- d7 i
3 i1 I+ ^$ C+ @* D9 ]& n( L) c1 V
通过这个框图要了解到以下信息:
! n' G. i; n- x6 y7 _/ T( l' f& X0 u+ h, H# ~' C" P. h9 e% B
(1)CANFD1和CANFD2共用一个RAM空间。
3 }2 b# F' l- O- D- z3 H8 {2 T/ I
(2)每个CANFD都有自己的内核。
& O( Z4 w3 u" I: m8 y# L; q& O% J$ s* B9 n1 S  n1 _9 V1 |3 v
(3)CAN内核实现协议控制和收发移位寄存器。% D, v1 l" D$ Q4 V6 ^1 f! }  A
! p6 g  ^: |  v: ^8 Z) l
(4)Tx handler控制消息从CAN消息RAM到CAN内核。
, x" V5 x! e$ a9 G9 `0 s' a9 l' P6 o: c# j/ ?" h7 u
(5)Rx handler控制CAN内核到CAN消息RAM。
: K! J6 M  D4 F  t, Z7 t* g( W
% E) j' I1 `$ ~91.2.2 CAN FD特性! X, t1 V' q1 d$ C2 S" s
(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。
2 \. H# K3 F* c2 ^6 w. X# M& Y+ }( A0 E4 u& i
(2)提升错误检测,支持高达CRC 21位的校验和。
% E! F. [8 d( I6 |" s
8 U% j3 n. z2 \6 y: i8 P# y. I' ~) P(3)消息优先级。2 x; K! L/ C( D- m) B0 H+ Q% ~4 @
  h3 V* R; v8 K* w; L2 K
(4)保证延迟时间。! o" `! j1 D6 l* p' I* n
  x9 A( N+ m( e, u
(5)配置灵活性。
: \& H9 m* q3 o' S2 [
# U4 C1 T0 M- H) H: O(6)具有时间同步的组播接收。
2 s3 g# u4 y& c9 G6 d7 K+ I0 j- K# ]' x9 X" _1 v
(7)系统范围内的数据一致性,每条消息最多64个字节。( V/ V1 G5 }4 Y& h# S* h: R
& Q# E' ~! ?4 O0 Q4 U
(8)多主机。
( o6 W5 I0 l- m  ~% Z0 C/ A; [' W# S& B  @
(9)错误检测和信号。
1 y  m: K; o* f1 i: L6 f6 d* m0 q+ O3 ^, L2 y6 D$ B. u
(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。
1 L3 T/ a5 k2 w6 I0 |, X0 G0 e
) j. [" f6 V6 \- A6 K91.2.3 CAN FD格式# R3 A, `3 Y& K/ W$ j

5 K& |5 _9 B7 q) ~% [8 l/ P
c692adda5a1149b0a6e3d8a30745fd62.png
: O* p. z4 Y  o8 |) K& v0 v
7 b5 g# d* w1 G8 H9 H. A
  s% ?" i9 x9 t. ~% F% _0 k
第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:
! ]* {# R* w8 v  j9 E& W; J; A6 q9 v0 I4 S% x
(1)帧开始(SOF)。
/ v+ q0 P+ G$ _# s- h) w( `
) n3 o! x1 m6 X( N% y(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。
8 ?' s+ K9 B5 h" ]. W- C8 ~& \1 h3 ^$ u
数据传输阶段(The data transmission phase)包括:
( K/ W8 s& M. |/ O  F0 g1 G3 [1 ]  g9 A' y3 t5 t! L
(1)数据长度代码(DLC),指示消息包含多少数据字节。
; ~1 W" j( T$ Y: ^# r$ I
, y& p% s5 w- V(2)用户希望发送的数据。
# r8 h& l% E' E/ R5 d) G; u/ J2 P' I: Y- d$ v  t
(3)检查循环冗余序列(CRC)。0 m" f7 P( v2 v

6 V& R$ v" w( W, {4 ?  h(4)显性位。
! V% G8 ?1 G  o" T
3 ?- ]3 `" a4 q3 w, t: {0 r7 i第二个仲裁阶段(The second arbitration phase)包含:. Z+ [2 F  h0 R" R, A2 [
9 |3 s: d: v: H+ {5 R  i
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)  e% ^9 Y6 J5 a5 e) ?/ I7 Y+ ^

  Q) |) U  t, s$ x" N(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。/ S- {. a+ q" V- n. [$ V

( k1 F7 P( b" j2 `6 ?5 R注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
9 i2 s7 O1 ^1 S$ `# B7 e% u$ Y' _5 @1 ]: r5 @9 h0 y9 v
91.2.4 CAN FD相比CAN2.0的提升
, J: D1 H9 T  M" G& VCAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:5 {$ C* I, ?, u0 M; j# Q9 H
0 [5 N9 T1 w, ?2 K( m3 {4 H# D
(1)17级多项式对最大16字节的有效载荷进行CRC。
) ]1 a: k  g2 R% W" i% `  k, n! x; k: c: `/ Q4 t6 ]
(2)21级多项式对16到64字节之间的有效载荷进行校验。6 h1 m; d6 f# `# T

- l- X% I* k) M5 s9 D, o标准帧和CAN FD的区别:+ m, D1 [8 b& I  G$ c, |: Q

9 h$ J) X; ]$ R; V0 I5 Z0 C% ~2 l8 R
050433e4b8fe4f4d91de7eb85d5e6bdd.png
& ^( {; ~  G2 _
" N5 A( a5 |: J

! Y6 A. y1 \- u& }0 i$ s* }8 Z" L标识符后,CAN 2.0和CAN-FD具有不同的作用:. U2 H+ j2 x/ t. ^' _  C

+ C! Y6 @& W1 ^/ _# }8 j0 @(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
8 n: _$ K4 Z$ V; b2 L
1 ^" n9 k) `7 ^( y(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。
% Q$ `1 j, @# l) c8 w# l& v2 W# }/ A% ?, T+ t( T7 T" c) D+ `. I& d
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。
+ U1 S3 n  T: W8 _; s# G2 C+ h, c# D
9 ~/ {* ^5 L: ^; q8 U* @& `; j与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:) x, l+ g' S4 H% ?; v/ C
+ U4 Z; c# [, S! p  e% l, y
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。
6 A0 B, g7 I3 z2 P( a& @8 k) a0 k; J8 u5 k& v# X- _
(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。' [% e5 ^. h; ]& p4 c: l

3 d/ o- L8 ^2 r& H/ H  U(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。
0 N4 j' e/ r0 z" K9 v* G% L, W5 M1 M! {
控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。
/ H$ o/ j) J: b6 e) M4 `. c# \, F# ]/ \
2 D& t1 W/ C& d6 E: g5 v$ \
c4fbc9fa3f184422a77784de5280382d.png

( t1 M& I: |+ K0 T$ p/ c/ O
1 }8 _  r4 j0 D. x$ o  K- L4 D7 `" p8 a, z& G% T+ \: T
通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
7 S$ m$ m% f& U8 k( _3 D  e. K' S3 q, L' z
(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。
! v3 g7 h: s4 X" |1 b: b# D- x6 O0 y+ P" {* k4 k, y7 p. F
(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。
& b8 X; y) d9 N9 ~  k# f6 E' @( `- a/ h2 _
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
3 u* I2 n" q) _0 \5 V" @/ l6 }* g  j7 U3 K
- }: \0 ^  n4 ^2 R  F; e- ?
a00dca8056bf40dc860b52366afa5197.png

# u( G5 E% L1 [% h8 e! E8 y, [3 E: ?

& y* @' |" ]* @- X& _91.3 FDCAN总线的HAL库用法
7 G1 T7 [" J" n! d: X$ w91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef( S% `+ V% s* _' f8 w6 k& d
FD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
- B, c. y2 F/ }) F; e, I$ J) r6 ^: l& v' }6 l: h1 M
  1. typedef struct7 A) S8 ~: x* {- m) m" p* c
  2. {0 @- I' l  o1 G
  3.   __IO uint32_t CREL;   
    * \) O" o6 D. z7 e( ?8 w
  4.   __IO uint32_t ENDN;        
    / M4 J/ ?9 u1 H9 F- ]
  5.   __IO uint32_t RESERVED1;    2 [6 R8 D. ~* p/ [
  6.   __IO uint32_t DBTP;        4 O* j/ l" v3 U2 h
  7.   __IO uint32_t TEST;        4 i/ ~7 H9 {4 k" V( C
  8.   __IO uint32_t RWD;         + @3 j9 x4 [% o  l+ K7 z4 z; M
  9.   __IO uint32_t CCCR;         
    ; h. W9 @" g+ E- {! x
  10.   __IO uint32_t NBTP;         3 \6 ]0 U4 T. N) b
  11.   __IO uint32_t TSCC;         
    + g) x- E- H; B* k7 x5 f
  12.   __IO uint32_t TSCV;         # a# U" }0 E% k% W) r
  13.   __IO uint32_t TOCC;         2 ~/ ^9 A4 H% u7 c" \; e
  14.   __IO uint32_t TOCV;         " N; Q5 H# n$ Z* M; K
  15.   __IO uint32_t RESERVED2[4];$ u# v9 Y. i; @% W# W! u+ F
  16.   __IO uint32_t ECR;         
    5 J% D; f4 R4 u: M9 q  i0 o
  17.   __IO uint32_t PSR;          1 q2 Q0 B8 H7 }  O) P9 f
  18.   __IO uint32_t TDCR;         5 ~  E1 y4 ]) t4 J3 k, ^/ P
  19.   __IO uint32_t RESERVED3;   
    3 X. f( o5 O7 a! W) @/ x% [
  20.   __IO uint32_t IR;           
    7 m' U1 l1 u5 p+ D9 k
  21.   __IO uint32_t IE;           
    ) ^& L4 [  D3 v% A( f
  22.   __IO uint32_t ILS;         + B: b* A$ N1 V5 ?: F; S6 y
  23.   __IO uint32_t ILE;         0 y9 S& L- B. Q1 S4 l
  24.   __IO uint32_t RESERVED4[8];
    ! @+ v# E& A4 @$ l7 B1 {  x; U1 O
  25.   __IO uint32_t GFC;         
    , c, D2 ^' w1 n( _5 u( T
  26.   __IO uint32_t SIDFC;      
    " O7 M$ E6 t2 c: a& r
  27.   __IO uint32_t XIDFC;       3 {: J: d# w) j
  28.   __IO uint32_t RESERVED5;   
    , k- U* @% C. L; h
  29.   __IO uint32_t XIDAM;      
    2 S1 S2 W& v0 O8 O/ u; e6 l
  30.   __IO uint32_t HPMS;        
    6 }8 o" N& Y. N4 G& U; O1 m& h: z, Y
  31.   __IO uint32_t NDAT1;       6 c9 Z, {7 s9 }
  32.   __IO uint32_t NDAT2;      
    ) o& b; C4 e/ b4 e! U0 e
  33.   __IO uint32_t RXF0C;        9 A: ?4 M8 v. E- p, z3 ?* G# s
  34.   __IO uint32_t RXF0S;       5 v4 T3 G; R( p/ y% H5 j
  35.   __IO uint32_t RXF0A;      
    ' x1 ]' r* Z- H8 H8 _6 H" [; T
  36.   __IO uint32_t RXBC;       ( F  J6 |6 D+ ]! j$ `3 Q
  37.   __IO uint32_t RXF1C;       0 S/ G" E* M! J/ Y+ H& C7 W) D
  38.   __IO uint32_t RXF1S;       % e4 t/ Q; j4 O- s, }( C; T
  39.   __IO uint32_t RXF1A;       + ~; g$ x$ ~6 x
  40.   __IO uint32_t RXESC;        , |  X0 x- M# N- H- S, t% M
  41.   __IO uint32_t TXBC;         
    / X/ f6 G+ [6 |, I" k* v% |5 J5 i
  42.   __IO uint32_t TXFQS;        4 v3 [/ K- H5 w- \: A" V  M6 V
  43.   __IO uint32_t TXESC;        ' e7 M$ P) }. y7 V# E2 I. t
  44.   __IO uint32_t TXBRP;        ) {' S; l3 q" u: T4 s7 A
  45.   __IO uint32_t TXBAR;      
    5 K9 F6 }' d6 Q7 w% G
  46.   __IO uint32_t TXBCR;        8 \3 e! Y2 t2 E+ G5 ]7 z) T9 C
  47.   __IO uint32_t TXBTO;        ' y" H, E9 S  L! [5 r8 G9 e, o3 w
  48.   __IO uint32_t TXBCF;      
    + j; ~6 A$ Q7 {
  49.   __IO uint32_t TXBTIE;      
    ! [( O" v6 \/ e7 O+ Y) r/ P
  50.   __IO uint32_t TXBCIE;      
    % W9 |. G  J: [& X5 ]3 r
  51.   __IO uint32_t RESERVED6[2];
    $ E  ^6 z9 y: \/ c0 @. v5 Z
  52.   __IO uint32_t TXEFC;        
    ! s) G# {0 j) M. D4 T# s  C
  53.   __IO uint32_t TXEFS;        , {, V# e/ E( x  R
  54.   __IO uint32_t TXEFA;        % Y# P2 y, Q1 G0 e0 m
  55.   __IO uint32_t RESERVED7;   % j% L/ N7 j8 i% N) X& Z
  56. } FDCAN_GlobalTypeDef;
复制代码

. z) `' }# b+ M1 Q3 s" S) h这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。) E! K2 a  T; m

  Q% W) ?* ~4 t4 U- d) r3 W& O__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
, x) q. Q) D, A' @# R. R$ |+ z3 F6 _# \) i* X
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */) e7 Y6 m  H1 X6 c( j
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
9 s% \! i$ a3 ]# Z0 f) N- P5 Q
下面我们看下FDCAN的定义,在stm32h743xx.h文件。7 k# a0 h# a$ F6 ~0 Y6 Z

. G) K3 i2 ~" P3 N& K) Y# W
  1. #define PERIPH_BASE           (0x40000000UL)   D% ?, B0 O4 F6 s; G) V
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE+ C& R2 z/ N3 b

  3. ! n1 w; M0 r0 G! B* }
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL), Z$ j- X/ H) ?% B
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)5 W7 v7 l6 ^) w7 }! }: u
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)* p, `: V  }# I5 t8 _$ x
  7.   z1 o1 \) p2 b% b
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000
      x+ t1 f1 Z  v: l3 l
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE). `# l1 G8 D8 s6 @4 f* g
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码

8 |1 @3 g+ v- O, r0 F我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。5 M2 E8 y0 u; ?9 r, K
0 ^+ Z, O( P  H
91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef9 _" ]) `" U2 d; z5 ^, A0 h$ \+ L
FDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:$ w# n2 z* m- e/ _0 e- t* E7 Z

: @! T5 L2 Y" q
  1. typedef struct% U$ o4 ~, Z/ l6 @2 K
  2. {
      k  X6 ~' Q- P& H( M! D
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */
    " h8 |: k- F0 V$ _; C
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */2 G! Z$ v7 m5 e) r2 t
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */: b- ]' ?1 s- j; h
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */
    " @6 B4 r2 ?0 X8 p- l1 @
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */
    & Q' k7 |) u6 E6 k7 i9 G: Y3 m
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */1 w  [5 @4 h1 y& A% S4 O1 M: Z0 |
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
    2 S# j3 ^( j* _3 s8 r% n' Q" @
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
    * {% O% f3 \' w) m& F3 ~6 J
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 *// E' Z; Z2 m4 Q, b+ {% N  ?
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    ( Q6 i' H" N5 j
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */. v4 m1 ^9 P" m. x9 @% Q  z
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */2 e7 k$ D2 R9 g  ~, x8 V
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
    , Z' |$ \2 X+ S9 |1 r5 B) S
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */% ]! _! w3 u2 E% Z' p
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
    . E4 M4 d! F& |. W2 b  M
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    1 T* t0 b- j6 z, @4 u+ w
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */) s3 c- Q& q0 D6 @6 n
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
    + {4 p: h. Y& V! S) \' c
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */( }$ |3 R' I6 y
  22. } TTCAN_TypeDef;
复制代码
2 z/ n. a8 v( F0 W; e+ F( T
91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef1 Y7 }: @! w3 S- M$ {* ]* _
下面是FDCAN总线的初始化结构体:
0 V; M7 J7 @7 R" ^1 t+ Y2 r5 Y- h' I3 t! o. P
  1. typedef struct8 I9 x6 a; b4 _# {& W" h/ o0 a* R, |
  2. {
    7 K2 l3 E  y& z& n
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.
    ! u" B3 z2 s7 c9 r' _
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     */
    - [6 K6 H9 T# ~* i  I# K  }' J
  5. $ u! U( d' M# x
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.( q) p- o8 Q' {
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */! P7 g$ p! e6 o7 w& _0 X- t1 l3 a

  8. - Y' R/ y$ f  g: e
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.
    : s/ u1 w3 {% x* F1 K  C
  10.                                               This parameter can be set to ENABLE or DISABLE               */% c  ^; `# W# c3 I

  11. % Y  J  L, n& [& i5 T; j
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature." O! J9 g  r4 a# V5 i* O; b
  13.                                               This parameter can be set to ENABLE or DISABLE               */; q+ i* U5 i2 w8 Q; J' Y
  14. ; k; @4 x* g6 j! \& U; L5 T
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.& ~$ S/ O( a8 n. a6 c  [
  16.                                               This parameter can be set to ENABLE or DISABLE               */- Q) W8 J! M5 m7 e( [/ g

  17. # k. H0 O4 Y5 j* k1 @1 H
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is" z8 B3 g) r( m# A
  19.                                               divided for generating the nominal bit time quanta.
    & B, W2 i* ~' z+ o% y* i: z& M8 i
  20.                                               This parameter must be a number between 1 and 512            */* x! g% ]/ m1 T3 }* M" }9 ^8 Q, Q
  21. , V) l: f/ r% e, X8 I8 l& U4 y8 t
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    . I1 X3 ]. [5 l& B# q, M; e8 Q* D
  23.                                               hardware is allowed to lengthen or shorten a bit to perform
    9 m3 @7 F' N, s3 q  R
  24.                                               resynchronization.8 U' e1 `0 f- H9 M8 t/ p. ]
  25.                                               This parameter must be a number between 1 and 128            */
    ! X$ Y4 H# o' V1 [
  26.   G5 z( \5 k6 i: B3 w
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.+ L% h# Y* j/ o4 C2 k9 G' ~- k- [
  28.                                               This parameter must be a number between 2 and 256            */
    0 r9 s) ]2 K6 W; \* b( \" p( m
  29. ! e0 o* {/ ]& W3 q1 |
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.
    , e3 V, `7 C+ c1 o9 G! h
  31.                                               This parameter must be a number between 2 and 128            */! ~, A, y( z4 p

  32. * c/ A, u' k, F4 O. L- f
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is$ f& p6 ~5 n$ A+ ^+ R: Z* ^* w
  34.                                               divided for generating the data bit time quanta.+ Y5 F; w: G2 O* s6 ]
  35.                                               This parameter must be a number between 1 and 32             */6 x5 M: \& g0 `6 o# H! C. ^* h

  36. . @& @6 W! |3 _2 o) P0 D8 H
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN: k2 Q& B! c6 Y8 }
  38.                                               hardware is allowed to lengthen or shorten a data bit to
    0 K3 C- E- F$ B# ?+ Z. |7 ]0 n
  39.                                               perform resynchronization.2 T0 a% r4 o7 I; X
  40.                                               This parameter must be a number between 1 and 16             */$ ~# ~, U) G" P" M! f9 s
  41. : P. k9 C3 }. W7 y3 M. B! P
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.7 ^7 X% }- `$ x# {- _
  43.                                               This parameter must be a number between 1 and 32             */
    % k$ u- f: u, p! ]0 t1 M% ^0 K$ G+ v
  44. 6 g# M. t0 Q/ j, K
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.5 x$ H: {' }3 X
  46.                                               This parameter must be a number between 1 and 16             */
    * |  M6 x) c0 O# V- d( G
  47. , h; V1 v: I  o8 D" Q
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.% R) c0 v/ n/ H. A
  49.                                               This parameter must be a number between 0 and 2560           */' Q1 W& q) j% l
  50. 6 m0 t" _  |# N4 c  E, a& v3 C
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.
    9 y% a# x5 ?) D% g/ b7 H
  52.                                               This parameter must be a number between 0 and 128            */
    8 L( W2 q& e7 [; j' W

  53. ; D" ^3 C9 D2 x8 I
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.
    $ i! S  b5 H  {) q- o
  55.                                               This parameter must be a number between 0 and 64             */( ^& k/ w+ q* J! e1 C# Z: U6 z

  56. 2 E) e  i* }; q
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
    / ^3 ]% {& q( N6 j5 s  K1 T9 g
  58.                                               This parameter must be a number between 0 and 64             */) s$ l; @% c; r( {) U

  59. 8 r) F( N# B; |8 [: r* H7 j1 J
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.# e  a4 a! g( a0 |) G( ?" ~8 C
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    4 D; Q, \/ H  Z7 S
  62. , \; ?% M0 B# l* @! G
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
    : I! a0 ^  r# O* q7 A; d
  64.                                               This parameter must be a number between 0 and 64             */
    9 I3 S' \3 k1 u. @. a9 ?8 m

  65. / H; T& X2 T) q/ n$ z
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.7 \3 C6 E. w) a$ C9 K  {
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */5 |7 T  |* V2 ^# S

  68. " {% B1 ^4 `! H: C5 I
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.6 J3 {& k2 H9 e
  70.                                               This parameter must be a number between 0 and 64             */  C  l6 K) a% L3 o3 o+ |
  71. : R/ d3 Y0 I+ c, r6 O' v
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.% j* U  L, N1 c$ W8 K
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */9 P2 j5 S1 ^# f$ |- P6 {

  74. 3 s2 x$ o# L, K* a9 c+ k/ c+ P
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.
    5 g$ `" {$ O" p5 y* f# w. V6 Z
  76.                                               This parameter must be a number between 0 and 32             */
    % f% e; r# D6 B$ P: N

  77. 5 k* e; b5 S8 {8 x4 j' C, P
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.
    ' C  V* S6 p2 T# ~% R/ A
  79.                                               This parameter must be a number between 0 and 32             */
    - |4 _) x* k+ S8 c  e

  80. : O; Z& y- ]5 I
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.! Y6 ]4 M6 o" J+ y7 r, d7 D+ B& |
  82.                                               This parameter must be a number between 0 and 32             */  ]) q/ m+ t2 u, r
  83. 7 ]8 S! e0 [, W6 V* s1 x6 E- v
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.0 ?; c9 V7 K  ~. N: o
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */. n, y" s5 p' Y7 |- m% v
  86. " |- y. X/ k" v% F9 v6 m: N
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.3 x# R* q" ]2 {' z9 v! P& a' P
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    4 p$ d! j0 `6 w
  89. $ y) Z4 O/ l" X! A( t
  90. } FDCAN_InitTypeDef;
复制代码
* }0 E( m  F# b. X
下面将结构体成员逐一做个说明:
& }+ i# Y7 l# C
2 q6 `, v  R+ g" \  FrameFormat
% O( z4 U2 s8 _7 n6 R- S" w$ W用于设置CAN帧格式。
% k" ~- |8 S0 d; i: A
& S; l" @! @4 E- D* F
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
    & n2 y9 F. _- m2 ?3 ^1 |
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */
    ; C0 r9 [( _- Q6 y( P- Q) j
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

! f8 Z) b% e0 Z  n  Mode
4 c% a$ H( _- z, ?用于设置CAN操作模式。) r  _) [, G4 H7 R' {+ l
6 i/ w1 [5 S- K# B8 G- y
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */+ e- K! c; @1 K; @6 |
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */2 T; I8 G) Q6 H& f( j- j
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    : t0 K; P: p2 j4 |- F1 Q- K7 ]
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */
    " a1 a* g, A: O/ s5 L
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码
( L% {' W, ~8 t8 F
  AutoRetransmission- e) j& \' {  b( w) m7 J/ P6 C* n  Q
使能自动重传模式。8 g" l, x; z- u, j
3 {! @- d" U3 l# ]
使能ENABLE或者禁止DISABLE。* I  a' {6 _$ {5 v5 h2 f
) v2 z. |: J8 C9 P
  TransmitPause
0 F! d7 G- h6 {% K' P使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。7 ?: C6 h9 P9 o

9 E0 k7 x' |, F" R% S$ K" T* p  ProtocolException% @2 p; g0 w' `; ~
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
( d* m$ U- a, O" q; Y# v3 P/ @9 u6 k; t# D6 G+ ^& ]( F( m
  NominalPrescaler* G/ `/ y8 J$ ]3 c
用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。4 C7 s/ s& y( h

8 U! q5 Q7 v, i: U: L- E  NominalSyncJumpWidth' ~6 S+ b4 R) [
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。( K* \* C" F: y: n/ |
% C) D; P7 h9 v6 c+ @# ?
  NominalTimeSeg1
" j4 Z* g4 L- \设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。+ [7 T, r* v  \1 y: u  _

, m' @0 k- `% D% f, z+ o) n$ c  NominalTimeSeg2
5 q/ b( P- e$ I# O' W, R设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。8 s2 r' v/ Q8 q5 f5 ~; h
' e: }; G( V6 O+ ?* \
  DataPrescaler1 _+ Z- z) |) H1 R
用于CAN FD数据阶段分频设置,范围1-32。
4 @- [# J- |1 D5 |) v8 L! I2 S
' V7 F/ i0 j. j' g9 _  DataSyncJumpWidth
: m8 y0 ?6 V3 g. {$ S1 Z- g设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。
; ~6 N: g6 H. T# v' ~3 v# ^: s( O( F3 m( d
  DataTimeSeg1% n6 X0 K% n' P+ u$ f5 C
设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。
4 _4 @: m4 V( v9 I  w  {2 u  j& C+ n. B! X# |9 D
  DataTimeSeg21 R' W/ M: d- M2 \1 D
设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。
0 s- H8 ^6 E5 q2 d: _4 {
- }$ U5 N/ o  G5 O$ b  MessageRAMOffset. Q7 p  i2 W0 _
设置消息RAM起始地址,范围0到2560。
! D  l/ t5 O" A9 x4 _" r% Z# w/ q; }* B$ |
  StdFiltersNbr
0 w' b" L) w2 a$ i# Q+ D* V标准ID过滤个数,范围0到128。: ^- Z  g; V' s5 @
, Q/ B( A; c  b% t: r, z; o  u
  ExtFiltersNbr
; T9 j4 B7 r# V3 [6 d3 F扩展ID过滤个数,范围0到64。
9 o) D8 X9 }! G
3 z0 N% A; v% W* P  RxFifo0ElmtsNbr, w/ W: ]1 T# J, a1 h* d( y# Q' l
RX FIFO0元素个数,范围0到64。# C& ^, I, K. q4 ?& I
  _* e2 t. x, r* N, f
  RxFifo0ElmtSize
6 Z2 w/ [% T1 }% P* _9 @RX FIFO0每个元素中数据大小,支持参数如下:- e# y! A# x; @

; I$ [- ^1 O8 M& E) A/ k5 W  }
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */2 z0 Y: N, I. p$ V" D
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    5 |5 ]  F5 D9 [  K! u# b: ?
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */" f" D. c6 y. E
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */$ Y) ~: @# a0 {( l* @
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */, q2 ^# P+ ~7 i0 ^+ v( N- v
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    8 y* t9 {0 N. W0 V3 ]* M
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */! w. ]/ b) D5 d* E: o
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

+ N5 s3 G2 P$ |  RxFifo1ElmtsNbr
, p* [) n) x* k! b2 L# T% M- I1 X5 bRX FIFO1个数,范围0到64。
4 e( X9 o: O$ j: V5 Y8 G2 ~; ]) ?  g
  RxFifo1ElmtSize
7 E) f1 U! A9 u% |$ g* ~# {& qRX FIFO1每个元素中数据大小,支持参数如下:, O" \# E2 l% }5 z4 Z. p0 n& f
# |# h2 V# R5 m: w5 t" k
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    $ F( V2 n& c8 [1 ]# _+ X8 A
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */1 L5 a  y& {; v/ o4 b0 C4 [4 K
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */  y0 O* B1 s8 o$ J* z4 `7 l% F
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */& \0 P+ H+ z, E  W- ~0 {, V
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    9 ?! J7 g0 J; I1 r
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */& f/ M3 c# N( a% Y1 A
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    * I6 e* \; m7 r. n
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
4 ~5 W% k1 B3 G
  RxBuffersNbr' x) R5 J6 O3 t& X- U
设置Rx Buffer元素个数,范围0 - 64:3 |4 F+ o2 ^( Y" Y0 g* J
! ^; ~/ }) g; o5 `( `  O( M4 T
  RxBuffersSize
" R% ]# ?" |1 w& S设置Rx Buffer元素中每个数据大小,范围0 - 64:' b/ A$ z5 X# B! ], F7 _7 Z

) @& j1 p& P2 _( i% [
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    ; s0 r5 K, h3 ^" l# G
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */2 f: p8 k& [5 F6 m' D
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    + t- b; v3 B  d
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */- O' k( H' U* z) R5 O6 q; S  \2 A
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */1 A) s2 u0 U! o' @; D. `
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    4 _4 r( x/ Y: O8 w; J& g
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    : `: k4 c% r+ e
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

( F; D2 i5 Q) w. _2 f* X( k/ h  TxEventsNbr
2 j1 |# U) C8 N4 ^" ?Tx Event FIFO元素个数,范围0到32。
: D  M. C2 P: ]& d9 _% E. r% Z, k% A. S$ k
  TxBuffersNbr0 f# e1 s+ S! H) A
设置专用的Tx Buffer元素个数,范围0到32。; q7 G& M% E- a. O* ]* {* n# @
7 E1 k0 Z# ~0 m
  TxFifoQueueElmtsNbr
  ^& V* q% l. ?/ f+ g( A& U设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。, {5 Q7 T  T2 h9 [' L0 c

7 `" c5 `" u; x6 e! r9 B' ]  TxFifoQueueMode
; v; w8 d% Y5 T" v( q设置FIFO模式或者QUEUE队列模式。
. B0 z/ G/ d3 ?, V5 R: V) r2 N) n
! V5 w" Y2 D# Y+ x, P" c
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */, l2 O9 O5 b+ Y- K/ G! U4 Q
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
  X9 `3 o  T, ?
  TxElmtSize
- k! p% W8 X' H# Y  |6 t0 A设置Tx Element中的数据域大小。支持参数如下:
5 ?% f" x6 q" x. v' u+ e
, U0 c1 n( f; @5 I/ F! l. j) I
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    6 N3 M# x( n6 k: l
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */. A% u. b0 O% J+ h( Q
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    9 ?% z8 _6 Z, W/ i( W
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
      M- G9 {% V0 G9 g
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    , J+ \, J0 V- t; S
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    ) U/ ]! I, i" i  N) W+ n% C: |* h
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    + ]( T5 E3 K4 O( l: z
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
/ ?/ ]6 z0 |( p: `
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
7 H- |: w* I# I, Q下面是消息RAM结构体:
: D1 I! A; n7 o. O3 g; F3 _

  1. 7 S0 F# s8 f. Y* R
  2. typedef struct
    ' E+ R- s5 ~: p
  3. {
    ! {* o" j* \8 I) p/ a4 F
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
    , v2 L0 }/ V: q
  5.                                   This parameter must be a 32-bit word address      */
    1 Z) m+ e$ ~& c/ h3 i

  6. 2 M( z0 A" Q6 U- D
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.; t# }/ U  w! w  E
  8.                                   This parameter must be a 32-bit word address      */4 F* m' R2 p$ Q1 Z
  9. $ X3 w7 K. {4 M5 ~" U7 t7 s
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.: u& r/ |, y; s8 n+ C: ]: V; }
  11.                                   This parameter must be a 32-bit word address      */: T3 h, ?0 s; p* J7 }% Z% z2 N

  12. , Q' w" c* s) O0 G: o! _, a
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.: u- h  I4 J3 p  E* w5 c
  14.                                   This parameter must be a 32-bit word address      */5 ]  G3 @& e* k2 V# Q

  15. 2 U6 {5 q0 j4 u3 i6 ^$ q5 W
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.
    ) Z( i6 U& H& e9 b
  17.                                   This parameter must be a 32-bit word address      */$ O6 c; }: d6 _+ T- z4 h* y4 P

  18. 4 b/ x* {8 K! k8 H% l: [, R% W
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.' y$ P/ ~4 p, h
  20.                                   This parameter must be a 32-bit word address      */
    2 L) u# j6 Y$ c5 x" ^% J# M# K

  21. - l5 R, h0 \. Z- T
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.
    % v0 K- K! O1 X( g" F4 Q$ R7 ^
  23.                                   This parameter must be a 32-bit word address      */7 V1 t% a& \# H" [
  24. # h% r  _6 P  r
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.: }+ \' Z) }  q. e3 ]+ i& T7 _
  26.                                   This parameter must be a 32-bit word address      */) o% A5 b8 r: A" N3 r

  27. ) u8 e( H; H% }3 D
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.$ ~. n3 h8 X/ J, h9 C
  29.                                   This parameter must be a 32-bit word address      */) V* c! c, |4 ]& K7 X* r9 g
  30. ; V# m- ?7 x, j$ ]5 h
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.) G/ [1 ^& E" c
  32.                                   This parameter must be a 32-bit word address      */4 `5 m+ ?4 ?0 l; B# C
  33. - l& t3 J/ [- u6 b' A. ]( n' Y/ ?
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码

& t$ j! O  `4 H, a$ S# {- y9 d下面将结构体成员逐一做个说明:
+ S& `. F8 z7 Z2 q6 i. h
! u6 x0 H" E7 M7 {- p' Y6 H  StandardFilterSA+ V$ ]/ }' z+ M& b7 Z* J
设置标准过滤器起始地址,必须是32bit地址。
( f4 R  O3 V/ i1 `  z4 S) p* V' ^' c, r- O& O+ g  x2 t
  ExtendedFilterSA
/ G3 |) p: U5 J* r- z: K0 M2 {设置扩展过滤器起始地址,必须是32bit地址。
) \3 d2 p. }! Z! B
6 m1 }5 T. L/ K0 p, Q  RxFIFO0SA0 M* v: k: T5 B1 W' z# E
设置RX FIFO 0起始地址,必须是32bit地址。3 ?& i2 m2 X5 x. y6 p8 @. ]
5 S& ^0 C# L9 I, e( I
  RxFIFO1SA! z! {) ~/ z' h+ V% U
设置RX FIFO 1起始地址,必须是32bit地址。
, [6 F) y* n( }2 |' H( O# Q- a* q9 [( e. d. k
  RxBufferSA
% a7 N" I" ?3 F. P设置RX Buffer起始地址,必须是32bit地址。
% X. q: V0 G, H5 A  p% o- h* c4 {. y7 T" ]
  TxEventFIFOSA
% F3 ?4 ~- k! m. R2 R设置Tx Event FIFO起始地址,必须是32bit地址。1 U2 l" c, l  A' C5 d

6 [% z% A! h0 X9 H! z- R$ w7 T- N  TTMemorySA
9 z- E  Y* J3 m设置触发内存起始地址,必须是32bit地址。9 k# x; ]1 p- O* v" a
. c" [3 o* C' q- @
  EndAddress
1 L* L8 |( X* d2 y; h设置申请RAM空间的结束地址,必须是32bit地址。5 R) H) T7 f' i+ [7 R+ f

; [' c; L2 E+ S* ^; A) k$ S& e91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef
! k. ~6 N; o! s% w8 \0 h下面是过滤结构体:
. e( j+ T% p; m6 A, K7 b
9 u# U; B2 t6 [! O/ R8 s5 A1 h( c
  1. typedef struct
    , R5 u7 z& j$ c9 R, W
  2. {+ C/ P) Z3 Z: F  s8 h( g, P
  3.   uint32_t IdType;           /*!< Specifies the identifier type.) ^: t& ]  z5 h+ K7 k
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */1 T; p' U/ s( R) w$ s
  5. + W) R/ a8 a* Q
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.! y  F: L1 I3 R, P' [
  7.                                   This parameter must be a number between:: ~) Q' b" [- w- J% v/ w
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID6 S. X6 o2 ~: \$ `" Y, b
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */* g4 Q8 i) n* q

  10. # l1 B# H+ ^$ X
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
    / {# _! }8 i1 g, Y
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.
    # m& G0 w# s/ t1 ?
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted
    9 ~" w) Q; R* O2 q3 T7 {! M3 V$ W; Y
  14.                                   only when IdType is FDCAN_EXTENDED_ID., ~5 ]$ R* X1 O. ^# U
  15.                                   This parameter is ignored if FilterConfig is set to- s8 ]# N8 R' t" `* E( ?  I: Y- P4 Z
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */2 B1 q1 Z) j0 `) T2 a! t

  17. ! y7 M! ~* x. ^
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.
    6 M+ _: R9 ^7 g+ M
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */3 q5 b' s# _; N3 @6 ?6 A0 S
  20. & [/ j: w" n8 |" K9 G# Y
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.
      D) f5 N1 n& r0 C9 K: C* k
  22.                                   This parameter must be a number between:5 _, W; I$ M' v1 C* [4 G+ N
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    * q, i% j5 J& I, B8 a6 @
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */: i( E4 q) h, j4 t' |% a6 w) S
  25. 3 V' j0 }  h3 v% T; f! g+ x9 l4 l
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.$ u5 p7 L5 X$ _: }( a
  27.                                   This parameter is ignored if FilterConfig is set to
    0 a, U: V  {0 ?* }% R- H
  28.                                   FDCAN_FILTER_TO_RXBUFFER.
    3 j. f! }6 O& ?. m- V
  29.                                   This parameter must be a number between:
    ; O8 I  w3 _! W7 F7 `+ p' \
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID1 U5 k5 V) k4 }9 ?/ n
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */' s* P& V+ f5 E3 I* W7 T' U6 I* ]

  32. * z9 Q$ `$ d7 R$ |/ J
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the5 s* E% O; n' F; \
  34.                                   matching message will be stored.' t! y: I/ x  ^$ B& `1 U$ o
  35.                                   This parameter must be a number between 0 and 63.
    . v) `% M% V* P( |4 W- b4 v. G) h
  36.                                   This parameter is ignored if FilterConfig is different+ x- ~& d' y! V' z  m1 H% ^) _
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */- Q4 n% _4 O/ B& Y  s
  38. ! a* u4 M! J. S7 ?8 E
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
    8 x' G' ?& \  @' I6 F" L
  40.                                   calibration messages.
    ' R+ n: q6 ~' ~; v& s; U8 a  B, x
  41.                                   This parameter is ignored if FilterConfig is different
    2 F2 }* ]+ B0 C: w
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.
    9 q  z' J1 d& l: o
  43.                                   This parameter can be:
    : n4 ]) r5 G; p" X, z
  44.                                    - 0 : ordinary message& W& S& \- F& N7 i4 o0 W* b5 [
  45.                                    - 1 : calibration message                                */$ ~9 Q& K2 g& m7 y6 i( r3 z

  46. 3 f1 F) h! e2 m1 O
  47. } FDCAN_FilterTypeDef;
复制代码
, v1 {  _- S: N8 r5 y- P4 ^0 R& p
  IdType
* _9 R/ U+ K2 T  X- R3 K用于设置标准ID和扩展ID。& ]$ t$ o3 j' I% e/ \5 L

& i, K6 C$ a# x2 V9 l+ b+ r. i
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    5 j% ^* d! z" o: N
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
) }7 e; j3 q7 _) I. h
  FilterIndex% n. T' s8 x' I1 y" J, p* S
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。: ~- k1 `4 @3 x1 ?7 p
+ h$ S7 k' s- d$ [# p) `9 t" Q
  FilterType
, W$ ?' N+ g$ d% t  w用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
/ |) c- \( \- c2 o1 G' j' `  \$ L0 q: h; V& L/ I/ j( q5 n9 t
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */. m% w5 R5 @) s2 C! E" F  U
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */
    , ]9 w7 s$ K3 `5 b- _+ ~& g
  3. % Z6 V3 f) i0 x! H" H! u) C8 E) D
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */
    # Z* f$ }9 g2 a# P. r3 o& T1 L
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)
    9 m& ^3 W6 O0 t( s* Y7 i
  6. * X- B% f$ r9 K  m
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */
    2 e0 A! F: U4 w: K) k
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

' q" p) E9 M. A/ j; A, U! x  FilterConfig
" F" ?3 C8 R/ q: N( _4 T用于设置过滤类型。
& G7 [0 X: ^4 r; ?% Y3 Z% n: O5 K5 p' ?: F$ Y
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤1 r3 [. l$ M6 q2 i& p4 r' q# H
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    . U5 b0 M# ~7 D. f$ b3 k
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1' V' a3 E) M) f* r( X0 @
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID
    - H* J$ v' m) \( a+ }4 c! ?0 C
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
    % C+ G# p7 q& E, C0 n3 i
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
    4 G  |- e8 m; Z6 ]2 g
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1
    9 Q* |/ [) N9 X0 {" D2 S
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码
  _% I6 F6 T7 E) p& S* O( V+ F( ^
配置
2 q. \4 {( m' P/ a  FilterID1# Y4 o5 D3 `7 D* f' ]" S
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。
9 P( S0 M% A! U4 |* E' S
. p# t7 B. e- k  FilterID2* w2 Z- B. L, U- y
用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。
: |$ h( l5 @: N7 O& S$ A
. z$ n! Z3 g: C' N2 A( g  RxBufferIndex0 W2 U+ i+ S! \3 q
匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。- e9 Q! G: b7 R6 J* P  c
1 E4 z0 Z/ T1 V0 D" s+ x
  IsCalibrationMsg
- r% \" n6 e9 C8 y+ b用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
+ O; ^9 e7 Y+ O) P4 }5 C
1 P! Z, y$ U8 N1 T$ a% W0 : 表示正常消息。
% a: |6 G6 P- Z
: U- m1 s5 t, s/ T1 : 标志校准消息。
# R  x: I7 B$ @8 v
/ ~# v, `/ o* w6 @4 D0 ^* V% n91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
" y' w, R, l7 ]  [3 D7 G下面是CAN FD发送消息结构体:
' ^8 f5 o) I5 @% l: }1 ]/ g; j" J$ `7 T3 X$ m3 i9 C: A- }
  1. typedef struct% t  w; `2 T' X( d  v& y& _! W
  2. {& ~! Z6 J3 j, `0 |. R: O  c
  3.   uint32_t Identifier;          /*!< Specifies the identifier.
    9 N  B2 I0 A  s
  4.                                      This parameter must be a number between:
    - u: `" h: ~- _2 |
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    8 l8 ?+ t7 {3 r: G* L
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */6 l4 x" c  `7 E' m6 w

  7. 8 c& R, c# ~/ S) s* h& e! {4 ?  d  y3 s
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be" l% ?/ h! M  R3 H
  9.                                      transmitted.9 k. q. ^' W9 t2 D; Q. e
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */" N. H& @1 _% D- T2 J
  11. ' P: Q  p/ E/ x7 h; |! l
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.
    2 y6 I5 D( Y' g, T; X
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
    ' V5 z9 c9 v3 Z$ D- l* a; ^6 d: t
  14. - B9 ~7 p3 ]* b, n% }
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.+ u! U  @- u: b3 D$ u% ^
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */
    ! s2 ?7 C0 o! w6 q
  17. ; S& b; Y5 p' Y+ z# H
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.5 W4 B# \6 C) l! ~5 p
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */
    6 V0 B* ^4 k1 {. m+ i
  20.   B+ P' _. U' y5 m+ D
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
    & ^4 s: Y5 d: v" ^* p
  22.                                      bit rate switching.. A" i+ W5 s4 P, v/ F8 T( L8 s
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */7 Z4 ~% G6 ~( r8 I% {) F

  24. " F, n9 P$ ~+ v2 v: c; R
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or. K: t! g& ?* m7 K1 A. ^0 i3 c+ W
  26.                                      FD format.
    9 A5 x3 d8 M% f5 m8 d6 ~
  27.                                      This parameter can be a value of @ref FDCAN_format                */
    . V! k& O1 w! W: l9 T; W
  28. 5 Q# n9 B9 S* f3 I; w% K& t! j
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.
    + g8 }* u+ Z- D# t. b5 i
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */% B: h( R4 U5 S  P+ `. `: ]% X

  31. 1 P( X! b" _* m6 ~+ Y9 n' }
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO
    , z0 e5 @1 {$ a1 _0 S" B3 T
  33.                                      element for identification of Tx message status.
    + ]  ^( ~) M0 K: H1 F0 @
  34.                                      This parameter must be a number between 0 and 0xFF                */
    9 l. O" s6 [# v
  35. 8 Y/ k( k3 e; N4 K
  36. } FDCAN_TxHeaderTypeDef;
复制代码
! j" i' a! X  @+ B* h9 G% @5 n
  Identifier) ~. ~0 Y% `  I+ d# O% v
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
+ ?( ]% b0 A1 [" B) v
% C) C& u1 I1 S( Q  IdType
& s  {8 K$ X' ]# h5 K用于设置标准ID或者扩展ID。
5 @9 h: R: D4 p3 a, a+ `8 |# @4 [% y1 o3 w/ v; c% V- L
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */$ j; w6 f  ^; E3 A( T3 I% |
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

: k0 N0 q  u# b1 T9 C6 T- l, J  TxFrameType4 [  l# [- U' p/ j1 D, K
用于设置帧类型,数据帧或遥控帧。/ _5 _% n7 M1 k2 N

8 _+ c/ b9 a" X
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */$ f5 x8 ], t! l" p
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

( V: b$ d+ `( o. U' ?  DataLength
9 c2 `8 |. k6 ~4 \" `* m& Y2 B7 Q/ c用于设置数据长度。3 G# D: [, w1 K. r+ I3 l

$ M! }+ m7 x& F. W% r8 z
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */3 R. P; _5 [! J
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */6 F% b: r2 n6 k. m( T; ^9 K$ B
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    ( _1 o, q/ I1 j
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */, ?' {+ y9 Q( L
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */+ }6 c! N! F0 l8 \9 @) j
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    * b  q% k2 x  X" l, p
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    # n: F1 R# c/ g! k' S
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    $ D9 p$ r, K9 L
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */! D0 t6 R% \/ K
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */3 R/ y( y4 @& I' x8 M  W
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field *// R- O3 V) n1 Y- F
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
    ) D) I* \' }* ]) B' I2 I
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    + @4 {& q8 X4 s& m1 x# y
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */6 }+ \! B/ J  `" p7 n
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */
    6 m8 h/ b" L( J# p
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码

# M' h: W) \1 b- X  ErrorStateIndicator, B- l; q0 h3 @7 ~# l
用于设置错误状态指示:; A4 U, T/ B. h& z; i) J+ F1 G
: J' b( t/ x. A9 K
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */6 \) r; I& S! @6 \3 V, w
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

# q* }. Z$ s' W( r# G  BitRateSwitch9 Z4 M0 k' f5 i9 f
用于设置发送是否波特率可变。) c0 m  D5 q0 a# W
1 s, t  k1 I/ s/ h4 i
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */" f1 Y5 z8 s7 Z2 c" d$ |7 o# w3 P# ~
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码

7 k1 s# J' g- W; L1 J  FDFormat0 o7 U/ o' F7 H- R& ?3 J# g
用于设置发送帧是经典格式还是CANFD格式。
) g; C- E/ D8 O4 z
  1. % L, Y' L/ d" v) R. _
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
    $ h2 z5 \  o5 n# J3 C& n2 G
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码

& h( W# k0 r. V& D, e7 \1 q  TxEventFifoControl
1 E* ~% V4 l+ V  R1 i( w用于设置发送事件FIFO控制。
4 q$ I5 ?6 A  {+ H. [* i1 M) v) y, y" T2 v3 i
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
    / A3 O% W6 u6 U" s' x  V# Q( ~
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码
  J, P0 k" _/ [
  MessageMarker
5 m! n& ~7 h0 L$ x& _  W; c$ {1 x用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。4 k, a3 ]& V( K  o" D! V8 S/ p
- q  O1 P/ v: m/ d+ v8 A
91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef
8 J' [7 C2 {7 [" s# Y- M下面是CAN FD接收消息结构体:; Z4 n$ p1 V3 U% P$ r3 Z

. L+ |' s  W- a/ e7 U& K
  1. typedef struct
    3 L1 V! w3 O) s- L2 t3 _% `# x
  2. {
    + l4 `& Q' y! H5 q$ W
  3.   uint32_t Identifier;            /*!< Specifies the identifier.
    5 R- W$ l& |( H
  4.                                        This parameter must be a number between:+ c4 `- a* ~8 g0 F) _! i
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID0 k% w: H+ P7 L
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    ) U$ i7 v' C7 U/ H) B: `1 c
  7. ) F1 o0 F; _8 v
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.) M# z$ p4 M: T# S
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */
    % h& M6 A6 Q6 j; T! z% Y/ b, v
  10. ) Z* }' h& t2 I! v
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
    ; Z. g6 O& \. L$ A# S0 a
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */
    $ k% O$ u" w2 ^4 I, [1 p) d

  13. " }% X6 R# j7 [+ `3 g0 U
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.
    ) A0 \( W$ r9 z6 l
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */
    % u; m$ M# G- R! b' a0 y; a
  16. 0 D3 i/ c3 g5 s4 S+ M
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.
    7 S4 a; z5 z3 \) N8 e0 z7 H
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */
    . F5 Z  Q: c6 t8 {+ A, J8 ]

  19. ; P! y/ Y$ u( J- j
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit9 Q+ H# a; `2 t2 t
  21.                                        rate switching.: I( Q* F. C; }$ b3 W, \! c
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */+ l/ h- p- I. X& c9 _
  23. 1 f8 ^" r4 A( J) E& m/ I' x( _& K+ R
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD0 L- _3 W' p& Z3 n2 f9 b
  25.                                        format.. x- u' w/ U7 ]) g$ r- m
  26.                                        This parameter can be a value of @ref FDCAN_format                */
    * D  E) {% D' o2 v9 i# F
  27. $ S7 C' k! f- P' h# g& V
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame
    $ J) J! w& p) T/ i$ i. R- X5 e
  29.                                        reception.* z, H, ?7 z' B- E0 Z! D
  30.                                        This parameter must be a number between 0 and 0xFFFF              */
    / \6 M4 X# `) X' D' T
  31. 2 y- N5 c( G  ^- y' [( M
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.
    $ K. k* k. h0 U0 e+ [% a
  33.                                        This parameter must be a number between:6 a3 H$ K/ q5 Z8 ~( I9 @0 e
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID
    $ y* w4 X# @& G  \# @
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */
    ; Z" X3 `, ?, K4 Y8 }1 d6 B+ u9 w2 k
  36. / `3 I7 F- G! d' d! ?* E
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    8 E: T3 R$ o0 A4 ]3 a8 z4 p
  38.                                          Acceptance of non-matching frames may be enabled via
    & W" U! ?+ E- k- }# ]
  39.                                          HAL_FDCAN_ConfigGlobalFilter().0 ?4 z1 J. H+ y& S) h5 h- d' ]5 R
  40.                                          This parameter can be 0 or 1                                    */
    ) X1 [4 p. i& ]" j8 T
  41. # D: A+ o' V8 [) j$ G( x
  42. } FDCAN_RxHeaderTypeDef;
复制代码

5 V  n: a: X' p( g. ^) t1 Q  Identifier
: R8 P( Q& _$ T7 S( j" d用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。: i/ j; U6 f# l" J* q# W
' \& f$ _$ X6 a- @. U9 [
  IdType* I3 w; M& o( X9 d
用于设置标志ID或者扩展ID。
  z+ d& J# a4 h$ m$ x
1 p7 v; h0 ~  a! r& M
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */" B) |6 ]/ ~4 h
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

! ~& m" y' N7 F' Y) A5 n# t  RxFrameType
2 {! m0 w# V' A7 z) h! h& m# v用于设置接收帧类型,数据帧或遥控帧6 K* ^# _  [: o3 ~
; m- b' c, \# w- u8 t
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */" e6 `+ u9 J+ S
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

9 |# Z; ~' p. [6 }- ~1 u$ k  DataLength. {$ c) F: s2 {$ [: ]
用于设置数据长度。9 s2 U5 L' V# H1 u8 f
9 f& {; O+ Q9 R; }: }! R
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */, H' Z- c  u2 b1 o7 m. k
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    * f# q, y+ q3 d! h$ e4 @
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    # C8 K/ ]) p7 p- J
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    , @. Y  l8 H% e" b3 S' k! f
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    2 X8 h! X5 W! I5 J
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    . r" V/ W$ Y- d) m7 \
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */6 l% H: A+ `4 [6 i* t
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    # b" q) B% w( Z& Q2 e# n  g
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    ; z; E$ m7 v( s' W. o
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */! j6 p' V. [$ ]6 l; u( b
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field *// D5 \) q7 w4 D5 b) @: z: H
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */3 D+ {- A) _4 K& J) U
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */. O8 r' ?3 g' S4 s* j# \# q
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    7 C  ^% e' |# ?& x6 `3 \8 m
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */' o8 U3 S' A5 p. e# l+ U/ {
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
    ' x% F' M2 o! y6 h% f
  17.   ErrorStateIndicator
复制代码

4 q! K- Z! D8 N  K) x0 m& W7 y用于设置错误状态指示:
: y9 \9 h  q  p" s" Q
1 `- d9 N8 L" {2 H: c
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */
    & Q% B1 f2 V% J" l' D, i
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
0 k9 F' `( J' E6 s- c- N( s/ U6 k
  BitRateSwitch
' V9 B' j7 r/ D( M: L1 u. ~用于设置接收是否带波特率切换$ i6 H: o, k* D: K

7 ?9 P0 r2 [% c* C2 L5 [
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/8 I; @& y3 H4 c$ P, K8 n
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

1 m3 k( U: ?" {* y9 v3 q  FDFormat
& X6 t% w$ t7 P: X# D/ z用于设置接收帧是经典格式还是CANFD格式  U: m/ G- u. ^
$ y% ]1 R9 Y  d" h2 x( f9 q
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */( Q' v" C. G  ^3 G
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码

5 |6 E! y8 K2 h+ ]# u  RxTimestamp
4 ^1 n; O" k1 ?# O  S& n用于设置帧接收时间戳,范围0到0xFFFF。   
, R3 R5 C  W$ P7 Z$ f
2 k* i# X+ i$ B  n  FilterIndex
" ~! D5 `7 D2 T6 @. q! |用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。
  ]2 o; A, [& D: u9 {; L2 x  o" Y) E8 t4 b3 N
  IsFilterMatchingFrame
) n; f6 U; b/ T& [用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。
! S- B) [0 u+ e, [: W8 F1 i* x
0:表示不接受。
7 ^8 `% r" K* f! Z8 @( }7 E
' R* z: r1 J0 D1:表示接收。
5 r! J! u0 n: z+ W4 e6 Q& s) _1 k5 e& g% @6 z: @5 g  ^+ G. o# G
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef  Y2 U8 I2 }; m6 ?/ J9 R+ q' F9 Y
下面是CANFD句柄结构体:
0 p5 l6 M. p# w# C1 Y( B4 C9 Z; O$ m) i
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    ' _9 h$ g0 A% g
  2. typedef struct __FDCAN_HandleTypeDef
      O% P7 v: l, k- n, N
  3. #else
    , y1 w( Y2 F% j$ T5 ~
  4. typedef struct
    % t, a1 G/ B/ f* x; Y
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    6 S- ]' P  G1 B% w4 n3 T' L+ \* |& m
  6. {
    6 A$ F+ ^5 e4 c  S9 r
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */
    0 U' K* Y' {6 e8 C  f" l' S3 T

  8.   S2 t0 x0 l' E0 u. v, S/ R. W) c
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */
    $ _/ L8 z% b( x

  10. . V+ e& K( \$ K# X; u- _; c
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */! j0 w" U% S- C/ _# R: X) |
  12. # p9 f' V! H; Q; d& f( N, j
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */# G9 Q6 e4 ^4 x. r/ E- J+ v  ]7 m6 J3 G
  14. ' n% i: j- J' [$ \  E9 w
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index! H, a9 Z1 C* W
  16.                                                of latest Tx FIFO/Queue request */0 S+ J8 h0 z4 L* P: l; [
  17. + j2 c% x! Z. d3 J( }7 d
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */9 y, I: v- t1 i9 O4 Z8 }
  19. . L7 i3 [  t' {/ X
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */
    ; H; H3 w3 y6 v: C. [
  21. / O  x: N2 J$ f* b" V
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */
    4 ?* _) A- m+ S& m) ]

  23. 6 w4 z: Q6 Q: H6 T- }
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    + A& e$ H* h! ?' Z. t+ l3 h
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */+ E4 P0 \9 X, @8 F- y
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */
    % C+ T$ T$ W5 _) b! \( H
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */
    ; o, K+ S/ H" e# h8 r
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */
    + I$ |- V# E6 r. `/ K1 |6 p8 w& `  {. H
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */
    ) K9 |; D* v; g  j9 i# ]
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         *// g/ y8 c$ b/ H3 I
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */; ]' i  b: y0 c; r2 `; I1 }
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */9 Q. T6 E, f: R! n/ v$ V; A! E
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */
    % _: J  m9 C2 G/ h
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */) Q. a, G* _/ q+ S" Q
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */
    4 W( e9 E7 \4 C' k$ @3 B
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */. D1 _2 T/ k9 C/ Y
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */
      q- }- t) B" Q% R8 W
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
    / L2 ?8 a" a, D; b
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */# v. V- z" ]: ~; j
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
    2 k- O, [' o" E/ Z0 _8 ]
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */
    4 v0 v0 n% u- Q6 f
  42. 1 x) A' B6 `1 ~' P! L5 A
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */1 \' D! _5 Y$ h1 e/ ~2 n7 W
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
    - h. h/ f" K9 }3 B5 B* V
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */6 M7 q/ V: J0 u# O+ l9 O* H

  46. 1 G, s1 O8 a3 l" L8 C4 t" U
  47. } FDCAN_HandleTypeDef;
复制代码
/ `& Y. v' E" g( O7 L  n$ U
注意事项:& W$ {& Q/ C6 I. }* W8 c" T3 z

& ?" @" ^; E( m  v) V  D  V5 L条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:/ ^3 w4 U6 M/ v, q# l
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码

) E, I8 C! |6 i5 {" X3 J+ Y
# K3 @, C2 y7 I: P( b函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。3 o. N/ Q  K/ O

: ^/ }2 Z/ o1 G$ t这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
; ^7 }( F$ M/ r
- S$ h% m9 i; |2 Y& u  FDCAN_GlobalTypeDef         *Instance# H2 T4 R1 C) ]1 w5 I$ P/ E% ]
这个参数是寄存器的例化,方便操作寄存器。- m2 |% k% \) i! N

& ~: `7 S& C, F) z0 [2 q+ n  y) U  O  TTCAN_TypeDef               *ttcan  c- A3 s# [4 i
TT CAN时间触发寄存器基地址。$ Q. R4 b8 h0 V( J

! B  {- V) d8 S/ f0 Q* [6 A  FDCAN_InitTypeDef           Init: n5 g! K, \4 X2 R& M8 W
FDCAN相关的初始化参数。9 v  ~$ \& E0 b4 o

6 |; }) e: D2 x  L8 w, W2 O3 P* H  FDCAN_MsgRamAddressTypeDef  msgRam2 k4 N3 h$ G5 ~( I
消息RAM地址。( d" d: y8 Q- s6 B

; F2 g4 h. ~2 ]( i  uint32_t    LatestTxFifoQRequest
, ]! t8 a8 _! Z6 E9 L/ S1 HTx buffer索引最后一个Tx FIFO/Queue参数。
0 o* |: Y) R# `& k, g8 V/ O, X* f9 {! V0 f8 }) D% t) ]
  __IO HAL_FDCAN_StateTypeDef State          9 @5 F8 L4 `( k4 H9 ^
HAL_LockTypeDef             Lock          4 i  I2 z, q. Z5 b

4 r5 Z+ ~% [  S- i__IO uint32_t               ErrorCode" ?, H) {2 j2 P% l! z( b( U

9 v6 H( n2 P6 |, y% t程序内部使用的状态参数。% G2 N4 P) H# A8 E8 Z
; o% A  O( R! {7 F3 n
  剩下的都是回调函数: q8 ]2 `: J6 Q- K* M
91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c. B  T% z2 G& m3 ?' i* }
此文件涉及到的函数较多,这里把几个常用的函数做个说明:$ Q/ U( @5 Y- R  z* r' k

* u! ]) O" y; Z, Z+ m. m: K* J! q91.4.1 函数HAL_FDCAN_Init& B+ e& U, N  @$ Z) Z1 a
函数原型:$ q4 M# U1 h/ \, \$ r1 d/ Y
$ C* ^/ z- Q5 g# Q+ j1 O& K* K# ^
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)+ A6 |4 I- ]9 w( W6 u; a4 U; @
  2. {
    0 H$ e$ ~- ~9 b, p; m0 ~/ _
  3.   uint32_t tickstart;5 U5 o$ \+ u( ~4 n/ e+ W
  4.   HAL_StatusTypeDef status;* J1 W) X3 z+ z8 f) i
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
    * x3 {* T8 w. d, P' w

  6. 7 J9 }/ a7 Z8 E7 p9 Z
  7.   /* 检测FDCAN句柄是否有效 */: `" E- W9 G/ R2 |  b3 ?
  8.   if (hfdcan == NULL)
    7 ?( f- L7 E5 Z
  9.   {
    ! p6 F* u$ `6 b2 A9 u1 [7 h
  10.     return HAL_ERROR;$ j4 @1 c  V2 c+ K) |( A
  11.   }& v7 ?% H2 A2 `9 R
  12. ' y( R  p4 o& l
  13.   /* 检查FDCAN例化 */
    / [( `% z# _& N4 x& B9 ^
  14.   if (hfdcan->Instance == FDCAN1)) O% Y4 N1 Q! D, X4 O) L9 L
  15.   {
    - o/ y) q1 I9 E2 D2 D
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);* V; w0 @. D1 n6 k1 Q
  17.   }/ B/ S2 f$ T4 j

  18. 4 A, @$ T: _) V" E7 k- M
  19.   /* 检查函数参数 */
    " P5 E* i3 z$ N
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));1 P7 [/ w4 y* m. A% G* q
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
    % u3 P, g% ?( v" }; [, ~
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));- m1 b0 V6 {- P
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
    5 a. R  e2 c/ a% v! y/ |) z6 D8 d
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
    & P- T6 u7 F, {; V+ I# b
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    6 d% v, i  Q4 m9 ?
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
    $ [) s; r8 m. z, @
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));7 D$ f6 H# Y9 \. e. g
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));( |! s9 Z# Y% Z7 b- |) J. P9 i
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));: ?& _" p7 @% F+ j0 b  ]
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    , Y, D6 ^6 |$ ~9 ]: T) t
  31.   {; m( W5 j; O1 i1 Q$ Y
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));
    - z* p# P) ~9 E, ]: F' Y- Y: a8 _
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));3 q' t' y* F6 g' q, i3 j0 l/ v
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));) j* c/ I  B, W; R
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
    ; i' B# Y' p& w4 U. y
  36.   }
    4 T/ Z: X/ T1 W( V
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));# E; T& ]# G8 m
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));8 q- }, W# T- P4 u- Q0 ]9 b
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));2 y- p' q/ e9 z
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)7 K2 W0 b" o, ?: _( S2 R
  41.   {: \. a9 U9 `$ Q, n: m. l
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
    5 F. }# b- A% F. E! w
  43.   }
    7 F- |9 I0 W% f% R- S* y6 B
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
    ; E! \# u* F0 A9 t  ^
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
    * s: j  E" G/ b/ v
  46.   {
    / g7 a  @7 t- Q2 ^
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
    4 b2 A) w: u* Y. L# e1 w3 z5 m
  48.   }
    1 @: c0 U# R* i8 w
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));- K- Q0 z2 o- t, d$ z$ T
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    % ]2 C+ r8 X, V; D+ A. y
  51.   {& V3 q6 ^0 ]4 ^; t
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
    7 l$ H+ m8 D9 e" [( C* q
  53.   }' G8 N  `, e7 d- r0 h
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
    6 b. a5 z/ h& w" n
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
    0 T4 J8 g1 q. H+ O7 Y
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)* X, m1 j* q- U, F$ B
  57.   {/ ?: F6 x- F5 x7 i: U$ A1 t
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
    " v( T' S2 h5 L% ?& ^: k
  59.   }
    $ D* P; ?) e* `8 v5 v' t& M
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U): v5 L! k# A! D
  61.   {
    ( m) F* |3 b+ L- [0 c( _
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
    3 u# _0 N; b) ~$ ^. y5 a( Z) U
  63.   }
    5 j1 b- C  G# A3 f  f+ q
  64. / w: r8 I# I: l! D1 O8 `' Y; f
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    , i9 R# w7 d0 C# h# ^$ Y
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)4 M) U  s, d! I. T8 j. O# S1 q# a" y
  67.   {2 ?& J6 i. h% \8 ?  M
  68.     /* 解锁*/  |" k4 s5 y( [) \8 h5 E
  69.     hfdcan->Lock = HAL_UNLOCKED;
    5 a& i. [8 f/ }. m; f
  70. 8 e& z+ m8 H) f- q0 e4 o
  71.     /* 复位设置默认回调 */7 F0 Y2 H1 Q& R! z; G
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
    . F" m1 p" Z) ~/ y  e6 z
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */8 x/ Q% x7 G8 y7 O6 f
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */$ R8 }' @: S: t7 h4 ^
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
    . v  c9 U# Q, N8 ^
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */
    . v2 M5 B; N9 D& [6 S; _. }) k6 a
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */7 e2 \: U6 g4 o# s+ }5 L
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */; y. }: w3 ~% ~2 z" Y
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */8 ^: h& {/ O# w, ^$ a! J" Y
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */; V2 @' d/ O* R7 E( Q
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
    1 l' F9 M* }3 y4 H4 I8 b8 d( N1 b; V
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
    . L- L( a& m1 o" J
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */& \' I8 \) k9 _. f) [9 ~& \+ Q* h! W: j: k
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */
    $ K' ~5 J6 m0 r# N$ u2 ]' b% v
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */9 [  ~" x  h1 b
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    6 }0 _2 `. q& ^) d( f4 M9 G
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */9 G- {8 ?  |* m) [2 r8 U0 E
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    , ]5 Q# p! I4 o' R% Z6 P

  89. 9 \) @9 x/ M4 m2 {1 y( C! U3 e& l1 G
  90.     if (hfdcan->MspInitCallback == NULL)% p7 e; @- f) |; q
  91.     {7 r1 G, D" P) e1 m
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */2 E7 f2 b6 W/ d+ J( N& `+ x: i* z
  93.     }9 x" a; U, Y- i0 B/ N+ q) d( [
  94. # G  a/ m" w( B5 ~
  95.     /* 初始化CLOCK和NVIC  */
    6 L$ F  E# I1 U" l1 {5 B" Q2 W
  96.     hfdcan->MspInitCallback(hfdcan);" J+ u1 q$ \6 @$ s
  97.   }
    $ T+ ]0 R( ^- D
  98. #else+ j* {. t& V1 v2 \' u* C9 V+ C7 {
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)$ }. c6 W, \( b, N  |& ~
  100.   {
    - E: d6 l, L! c/ E$ G
  101.     /* 解锁 */
    ; L5 v* c! [- A
  102.     hfdcan->Lock = HAL_UNLOCKED;4 O8 i; b" _, `! k

  103. 3 x7 L4 }) N  `( {% G
  104.     /* 初始化底层硬件 */
      J7 P+ ?0 j$ l, ?4 a; ~* p: v
  105.     HAL_FDCAN_MspInit(hfdcan);& ]( Y. j1 _+ m
  106.   }
    / [& R3 z% x+ W! Y) x/ a7 m
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */3 O8 Z' }; m7 Y) R0 G; D* L" r
  108. 2 ~9 s* R, M. l7 r
  109.   /* 退出Sleep  */
    2 s) i3 i9 m$ ?
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
    9 {' y3 K3 A/ z8 d) v- o* {: S

  111. / `+ Q  M! o0 B3 s+ I. y( ^
  112.   /* 获取时钟 */
    0 u! Z5 ~4 P5 Z* H% h8 s; z
  113.   tickstart = HAL_GetTick();
    ) ^! ^$ R" A* k- K% K7 E8 W

  114.   t+ j' a- e4 l
  115.   /* 等待Sleep模式确认 */6 I/ |1 o/ l* }. K
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)
    . y7 R- W7 ^* u' A9 m$ l6 l
  117.   {
    * M! L/ p/ ]2 X, |% O
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)% Y+ i0 h8 _: r+ S/ [
  119.     {
    # S6 N. n2 O9 U. |
  120.       /* 更新错误码 *// J4 L7 ^; R' X, Q+ H
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;* g; w/ k& f7 a) s
  122. # d/ q* w5 \) P
  123.       /* 改变FDCAN状态 */8 L/ x0 v4 L2 I+ u+ D9 P
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;: N0 W" Z$ P5 ^, z* u5 j- z: a. q
  125. $ b' ^2 ~, q/ }4 b2 `
  126.       return HAL_ERROR;7 n4 h6 x0 x4 |3 J* S  _  B: P& X
  127.     }
    * h9 e  W! L1 j% P* i8 a
  128.   }' J1 A) q8 z" @4 \( w" \( G
  129. 4 k# x7 n# p7 W% ?
  130.   /* 请求初始化 */1 B+ U; K9 i0 M* Y  E5 M5 @2 I- _
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    3 X0 o6 T" D# x- ~% a2 S( X
  132. : Q( G+ k$ }* {* N- l9 u7 K
  133.   /* 获取时钟 */4 Y0 @+ L0 O5 S6 d6 v
  134.   tickstart = HAL_GetTick();6 d7 J4 a$ y1 d1 s
  135. 2 H* d: j1 K7 a' W6 l
  136.   /* 等待CCCR寄存器的INIT位 */
    % |6 T% E% g/ Z- }4 c
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
    . v2 O9 V- b* [$ A. g& T
  138.   {" F# S! p/ Q+ ^: d2 O& ~
  139.     /* 检查溢出时间 */
    6 }7 v) x% r1 K/ U# t, F4 ]# @% s
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)! A4 \; ]5 P2 s
  141.     {7 R, @) ?5 [! W1 j1 v
  142.       /* 更新错误码 */
    5 C- I1 L4 {0 A2 ^
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;9 Z' T. {. Q! A9 J4 q0 S( N
  144. ; x, o6 \* b9 A9 s
  145.       /* 设置FDCAN状态 */8 o. H( M2 j, N, {, l4 ]! n
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;
    + q6 R+ d7 l5 t0 _7 |
  147. $ G0 L3 q- B- ~; Z# \0 V
  148.       return HAL_ERROR;
    7 c1 S, L8 T9 C& }+ J
  149.     }# o8 b9 U0 _4 m; J7 D) Q! u- m
  150.   }
    - l0 C. j5 Z  L) _1 ~/ A

  151. 4 b$ W" o& h: v7 F) S, f& a( d7 B
  152.   /* 使能配置修改 */
    0 A6 [, c- E! t' @, c0 W, g5 n
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);9 C' y* Z4 u8 d* B3 f3 e# t* S/ l
  154. : l# ?$ `: Z1 O* A
  155.   /* 设置是否自动重传 *// o; V' ^) R3 h* j$ }# S) n$ h* A
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    # s& W, g. A1 |; ]
  157.   {
    8 I1 D& |& s# j& o
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    0 e5 m& u% B5 B7 T( O
  159.   }/ k+ j6 _1 A2 G- Y" ]$ j6 J6 ~
  160.   else7 O$ p/ m) |0 X+ E3 R3 G& |
  161.   {
    * g: S+ z  c, o) ?5 `$ ?4 F( p
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
      ]* h# b( k  h9 J
  163.   }
    % q" D" J$ P7 u

  164. - j) e* a- E0 T$ u  ]  q9 G: V
  165.   /* 设置传输暂停特性 */
    # a* U, |5 b5 }: E& }1 d
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    ! n1 l; i7 R4 e+ Z" S0 M
  167.   {6 H0 I4 f' T& r" n( d
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);1 z8 E6 V$ P) P
  169.   }- c( ]: [! d( _- n$ T
  170.   else) t. p, s$ ^  o6 Q5 i% I
  171.   {: f) ^9 K2 g3 f5 b9 j
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);+ }, w. J  S: ?2 P/ m) ^  E- f
  173.   }. X7 \* ^. i6 \% ]+ `

  174. 5 w5 @. A' w  p9 u5 e" {
  175.   /* 设置协议异常处理 */# \5 J1 A& F; p
  176.   if (hfdcan->Init.ProtocolException == ENABLE)
    ' n0 X- P4 K3 p0 R4 c
  177.   {9 s; a5 H7 R4 d! I7 C. U& S
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    * Y, V7 w& @! H
  179.   }
    1 B* c1 P8 K. H  O; d5 n
  180.   else
    % _+ M" Z4 [! b5 e( t
  181.   {% S6 O  J. r: Q
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    " \. F6 _% B9 C$ ]
  183.   }' r  w" ]$ L! g2 l; [; B% h2 @# q
  184. % l( b" W/ w$ N0 T' T& C2 K
  185.   /* 设置FDCAN帧格式 */
    0 T' W( M8 R( O
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    3 b2 q8 C2 X/ o' G

  187.   q$ V7 r+ ~( P; i
  188.   /* 复位FDCAN操作模式 */- p9 K! D5 [! {: v
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));; H0 S: F; L' n, e! u
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
    % ~( l" u" F6 b( C
  191. " `6 C# s, N& d; g5 _0 G
  192.   /* 设置FDCAN操作模式:
    0 p4 Y; C5 W+ K1 C# ?. A- S) O/ c6 f  j
  193.                | Normal | Restricted |    Bus     | Internal | External
    . k. ?9 k- e4 @% I
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack
    . T" J# P  F& B$ @/ a( f; w6 f, X4 T
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    1
    3 [1 c- g5 B; C
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    0
    , z; \0 C2 S' e: ?
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    1! w/ P* ?! t$ J5 R- y8 k' {) M
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0& N6 V1 S$ H* o! ]: K
  199.   */
    # g4 s1 d) N5 U& P7 R5 t
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
    $ Y* g+ K) V, s$ U
  201.   {
    5 Y' x  s$ ~, X, Y; d/ U
  202.     /* 使能限制操作模式 */
    , M- ^" j9 q( W$ t
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
    : i* E3 i6 L- b  G& ~' p, y1 O/ f
  204.   }
    2 u1 k0 E; i+ h6 m- c
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
    0 j& D7 c% r1 a1 a
  206.   {
    8 j8 I, }8 O$ X& ]5 C9 a
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    ; X& o6 o+ x3 g4 ]. [# q6 M( K
  208.     {  R& o9 j) w* i' K& s. D9 u
  209.       /* TEST寄存器写访问使能 */8 w! j, e' k8 e% t* n! U7 k/ B; S
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);7 V  S, i( {0 Y5 [& R( @
  211. 6 S+ K" x% z/ ?' _/ S
  212.       /* 使能回环模式 */
    ( q. \& n( W6 r2 i8 G/ h
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);# x: E8 b$ ]  i7 ~& D

  214. ( W$ ]- _6 f% `* G
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)6 [, W# o. F# l$ u+ y
  216.       {
    , }5 m  m% @: e) A
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
    & Z" s5 j! g) k
  218.       }
    7 A9 _+ J2 `6 g. d  \4 X
  219.     }
    ) Z* X0 N+ M, R3 W
  220.     else
    + B( s  Z! C/ D
  221.     {% g) A. c* u" e( z# W- D6 J- [
  222.       /* 使能检测模式 */; j6 c& w7 h3 K" A9 I. t
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);+ A; }5 l; C3 q3 b
  224.     }' t& X) V( G2 X& u
  225.   }; K( I3 n, n6 l% \, {6 j
  226.   else
    & L4 u) F/ Q, f1 c$ M/ z1 y5 Z, H
  227.   {, M: t; X1 u' u# Z; T
  228.     /* Nothing to do: normal mode */
    / J- Y# _' |* D+ x! J4 ~! [& a, O
  229.   }7 T. t, Z, A# G% x) W* a) @

  230. 5 ?& M# s  G5 J$ a  v
  231.   /* 设置nominal bit timing 寄存器 */
    6 u6 B6 o4 z' A+ d( E
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \9 \6 o% \$ D! b1 X& D; k$ ?
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
    : K, j! C% n0 I% z
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \: q9 o! z$ a: T' o
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));
    . V+ A# Y& q7 k- v2 ~  I) a

  236. : Z5 y* g% n" |5 U) @, R
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/. v. X& J5 B/ j$ T9 X* D/ W( W5 W4 c
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)) w1 `' C$ B5 o4 k! m& x
  239.   {. @1 n; L; A9 f# @* d: y  Z
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \' \$ `5 l( @- H/ E" z: N
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \3 o7 p4 @: t; [" S' u( m
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \3 `  T! j" i5 S$ N! F2 a
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
    + c+ l" i6 l. J
  244.   }! }0 C2 y8 W# D! s. R& j
  245. - C9 v6 _6 H9 Y  k6 ]
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)$ H8 q; E9 m' E7 A: G, C1 I+ s
  247.   {
    7 ^& }6 _& a2 U! V
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
    4 r! C4 Z0 ]6 L5 x, q  y: Z
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);5 N# s1 z7 n1 @3 {6 s2 ^! Q; Z
  250.   }
    5 v  e8 b; s7 B2 {8 m2 \
  251. . P/ J; l7 b9 y0 o
  252.   /* 配置Tx element 大小 */1 B3 _$ d  T+ R- m2 d
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    5 J( P2 B! Y% Q
  254.   {
    4 i8 H) ^0 e, Z. K  r
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
      J* J1 Z. F& ?# |1 O* t+ P2 s
  256.   }
      k' S8 U* z9 j5 ~4 z
  257. - @/ [, j0 Y  Q$ W. E% z
  258.   /* 配置Rx FIFO 0 大小 */: s  T. {6 W$ V' I# p$ k
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
    - T0 R) |% z$ N
  260.   {/ k4 s: n6 E/ N6 J+ v9 e# W
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));
    ! P# |- D1 [2 |. D+ {
  262.   }
    ! j( C, H0 E+ j# y( e

  263. . ?0 g2 [" L  ]: X
  264.   /* 配置Rx FIFO 1大小 */
    / }; o+ n0 b. h% g
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
    * X, }8 q0 x, \6 Q* Z1 j
  266.   {( X4 J5 m/ I* i. [* F1 C# }( Q' D- V
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));
    5 A, |: i+ T, q% p% D6 {3 g* |  \& P* z
  268.   }
    1 L  A( t5 M( v& Y9 [$ z
  269. 9 G6 j; o1 v' M; p. Y5 S4 K
  270.   /* 配置 Rx buffer element 大小 */
    ! g0 u  K6 d/ x; ~( k
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)
    * w0 O; F* O( B( c5 h, f8 ]* |
  272.   {
    + a3 U* @6 e, @& z- r/ D
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));, g5 E/ Q0 G+ W( ?0 @/ W9 y
  274.   }
    $ s+ K2 H, Q+ u; r* k! |  F7 [

  275. 9 @, x) a# R. p+ ?9 h. `
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
    - D0 z, i$ N" u- K! p+ l
  277. 后调用HAL_FDCAN_TT_ConfigOperation */+ `+ K* A8 R0 \0 Q" A( F
  278.   if (hfdcan->Instance == FDCAN1)7 Q  N9 Z' Z+ [' s. p3 Q
  279.   {' |) s+ S$ ?  {. Z
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);8 T, g/ }; ^5 `
  281.   }
    6 y5 }" T# q# R1 _: P: |2 ?
  282. * [3 m7 c# M, t
  283.   /* 初始化Tx FIFO/Queue */) Y8 ^& j; n3 o
  284.   hfdcan->LatestTxFifoQRequest = 0U;- k  h9 e2 O8 m4 z

  285. 5 n- J2 Y" m6 v% K, u
  286.   /* 初始化错误码 */
    ' D  R2 k1 b% V' y( H
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;! [  K. \& D5 Y2 d- z

  288. - Z! ?9 b( T$ ?# T/ H4 r1 w
  289.   /* 初始化FDCAN状态 */
    ) S. I: t" L4 y
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;
    $ L$ J4 c! g2 g; P, t9 i, j
  291. 9 s! L' s/ K; Q& M3 _6 E3 a
  292.   /* 计算每个RAM块地址 */; ^& }0 _' i4 I) T
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
    , h* m! P: h3 w* {/ p# U
  294. , b' f8 _' L2 ?- j7 g8 I: a* h+ i
  295.   /* 返回函数状态 */3 j# W& w" j" a( ?% T
  296.   return status;
    1 j; T* u: O' }; G) ~( y6 m
  297. }
复制代码

+ W9 p0 [. r- \9 ^函数描述:# R5 e7 U. \- {4 s9 e8 T
8 A2 J  ]1 G; x/ s
此函数用于初始化FDCAN。
0 w% a% d* z. S+ O& t. ~
" T7 S% ]$ m1 m: d' C函数参数:3 V6 _5 a9 p% ]1 f  C
! C% K- Q% x+ u. P+ h
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。* o7 Z1 `& `# I7 p( S8 g
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。* G  i4 ~8 i0 R1 w1 S
注意事项:! s9 p* T" q" g0 `; |0 y
' J( m4 H% k/ L5 h; i/ t& }
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。5 g% r) J8 m0 N+ n; W, ]
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。- {$ Q+ j# q( W* M+ y/ ?# z; k0 X8 y2 R
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。
! V6 c7 ]1 R  n5 a0 V' W& G
. w$ p7 t' N. t* Y4 J1 w1 Y解决办法有三+ t( V- ?9 X0 `+ v5 O

) l0 N6 t1 r8 y) l/ ]7 m方法1:用户自己初始化FDCAN和涉及到的GPIO等。. q5 G* E6 F: Q  ~+ a  j

  k% U9 g1 N3 ]' R! T: J方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。
9 X. {" G) k) v% h3 C, O
9 u& P! P4 V1 H2 r# y* G: W. Z方法3:下面的方法
* }' a1 q! y: S, [: d5 h6 T. O' t3 `# ]# _
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)1 ?' _4 Q2 T; t% J
  2. {
    8 V4 s3 t  d; K" d% t( a6 H
  3.     Error_Handler();
    - ?0 G3 k2 i7 Y, w; Z& I' V9 g
  4. }  . X' J; |4 L( D( W. C7 Q) b2 }7 h
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)1 @1 ~: p6 Y% o# V1 W# K+ i
  6. {
    7 p9 D& P/ Y  K
  7.     Error_Handler();$ l( f# I! {3 W, \1 Y+ I
  8. }
复制代码

" D1 y5 F$ w: \8 v使用举例:" s8 k& N: W5 m- G5 n

; ]8 H5 n  E: q3 P. S
  1. FDCAN_HandleTypeDef hfdcan1;
    ( `% }# y% b$ C5 e+ p0 R/ z2 w, {

  2. 5 z7 |$ e3 L6 J/ `5 [7 Z8 `2 P5 A
  3. /*
    * T0 u  W' k  o
  4. *********************************************************************************************************! p8 `. M" i" i! N$ E2 h, Q
  5. *        函 数 名: bsp_InitCan1( @5 J$ [2 _, s' @- C7 F, R+ e9 W
  6. *        功能说明: 初始CAN15 s9 e  u7 b; s* t% V; G* Z4 D
  7. *        形    参: 无
    : [4 _/ C$ F5 t3 l4 E
  8. *        返 回 值: 无
    ; Z% c. k$ i5 @  i
  9. *********************************************************************************************************3 w9 w- Z6 B( Z& v
  10. */
    ; p# O/ K" x: l& c
  11. void bsp_InitCan1(void)- U- t: \: j3 p/ [# I; o; `. P- u
  12. {         $ }2 b& {  l" ~2 ~
  13.         /*                    位时间特性配置
    7 k  Y) J- D7 b. B
  14.                 Bit time parameter         | Nominal      |  Data7 s$ x0 m  B$ f
  15.                 ---------------------------|--------------|----------------
    2 w+ O- E/ `7 R0 Q( h
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz
    - c' o( M! u0 |) t
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns
    3 G4 n$ Z4 a6 P! z# E
  18.                 Synchronization_segment    | 1 tq         | 1 tq
    + z3 q) x, B0 s8 n. w+ i4 U
  19.                 Propagation_segment        | 23 tq        | 1 tq
    $ S" p  V. s* A  K- S; x
  20.                 Phase_segment_1            | 8 tq         | 4 tq
    4 }# @  p7 \/ I7 |; R9 q1 n
  21.                 Phase_segment_2            | 8 tq         | 4 tq
    # G- ?" [7 v2 t5 C
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq
    7 j" u! v" H. i
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
    4 r6 c. C8 }$ M1 v- e, C7 L
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
    5 \. @* X+ o( f1 H! Y1 b6 k
  25.         */; ~- p% w" k. p( C! j# Q, h; k
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */             5 r* Q8 [* `5 g7 i) Y* a
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  " ]) M, n4 V& g1 q- Q9 j
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */
    % {9 V6 d/ u0 h. F. N( r3 I0 f* N
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */ # C. f3 v! Y3 q7 O. S
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */
    : A# i) S! C5 W1 o
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */5 V' p8 [: F7 B- G% O+ I
  32.         
    + ?& A+ j3 j6 v8 f' k6 T
  33.         /* $ d8 o8 x. @' T3 q5 i' g
  34.                 配置仲裁阶段波特率 8 H  H5 o0 Z4 P% i
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是$ {# c; Y' r+ W/ [- |
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps          R0 C( ^1 y7 R1 R5 `& n
  37.                 . K* K. a! c! m. v$ l  c* {* y! d7 c
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    / R4 E' [( P6 D" A
  39.         */% n1 s( n( W. k# g
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    " x6 E* e. P; m9 o# Q  Z8 P- I
  41.         hfdcan1.Init.NominalPrescaler = 0x01;
    . o( d( C8 p5 c8 \; A
  42. 4 S& {! ]* C6 T' p' x
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */
    ! g% P. ?9 b# I2 n4 p
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08;   U9 ?7 N. T* e+ h1 n) v; k) ~" V/ D
  45. # ]/ ]6 I+ f/ C
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */. U6 [; t& p4 \8 H6 h$ ~* \
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;         
    ) \4 U, @( N" J
  48. 5 U1 l0 a5 O) n) k# y6 \
  49. /* 对应位时间特性图的 Phase_Seg2 */4 X8 R" C8 X" O- T0 Z/ ]$ g
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     
    % {7 i3 u4 h7 [; B$ H( `: b

  51. 8 @, b/ D. I2 @3 C8 w6 i$ t

  52. , K' ?  {3 z# |5 a; w
  53.         /*
    6 E. M0 k. V0 g! k
  54.                 配置数据阶段波特率
    ; M% O$ L* j; v" M, a/ x8 I" v
  55.                 CAN时钟20MHz时,数据阶段的波特率就是
    ' d! ?2 u9 ], H) ~1 T8 \
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
    & p0 k8 @! _7 \9 I$ K
  57.                 / C9 X' W, V, o; `- J/ O
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2
    4 `3 P* ?2 W( l. U& P6 T- a( v! y
  59.         */" i( X8 j: C0 d" A' y$ A
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
    9 y$ B8 @* M/ A& [; V+ \  T6 t
  61. 范围1-32 */+ j* @) F3 Y3 ~5 H2 `
  62.         hfdcan1.Init.DataPrescaler = 0x01;
    ! q! }. u6 m) C

  63. 2 r; ~( Q* }! R4 x5 V( Y9 t0 ~
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */( G' e4 t7 C2 S# S. }/ q
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  
    4 D% X2 `: ]5 ]2 h' M2 ]. H
  66. 4 G; a4 x' s; g. E- B. y* J
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */. B2 t& d+ `$ E0 A6 q
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05; $ T- K, g! ?0 w1 r
  69.   `' \. y% ~0 y/ M2 _2 g& x4 C
  70. /* 对应位时间特性图的 Phase_Seg2 */                ) Z) k) q' J# c9 i& q9 u8 {
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           6 H- X4 {) [) ?; K: f- f9 F
  72.         9 C* k  L- j8 V& h
  73.         
    $ x: Q6 z3 L; X- [3 R' Z4 W
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */! {# N& Y5 U( i
  75.         
    5 y# w& P3 f/ p
  76.         & B; ?7 h2 W  l
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */       $ Z' |1 {' q" K* E" ^/ ]/ b1 A1 d
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   
    1 m& L4 n" C/ K% V- @3 @* o
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  3 a4 K, W: x1 J9 ?, Q
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   5 V6 {1 ^1 R2 z6 ]! r" [
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 4 F+ d$ x  L% l, D% [* u
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */
    , r# j0 B, ^" J8 D! ]4 ?: Q

  83. 6 h/ O: P4 n' G0 _  A- P+ t
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        # R. L6 U& c1 n9 G' i
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
    2 D4 y& K" I& }* j, V0 ^$ B
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */- S% s  Q+ Y( `
  87.         
    " k% X: m, M$ q* V+ a0 s8 U6 [
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 *// g* V( O+ w& K$ ^" Y& ~  A5 m7 c) i
  89. hfdcan1.Init.RxBufferSize = 0;                             
    3 N3 V  O+ y" w/ `, O3 c
  90. 1 q( ^+ V5 c7 M$ \4 A# l
  91. 6 {: g3 Y* c+ I( b0 i% W
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        
    / g8 a" U2 ~5 Q6 ?
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */) `9 A. U! o, U& `: X$ S. Y0 g
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */
    # Q3 G0 S( G% }  ^2 ~  y0 g
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    ' v: D- \* k' s2 C7 Q% [

  96. 3 ]+ Y) P4 }9 G5 ]; n6 \
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */- Y( f! t: o# d- w& s
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;         
    + ~, b8 C: g  ?
  99.         HAL_FDCAN_Init(&hfdcan1);* g  V9 ?9 D& _# w% C; B! w& E

  100. - z7 n, B$ a' k' A: ^+ k9 [5 n; ]! s
  101. $ D0 ?4 V# i% @; ~7 j
  102.         //省略未写
    5 x# N" b* v0 f; {; `7 P$ v
  103. / J& [& A: r# [! @5 y2 H% N  v
  104. }
复制代码

; S2 {( p; T0 }& ^# n91.4.2 函数HAL_FDCAN_DeInit8 D: e5 ?2 {8 @
函数原型:
" s, M7 _( x2 I/ t" s2 O0 B2 E# H
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
    8 b6 m- U$ Z' c; u2 d
  2. {: h0 [' J9 b9 J6 W
  3.   /* 检测句柄 */
    , a" G& G- v- U5 ~, k2 t: P+ `
  4.   if (hfdcan == NULL)
    6 E/ }0 ~$ l4 K( K& q3 [1 g
  5.   {
    ; U. P9 c0 m) s' s  E9 q" k
  6.     return HAL_ERROR;* p" y) @- V. R/ C) b8 g
  7.   }7 ^# ~9 S* g) c) p

  8. 0 j+ I) l& J' }  n+ p' x
  9.   /* 检查函数形参 */$ D/ k& }* A0 q$ P7 r% F& Y5 V
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));) T  k- _: n5 z4 v
  11. ( u, u; q0 x9 }- L( |  [% w
  12.   /* 停止FDCAN */
    ) i/ V2 }- M; c1 p' n0 q2 i
  13.   (void)HAL_FDCAN_Stop(hfdcan);, T/ X0 E1 }4 ]1 S) `

  14. 1 l; o: x8 v% j! C# @; m# d
  15.   /* 禁止中断 */
    ) b. e2 L" L) r* x7 S9 G  |
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    " i8 r- n* b( J' R8 b
  17. 8 s1 D6 V7 @' h; V# H5 z+ [
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1/ k7 }# u1 {* ^- \$ K
  19.   if (hfdcan->MspDeInitCallback == NULL)
    % A: p2 V5 w/ k; V& ?& A
  20.   {
    5 x$ j- X2 |+ i8 i& u# E) T
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
    * @# I0 ^1 d3 Q5 A4 {
  22.   }
    ! \1 y! L. \/ H9 P

  23. ; s" S2 M/ o. y, N$ w0 z$ u
  24.   /* 复位底层硬件,如时钟,NVIC等 */! `( l, k& m8 v% J( F
  25.   hfdcan->MspDeInitCallback(hfdcan);2 R- z7 P% q/ U+ n
  26. #else' |. X3 ?$ ?- K4 L. _3 B) C8 G4 }
  27. /* 复位底层硬件,如时钟,NVIC等 */
    ) q4 p" k2 c4 _; E- a  Y& k
  28.   HAL_FDCAN_MspDeInit(hfdcan);4 S2 o+ \& C" p) s; T; B
  29. #endif
    ! l4 y5 \5 J2 v' x

  30. ' S  \3 |# |  z- h
  31.   /* 复位错误码 */6 g' N& c4 H6 r# `4 q
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;7 w3 C6 ^: C: Z( K. \- m, d$ i
  33. : o0 V7 P  Z$ Q) t
  34.   /* 设置FDCAN状态 */
    " r- [1 v6 @" Y
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;
    ! y& u5 ?- s0 x$ @) ]2 H

  36. , w7 U3 b( n' H* Q. I+ U- P
  37.   /* 返回HAL_OK */
    , k" I( u6 ?" ~" Q: f1 J8 |
  38.   return HAL_OK;
    % r- c& |9 B: c1 Q& B
  39. }
复制代码

( O: u8 f3 ~: f8 Y函数描述:  F) l& `$ Q/ A+ W$ I

1 _7 K4 q- h  N) j( {& p. L用于复位FDCAN。& U0 f" v, a" X" b) [, j, w1 u
2 @. C% e! D0 x& Z4 g3 A  Y9 U
函数参数:
1 Z/ F) v! d4 M9 \1 H9 l+ k! O8 `4 X! i# _" u
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。5 L6 u: x6 L+ r6 }9 Z
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。3 \/ y# U: O( w0 I- d: p/ i: j
91.4.3 函数HAL_FDCAN_ConfigFilter- s8 `2 m9 X: V* X. A' U4 H2 Z
函数原型:
5 \9 r; x  S2 }. |5 ?: N
& @* u1 J; Z+ c3 M
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)& F& N3 B( {% Y% u
  2. {$ d5 H2 n; ?1 I! @; A! d
  3.   uint32_t FilterElementW1;
    2 _7 D3 U' @* W9 @$ ~" ?# n
  4.   uint32_t FilterElementW2;
    2 L$ o- G! v* x8 Z% b
  5.   uint32_t *FilterAddress;
    4 Y$ G$ {1 Y- x" d! I4 h" R
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;& r# i& H" @  u1 b
  7. 3 f, \$ p# E" Z, Y1 l9 Z
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    3 s) d- j% t' V- g
  9.   {% L; M* ^  K  Q% U3 a/ ^
  10.     /* 检测函数参数 */
    # P! x1 O* Y- Q# s) o1 T# M& U
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));, P. J$ O% ^4 V
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    ) b  X2 o6 q6 E. S6 F9 }7 f2 v# A$ k
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    " {7 l( m8 p; h; [4 F9 a
  14.     {
    5 O; u. w$ T8 ~6 a9 s# T0 W0 ^4 [, m
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));2 a1 h' C8 F2 X6 J- R, L
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));$ n" D! D+ W8 L2 w6 e9 U. q8 O
  17.     }, O2 t2 H5 S- `' u8 R* X8 t' ?* H

  18. 9 V# a- n2 Y$ L- A
  19.     /* 标准ID */, _: j7 B) x. g1 R
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)' O1 h$ A& x  B+ H) {7 @* |( {; s
  21.     {
    ) J% [  L9 p/ I  A1 {- T4 y6 v/ _
  22.       /* 检测函数形参 */
    % L1 R; Y; E! U6 T0 ]
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));6 N" u1 m% h4 L8 X# l6 j1 a
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));/ c/ A6 H, O2 ^
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER), C3 C5 ]5 c  x4 v4 K/ I
  26.       {' S, R/ y" X( x. G& i* ~" n: D
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));; n1 h1 Q6 a9 G* T8 A/ G
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
    6 n- q2 @, D( X/ k% p
  29.       }6 S7 `' x. _9 G

  30. / R7 G. _6 S2 t1 \+ r# J: S8 p+ @
  31.       /* 构建过滤元素 */! X% s1 \) L) z/ k% B  n
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    4 @, z$ A+ R2 s6 v9 N, ?
  33.       {
    - u& f7 j% k8 n& r$ L
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
    " [5 |) A$ N7 {5 q
  35.                            (sFilterConfig->FilterID1 << 16U)       |
    ' H2 i( z& F$ d5 j- i. ]
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |
    ; u9 h. Z6 ^7 Y3 L2 T# x8 ~+ E# s
  37.                            sFilterConfig->RxBufferIndex);
    ! u- q( y0 K, i# K9 ?' d4 s
  38.       }
    - Y& }+ _! b/ G. p
  39.       else
    ' n0 v; `# J0 a# X% N
  40.       {
    5 A: W' H: L0 d# c- w- {
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |
    + s( W$ W7 C* A. j( i3 q* Q' _5 E
  42.                            (sFilterConfig->FilterConfig << 27U) |. H* Y6 a' g- {, v
  43.                            (sFilterConfig->FilterID1 << 16U)    |( t' ?' f7 H1 T! u+ k: B2 o
  44.                            sFilterConfig->FilterID2);3 w2 N. w4 }: B% o+ L0 G
  45.       }% A* ^3 O% T" H9 C8 n

  46. ! N. x) r8 o2 p- E+ @; l1 A# |
  47.       /* 计算过滤地址 */
    4 t& u- ^4 A7 @+ b: J
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));
    3 L+ R$ z4 Y( R" ]

  49. 4 H8 [0 E% s( W, h1 {$ H+ S9 L# T
  50.       /* 将过滤元素写到消息RAM中 */
    2 A) o- _8 f3 O( v6 l: O
  51.       *FilterAddress = FilterElementW1;' F# g% }% l5 ?( O& `# _- J
  52. }
    * T6 x+ _* }9 u. z4 W
  53. /* 扩展ID */
    ) n( o" [& n2 m. c3 V/ \2 T, u
  54.     else
    6 P, X2 I, ?2 p" y! m% V! J. F' m
  55.     {4 w/ ^$ U% N  `% A# x+ S
  56.       /* 检测函数参数 */( S. b7 n2 P9 h* |* A) i/ ~1 r, D4 p
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
    1 t, k: O* k# r* ~1 d
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));& a* ]' e( h! J6 x* ]2 Q
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
    / ~( D# h6 L: ]
  60.       {
    6 t2 d" p: Z3 Z0 A
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
    1 c2 j7 ~( s6 |6 m. I2 |+ s
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));/ ^4 i  B6 y. ^
  63.       }+ {' L; _4 r9 `" T5 }: r9 O
  64. . H# n0 h2 t9 G% b6 ?+ i
  65.       /* 构建第1个word的过滤元素 */2 l* \9 z! X  j0 t! M0 }
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);
    & h& v& g4 @5 ]+ ?

  67. . W. W5 Y; H- p0 h4 J; r
  68.       /* 构建第2个word的过滤元素 */! F0 W" G7 ?6 o% r" `' x, j" X" L
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    2 q( F1 t  Q4 c8 G4 f
  70.       {
    8 }" @) {; w$ X4 u
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;
    % i1 S  I- Y3 ]& R2 e
  72.       }& e# q5 m) R: ?6 s& X. _
  73.       else& L# f/ m0 ^0 q% {) Y
  74.       {% L6 G2 f3 ^/ j" G
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
    . k$ ]  H0 e3 w8 K9 r" C/ w
  76.       }
    ) V. v! G' x: p& s
  77. + K/ e+ n* C; K7 E' H
  78.       /* 计算过滤地址 */1 O3 Q. x" s' _% |" V
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));
    ; I" v! c5 w8 k

  80. & j: k6 a$ y" R2 A6 m1 t7 b. ?
  81.       /* 写过滤元素到消息RAM */* V: ~" \8 i; C& z" X0 m% ^
  82.       *FilterAddress = FilterElementW1;
    ) t/ f# {" I1 g$ `5 P, p" b7 v
  83.       FilterAddress++;+ o" ]2 p" }& l5 M! U
  84.       *FilterAddress = FilterElementW2;4 `! R3 `3 y/ ]. R  x4 D' N
  85.     }4 b# f/ Q- X1 u: r, d

  86. % G1 V' P/ u# _6 K$ C* i% ~
  87.     return HAL_OK;
    # `: H6 N5 n- a9 c
  88.   }
    3 G' b, [% z3 Y3 l) v: X4 @
  89.   else
    + q( }% X2 x: q, I
  90.   {- _8 V) m6 v0 ]
  91.     /* 更新错误码e */
    ! l# b3 k) S2 P, P0 P. y  K
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;) \0 q% h' {) e2 d, T; I3 J

  93. " ~9 F2 e: |. r
  94.     return HAL_ERROR;0 g9 [2 G- m, W1 H
  95.   }
    ' D5 ]- F8 R9 M; s
  96. }
复制代码

1 Z# V( T' L% e/ Z函数描述:
+ k2 ~5 m. V' |% K) G. @5 l; i' {4 n4 ^8 y" ?: x
此函数主要用于设置FDCAN过滤。' c( l" V& {( I

+ j- c: ~0 i3 L( S( U" v! ~9 E函数参数:
4 g' e% p$ F" \) x" P7 [# |, \5 }; q. i4 e
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。' H  T5 \8 `( a7 I0 V1 \7 @
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
6 Q" ]5 L9 ~8 X2 ?, d; l+ J  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。" y4 P4 }/ D8 b' B2 K3 U
使用举例:
7 i3 k% I3 B5 I8 A
# T0 a2 f! F6 e8 n2 u; n8 n6 x
  1. FDCAN_HandleTypeDef hfdcan1;
    1 K+ c' L3 B  h0 D
  2. ! V( `" ]8 c1 c( n! C$ ]
  3. /*& v6 j3 f) Y# m9 }/ o+ Z6 s/ k" P
  4. *********************************************************************************************************
    6 e0 T1 i) M- A' D& n% i  @" ]
  5. *        函 数 名: bsp_InitCan1! c  ?: U2 ^& o8 G# x5 W2 O& e
  6. *        功能说明: 初始CAN1
    , |' [. F2 p  h" E9 ^
  7. *        形    参: 无
    ( J8 N- c9 ^" a; E+ s
  8. *        返 回 值: 无1 C7 l9 H  d7 S8 o" k9 p
  9. *********************************************************************************************************: }" M. X' z2 a2 F9 `4 a
  10. */0 }) t% j, p3 L3 @/ ]# z; ]
  11. void bsp_InitCan1(void)5 l9 s3 T* _; ~$ Z
  12. {         
    & L& @5 ?; W) j, E1 T' i
  13.         ! I7 r0 d/ U5 m2 T8 |0 C
  14.         /* ( V3 t2 d' R- V- z
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。
    4 p1 ]5 S% \% Q5 w0 |
  16.                 FilterID1 = filter- A/ E9 z* V" x# ~: J+ V% I: X
  17.                 FilterID2 = mask$ M6 O) K! |# v5 D6 E& s
  18.                 . G% @4 L4 c) q& P( w' G
  19.                 FilterID2的mask每个bit含义9 B& F8 A- }# W* j: M; S
  20.                 0: 不关心,该位不用于比较;& H# S$ m5 Q' `* T  V4 d, M; O
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。
    ; W# O( B2 `2 c' z
  22.                 . @! E4 e# m5 V& ^
  23.                 举例说明:
    6 g) \: U& n4 S+ _; O2 P
  24.                 FilterID1 = 0x111: c: X( z7 u& Z6 y% m) i
  25.                 FilterID2 = 0x7FF , r' q1 f- U6 G( u; T
  26.                 表示仅接收ID为0x111的FDCAN帧。2 a3 i' i+ R' x# O% D$ s4 c7 i3 u9 H& Z* w
  27.                
    + [2 U( ~0 _+ o' K( U8 W- I
  28.         */
    , r9 Z) V- c9 i/ l
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */4 \: ?+ g3 ~5 S5 ?
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
    ) Z! U' U9 b" {! Z9 o5 T- S+ P- b
  31. sFilterConfig1.FilterIndex = 0;                                                   
    7 N, p: ~4 R4 P: Y3 g
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */
    , ~) ?( D$ b/ w0 L: T& `. R: k0 R
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
    & n8 x+ F8 \0 o% U6 g6 c2 X
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
    % @  W. }, D% [8 y
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
    4 x; f4 x' n& E' a  W
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    & ?$ p- ]  @5 @2 @% ?4 E

  37. / l# ?! ~$ n/ j. e* C: z* R
  38. }
复制代码

/ f% o: y8 i' i& D. x" C91.4.4 函数HAL_FDCAN_ConfigFifoWatermark
/ |( Y5 }" I: N6 x4 n; Z2 H函数原型:5 I; \( M3 j9 x, Q# f: t, k

: K' E! y, i! @- d  L: b
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
    ) ]* c, Y% n6 `/ L
  2. {  A8 m( [+ s! Y, I" \  O, [
  3.   /* 检测参数 */7 j& r- R  y/ t# C# @  Z
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
    4 h- i7 t" V( p6 n  w; T: ^
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    1 W0 c. x( J! I* b0 A: r- L/ x
  6.   {+ _5 @# Y* f' {# l* e) B7 r$ u
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
    7 U0 P% Q+ l7 q5 e3 y* X& t2 g
  8.   }
    9 I8 m" F+ @" b
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */; F0 M5 }5 j4 I- W2 n5 V0 M2 [! r
  10.   {
    7 a6 Z- \+ c- j5 u( F$ ?5 H( L
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
    ( e8 I6 N: B+ s% N3 ]7 R! [
  12.   }
    1 G0 @$ k4 s  b+ p- B' p
  13. " ~; t% r: H* K( L* L
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    5 W4 Y& Q7 T0 O3 j7 ?# b
  15.   {0 a" ^9 [3 ^8 f+ ]  W0 K
  16.     /* 设置发送事件FIFO */6 N& _) n$ |* R& @
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)% k2 A3 `' s4 Z" ]) N" k- N
  18.     {" a* L' l5 J' y; w! P
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));4 F: k9 b2 w' ^$ v: K6 \
  20. }9 c. v4 W) S, r
  21. /* 设置接收FIFO0 */: q0 f/ Y& G: j  j
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)4 C  V/ N9 o4 `4 B
  23.     {5 I* ]3 K6 P9 u+ o3 @! j5 X
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));+ G3 q$ x  z* J
  25. }
    + `, n# T# t0 ^8 r$ t, I- u. u
  26. /* 设置接收FIFO1 */7 k" ]3 G! Q5 Q  a  G
  27.     else
    6 W  {4 k+ _4 V  `
  28.     {# j1 l4 M, |. M& Q, x- G8 X5 }
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
    ; Q# G# i" C6 g
  30.     }
    " K. C' B& z( E& \! M/ {5 V1 e
  31. 6 Q) a; u- {4 D0 j# C0 D
  32.     /* 返回状态 *// d% h1 H) k) f! i: b- q" L
  33.     return HAL_OK;) q% C  T' w" `( N4 S
  34.   }
    8 L4 ]# @$ t  E5 l
  35.   else/ y5 B2 X; E' d2 W) l* |
  36.   {
    * S, p$ g1 O# k% P& b9 W$ X# ~
  37.     /* 更新错误码 */" U; F. }, ]" s* w
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    , t% C( h1 r. }/ Y
  39. $ b" b2 F/ T, |: L
  40.     return HAL_ERROR;
    ; {# I. m" f& G4 X9 M
  41.   }$ H% d) M0 \8 w$ |0 ~
  42. }
复制代码

$ A6 Z1 \; M3 J函数描述:
0 B: c: O, O* Y
6 h# i4 M+ v9 r0 a( y% C- ]此函数主要用于配置FIFO Watermark
6 n$ _. N! \8 _8 V0 i2 n8 ~4 K. @# g; m
函数参数:
9 \. w1 y2 H0 ]; a3 M: n; H+ E5 ^
/ ]( Y/ g  R. h/ R/ p% n5 o  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。! a3 X/ c  W6 j0 X
  第2个参数是FDCAN FIFO Watermark
) g1 g: H- v9 Z7 h+ i
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */
    " _9 J4 t2 r% `) v6 g$ u
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
    1 ?( ~$ u) u& o# T/ _
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码

2 ^  _! n/ |  P$ F$ l3 l8 F  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。3 n" V. D  i& D, F  j
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
* A4 E+ N# I6 x) a8 f$ v使用举例:
5 m6 B3 L6 y/ w* B! j- C/ D7 N4 G0 i
  1. FDCAN_HandleTypeDef hfdcan1;+ l6 K" Z" g8 X3 p; p

  2. 0 _: a" E! }9 h! `# G) t# x
  3. /* 设置Rx FIFO0的wartermark为1 */
    2 n7 D/ [6 s$ l7 @) W
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
1 B$ M4 A: B; b0 l
91.4.5 函数HAL_FDCAN_ActivateNotification
/ O: k4 L1 ?! A/ y函数原型:
- ~1 w& {: n' q; D' T& G8 W, {" X+ ~' @' v& U1 x( a
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes). J8 k' M. b% f( i# s  d
  2. {( q. s  d, Y' D" M
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    $ S( q( g& [4 L* Y: I3 I& ^7 Y
  4. " i& Q. U) p' [$ I% g2 g! L% w
  5.   /* 检测函数形参 */$ U3 @" ~2 C2 U( C) a0 K
  6.   assert_param(IS_FDCAN_IT(ActiveITs));/ w" u7 q5 O% l0 T; P( ~: K2 d
  7. 5 D# n4 \7 K0 F
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    ) Q" J- M. e, ~7 e) d2 o8 d$ L
  9.   {& H0 B! X4 B: ]+ a6 f5 A8 n; D& ^
  10.     /* 使能中断行 */
      x; w# n2 Q; d! u
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)+ f! F2 x5 d# R1 F; _1 ?
  12.     {
    ( R. h# |2 T. G9 e; d+ H
  13.       /* 使能中断行0 */' R) z" a3 H: k' L' M
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);* Y5 E1 l: F7 D0 Y: P7 w
  15.     }
    : C" g  R  G* b, W: r$ U0 B
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)) q* }" M0 G: |0 c. ~
  17.     {
    ) V! P5 X& t- p/ E0 U7 [1 j
  18.       /* 使能中断行1 */
    . X; u. E! \$ }. a$ l
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
    ' R6 _% L& S( j! w4 S+ q$ L
  20.     }
    7 i$ d& s  P2 S% c5 S* L3 h4 @
  21.     else
    3 r( z  _5 y* o! h
  22.     {, D0 p% P! {" ]5 R" h
  23.       /* 使能中断行0和中断行1 */  R: N9 N% G; l1 ~- Q( x% `
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);
    0 }& f' Y7 L& Q7 n% i) B
  25.     }
    $ g  p' J+ D- U$ ?# t
  26. 3 _! |( D6 M/ v) A! t
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
    4 _5 B. P/ n  [* c
  28.     {
    - A* C7 ^1 _8 }! V# f) v8 X2 x4 [
  29.       /* 使能Tx Buffer Transmission 中断 */) r( p: S4 {- }) e; M; G
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
    6 S+ c" g- X/ i9 W  K
  31.     }
    - e% k: G( J. k/ ^3 h9 s
  32. : F( W) W9 j) C* ^
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
    3 d3 Q7 @# _' S2 g. U  x! O
  34.     {/ y# Y( d  u, p  t6 P
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */( E4 G3 J& y. q) B; g" L1 c1 w
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);  m& y1 z3 q/ `$ H4 K8 j
  37.     }" Y5 O8 s" L% _0 X  k6 b3 V% W
  38. 3 ^9 X6 {" h& j- P! G
  39.     /* 使能选择的中断 */' g3 Q6 Z( s& C$ e7 x0 m: J( \, i
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);. h. b1 U% ?& ]7 Y+ M

  41. ; M% `- t( n9 v, s& r" w
  42.     /* 返回函数状态 */# H" ]7 S6 G% w9 F: N1 W8 }
  43.     return HAL_OK;
    5 a# M' M$ ]" _# t
  44.   }# b$ e  ~* `+ l/ B6 [9 l2 i0 ^
  45.   else
    " F, S. N* ^$ \4 s
  46.   {
    2 L$ D5 z% t" u; I3 p0 [/ B
  47.     /* 更新错误码 */+ @( k! i; N- f8 P3 v2 O
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;5 x5 [9 L! V- U+ I

  49. & V+ l0 w0 g! `6 V) e
  50.     return HAL_ERROR;% ]2 N6 \2 U8 B/ W5 ], n
  51.   }
    ( d+ f# Q8 a- [5 `! D9 e6 N
  52. }
复制代码

) q! Z2 B8 h; E" k: ]8 T  {' o函数描述:  ]4 I( U" S, U: G4 |

+ G9 N; h" G4 l5 e1 k此函数主要用于使能中断。
4 E4 o. [! f  u" ^0 I) H7 Y! z. f5 v0 |9 r* T5 R5 }2 l' D4 |4 H
函数参数:
9 U; O$ S" w: |0 p7 U$ l/ x3 E
& o$ [* `" ]& [! r  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。' }* }! Z  t7 [( o
  第2个参数用于设置要使能的中断,支持的参数如下:- n* u# g, N) I! s
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  8 H' P- K+ x0 B9 A+ T$ |  Z
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
    7 Y" ^: L. r/ U+ I; [' ~8 N* L
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         $ Q# a; z) G: K# z3 Z
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */0 j/ j; A* b6 {& J/ u4 X
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer
    1 X# [" Q+ ~& k7 v3 L4 o8 T5 P/ ~
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
    6 M, t$ r) Q& y' Y3 L9 ~+ K
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */+ h, K/ ?$ d5 }' M1 |# V# ], O4 ?

  8. ) K6 \+ {) t! s$ ?
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */3 r. K+ D. l7 L
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred / E* a8 B0 k# B8 @3 H% P' \# Z
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */5 T% @/ N+ O4 m1 {+ P4 F
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */
    . m% ^! l4 _3 E  |. H' k
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */- _  M" ^0 }" r) M1 Y2 a" i  k
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */9 l8 y  m# S2 {$ r# Y8 q

  15. ) r, `; R3 [6 p6 {& `2 E
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */( w# z5 d& ?$ Z; P$ `
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */: D. m( I6 r. Y& c7 @3 M
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */5 S* L3 }* v$ G% b# \* x  x8 N
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */
      @* [) u# j! `( B
  20. . k0 d- O0 ]) _# J7 o$ L7 N
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
    2 N1 T  `% s5 o: \
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
      N2 F  q' }. A
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
    ' b4 B% X/ O* a+ k
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */' \9 H9 N( j  l6 X& I8 V
  25. * y6 K: }; X3 `- ?2 P* v
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              $ ]9 k: Z; _, _3 L( Y3 C
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred 8 ~5 ?3 N1 d* i8 C) a) Q4 `1 t3 W
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  / v$ t3 P: C: ~+ A4 Q* g9 M5 A
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     
    5 }1 ~6 i* F6 j/ O  X4 P3 K- X
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            # }) K' \5 v* x- X! k+ }1 o
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              
    / j+ v( h. d5 Y1 ]3 z) C
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
    2 r' {- |" ?& m9 G# X8 O
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */
    5 P8 |  c% O9 ]# D& i
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码
6 s. \3 c8 M; r- \% C: }
  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:! Y9 m' }; f; G( {6 w- A
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
    ( k9 u2 M% u6 g4 i% R( {
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */
    0 M& A/ e) K! n" \' g" W  K# p/ q
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */0 l. B9 _) `# m9 _5 Q# L1 P- c! M3 r4 M# s
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
    ( a; l. |0 ^/ y3 \5 Y' ~; G
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */
    $ v7 i: x$ n6 `( y. k( s
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */) u5 |, e( ^! [) r2 G2 c8 u" k" o
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */( }! P) `( ?5 q( M6 S, Z
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
    6 ?# p, [: F0 H4 D3 O
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */3 }; X& h* S; |8 J& t
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
    ' D1 y0 _/ Q$ d9 K' t- k
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */$ t3 }, X& E6 I/ f% M
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */" g9 \9 Z4 I2 z3 k9 {' M/ ]6 I% X! \
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */( Z9 `' c6 l) g! G
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
    7 _' c  ?/ i1 _' w5 Y0 p6 [
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
    # \5 G, C5 k9 ^6 `& m4 m  ]+ f
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
    & U; r3 n8 h  V4 U0 `" ~$ N% V
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */% g* z* k7 i8 f- n- H5 {( P/ E- E+ H  V
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
    ( X" ~0 k9 Q! c0 Q9 j; [% v" e9 i
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */( g, A: d" Y* c; |" S( T
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
    7 V/ N# B/ I) G6 F" [
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    % N- ^9 L" z% |2 A9 _5 D5 p' ?
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */$ n. h' G! X  {2 h, i/ ]' \4 |
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */! Y7 l( a  P; ^/ J8 j, a& b0 t0 n
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
    + o' x; g# E$ s
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */3 F7 c6 q( h$ P8 A1 V& H$ ~& Z
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */
    6 R) j1 P- H3 b. N3 x# q
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
    " B# M! h% a  w; Q4 ~; M" f
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */- l0 C" K; t3 |% I7 F
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
    & x) S+ v: F' |+ g$ T
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
    3 i, [8 Y8 q! j% B* L- q+ Z
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
    $ B  t! i; K6 M
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码

. x' ~5 h; G$ @如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。
! T/ x$ w) v. o0 u- C7 l& H. s6 D! U; s9 D( n8 H) R% m
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
8 `. c* O$ w0 h/ ]1 f8 |+ Z使用举例:) l9 l0 m4 R2 W- x

- i. H; R% h7 L1 |- i1 q. W- SFDCAN_HandleTypeDef hfdcan1;
# h2 n- c; ~  o/ f
: s7 ]! M: P1 Y: {. u/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/
5 s! f* a. o6 h, O2 i; @/ PHAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);! M5 p1 r5 n) U4 S/ ^5 v
91.4.6 函数HAL_FDCAN_Start5 b  X9 E" T$ w4 Z, _
函数原型:
0 k) d& S7 N& Z+ n6 ?1 ?, o2 A8 q6 x6 ^! ]4 y/ Z( `% J; ^
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)( `. Y5 P/ F: }0 {) y; }- J: {5 Y
  2. {
    ( @  P3 R# h* z3 B8 F$ h
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    . t; k, m4 K" r% [4 |
  4.   {$ p9 y: n) O1 ^6 j% u( {4 h
  5.     /* 设置FDCAN外设状态 */1 {  _, H! I2 M+ a
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;
    + k. m# {% F* N7 `: b1 m  i( J; P
  7. % l- z* g0 P4 @: r/ j8 y, k
  8.     /* 请求离开初始化状态 */
    % m) B% s4 m( L* Y# o' M8 H+ w
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);9 p: u7 O, G4 x8 ?5 {6 U. z  H
  10. ! \. O1 p% ~" a" ]6 |$ T. g
  11.     /* 设置错误码 */3 l* s& s. V' Q( e
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;1 z  X+ Q: d6 V

  13. $ Z, C$ g  G+ g7 |# ?# m! P& g
  14.     return HAL_OK;
    4 [; g( t( @' v8 {7 \
  15.   }: X, W3 q$ C8 [' j4 F
  16.   else5 o9 G0 N$ M3 I% h/ _8 E
  17.   {
    , n4 E+ \8 F- e4 N& Z
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    ( k! j+ N* E' W! R( d" o* u
  19. 6 O/ [4 l% c$ S5 ^% u  z
  20.     return HAL_ERROR;# N" W9 S; h' u8 E6 b
  21.   }
    . Q9 I; a- q9 U8 c- j
  22. }
复制代码

  E8 ?; ?2 O$ O. W- [7 d3 h函数描述:! F- W5 _/ ?$ S

! t7 \3 s6 |; W( m; h" d+ U$ [, L此函数主要用于启动FDCAN。( j! S! N# u+ ~# p1 S
$ M6 g' n/ {0 ]5 k7 h1 Y
函数参数:& m. C7 g. C' c1 m. _- s
2 M* v# C7 P. G" ~9 ~: f8 _
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
9 O# X  p  B4 @4 Y0 E/ i2 Z  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
# q* {! s% D2 i7 d. a& j- n% U: v使用举例:7 D1 b. {* @# ~  s

1 r0 ~+ T4 ?  p0 Y: w1 E+ _
  1. /**
    . e5 H. f* h% b3 w
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.' z# V  {7 P' u% S6 ^) M5 K) N
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
      h$ A' B0 K$ k
  4. * @param  WriteAddr: Address from where data is to be written
    2 @: |3 b4 ?5 e4 [4 {( M" L
  5. * @param  NumOfBlocks: Number of SD blocks to write9 y' w! W3 ^  |9 M
  6. * @retval SD status
    : o8 x$ X$ u9 q4 j5 ]. P( e
  7. */
    - V( R' C& [, K- |$ f" h6 l
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    2 P) ]6 S7 A9 X3 a3 p7 |2 P6 V
  9. {
    - R3 l3 R1 [; _) e# f* ]
  10. 6 G4 w+ Y$ O, J, S$ Z
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    ' p- T1 C* j2 [. O' z! C- P
  12.   {
    $ Y% R- Q& [/ f" S7 `/ l
  13.     return MSD_OK;4 x" d, y9 @. P9 v' _
  14.   }' ~1 ^* f8 q( c- v  b1 s. S
  15.   else
    % z% O$ d$ L7 o8 I7 x- }' v3 d
  16.   {7 N* X: N; O0 k+ R6 T' T4 o4 x
  17.     return MSD_ERROR;
    , E; n$ O3 O2 M7 M
  18.   }
    1 F: G0 Q- `0 G
  19. }
复制代码

. F! F1 m7 _% O( Z. B91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
6 l: Y: f( n( C) U5 {6 \( e! M5 q函数原型:
/ w4 x3 a+ b; _1 q
+ J4 ]; U9 Y/ A; N
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
    6 e- u) A# h! ^8 P$ M
  2. {
    1 b8 y3 r& R- W" c
  3.   uint32_t PutIndex;
    1 F& X' t2 c$ H) m5 f# _
  4. & l7 q  q! t) H6 @6 k7 `# y
  5.   /* 检查函数形参 */. r  k- C% d- N8 V6 R
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));' `- F, B9 E7 z- B
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
    + L; \; o( h4 T) M+ n
  8.   {
    . X  o' d* Q6 h1 v% h. A
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
    1 A! @$ T; {3 y; N2 ^
  10.   }
    7 l3 k# A, e! M  T
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */, p8 ?( _7 Y. Q, q, P- o
  12.   {
    / [, |0 e, p% x7 C/ S- d
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));/ O# e- R. P- `" f) H9 X7 ~
  14.   }
    $ P; ^4 u9 w1 P/ o0 i4 I/ ]
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
      l- g9 a7 v& P2 M$ {5 [
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));7 l; x) Q1 f+ `8 H+ R
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
    $ X; N, H& s& N8 y( ?1 U: G
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
    & X4 {# a* f* j, X# B1 g% I! e
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
    1 {) Q  A$ J4 ?7 _: o! z+ @
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
    ! v+ R. _  x) z! J) z; j
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));7 T- a8 |, V# o$ F- d) E# Z0 ?& o
  22. ; |0 |# a; \' f
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY). D4 x* f6 t/ `- ^
  24.   {7 b# e. N) D* F  U
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */9 ?8 [5 p' E1 A" Y+ C) L
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)8 o( f- v0 i3 ^2 L1 e
  27.     {, d6 k; y# R- c$ m; x
  28.       /* 更新错误码 */
    ' q/ P" c5 Z/ _- k
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    $ I' t7 |$ \* [* g: h; u
  30.   }' y: F& E" v2 ~
  31.       return HAL_ERROR;" x! T1 H7 c' J  a( L
  32.     }
    # G2 i5 G$ Y. H3 c5 x/ r: P( S
  33. 4 O' {/ N: E# j* W% S
  34.     /* 检查Tx FIFO/Queue 是否满 */
    1 V2 \5 n/ W* l) h% t
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)' G/ }& T( V! I' f9 U0 K( u
  36.     {
    : q9 a& G/ b' J8 l0 Y# m* X
  37.        /* 更新错误码 */
    # p6 Z2 I# @0 B5 C$ F3 y6 Q3 W
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;
      }. m; P- b" S9 Z7 ?2 I
  39. 2 v  ^! `5 }  `8 F; {; L
  40.       return HAL_ERROR;3 \6 j' n5 J3 o* |
  41.     }
    ! G9 t: c" T1 J1 z( i1 |8 L$ y
  42.     else
      A# @, Z8 U1 _- s5 ]2 R* z( v$ @
  43.     {
    + h( z) T% ?  ~$ K, G5 {- p% s
  44.       /* 获取Tx FIFO PutIndex */# Q8 e, L$ C  u8 N& P
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);# R" v  |4 C6 S- ?  i3 ]7 I) Z
  46. $ K8 X2 n! w, E: K
  47.       /* 添加消息到Tx FIFO/Queue */
    5 j5 P/ g7 s: {) T
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);
    7 q1 ?; a! t! r" D* H6 r. I3 [2 n

  49. 3 ?% M! ?; ?7 N4 C9 W# V
  50.       /* 激活相应的传输请求 */' x6 ]3 c0 P4 X
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);
      p) |2 a6 i; A$ k& H$ X" G2 \

  52. ( @$ i4 Y1 m) n5 p2 s+ _: m& f
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */
    ! y* u: P6 }8 Z: C# `/ @
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);6 L+ r6 U7 }% S" `' P
  55.     }
      Y( }" J  c! m9 i1 D( ~
  56. % _: ?1 |; f! ?" X
  57.     /* 返回错误状态 */9 _/ |) U% u- g" j
  58.     return HAL_OK;# q( n, ^( N0 Z
  59.   }
    ) A) W0 n7 a: x( I8 ?0 p% q
  60.   else, v, G1 q: @4 `
  61.   {
    4 ]$ \: w. P0 {; m1 d( |
  62.      /* 更新错误码 */5 A5 V4 x* I3 [/ N9 Q
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    ) R8 C6 y( d8 F- n: R
  64. & S( ?' x' b$ {. [
  65.     return HAL_ERROR;
    7 j( y/ S8 q0 z% R9 O$ ~
  66.   }
    * X# B  k( u  l! Q& _
  67. }
复制代码

7 l: P/ c1 J7 [3 I( y函数描述:
3 p0 _" V$ d/ o% ?2 s2 z- k' h
8 u* j2 m4 _! N4 g2 o5 X$ t此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。* ~/ N$ M6 m& k. v- `

* ?5 |0 t) r" w+ I! H函数参数:
9 \9 J( G& V( B. A) J1 X/ t8 Z# k9 z3 Y
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
) Q) n" G8 p! S) G9 _; x( `% T  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。$ }3 I# l( s+ P4 J9 E: }
  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。$ u, J3 y. N8 ?; K6 S$ y( ^; G
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
; f" k8 f8 h8 k5 o) J0 u使用举例:
# y( A6 O# v) ?5 {7 T! c" H6 F5 k4 P' ]" e# }6 U) ^
  1. /*
      T0 B- I( c- F
  2. *********************************************************************************************************
    5 V/ {& W* W7 f9 O5 x& P
  3. *        函 数 名: can1_SendPacket5 f% w2 b" H4 n' _  A, O& S$ m1 j
  4. *        功能说明: 发送一包数据
      [! x% q) V8 U& `6 M: J
  5. *        形    参:_DataBuf 数据缓冲区
    % u7 q  G" K4 W. w+ h( D
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节
    4 p5 ?! M& a! i$ K
  7. *        返 回 值: 无7 V' }: R( D2 Y3 g/ b/ H( t( h- ]3 O
  8. *********************************************************************************************************
    3 z8 r: n" E" J4 w: z
  9. */; F2 X9 u. s5 V  z2 C
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)5 V" i6 r8 O4 T5 i7 e6 p) E( ?
  11. {                * s2 A- A( v: I2 B8 A2 J
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};+ Y2 p' u  \8 ?: n! {! S: x5 y' c
  13.         
    9 p8 Y* S' ^, {. f: C/ ^
  14.         /* 配置发送参数 */) E# X+ ~) G) ]+ Z8 P8 I/ |
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
    5 z1 h% T2 u$ s, j1 {7 u
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */, w+ m9 M4 b% ^% S. K- f
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */6 F4 A1 w2 \& ]! T
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */% `" h( _3 u) S7 [5 ]8 ~4 F
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
    ; q1 {/ p" X5 M+ w' ~* ~% h
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */$ {9 t+ [: y% i/ k$ A7 z+ c
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */9 ^# O( F' C' R, T" s( Y
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */
    ; m( h- _2 o+ D7 `7 \! u
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */- P) A' b7 T5 ~1 U
  24.         " B- r9 Z% h8 s. x, `! P
  25.     /* 添加数据到TX FIFO */
    8 S* V& K, ~) `# _4 `( b
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
    2 n  m# b, _! `5 N
  27. }
复制代码
' _- b9 k8 W6 K4 x4 S( F
91.4.8 函数HAL_FDCAN_GetRxMessage
  e8 `* }+ J7 I6 D函数原型:' [3 K# g7 N$ ?% K" ?0 G) p

) i$ T$ ]$ y$ d; ]1 l- f; Z
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
    & X0 F" |5 b/ ?3 M  T2 _
  2. {& F2 y; x1 N6 n( ?0 S
  3.   uint32_t *RxAddress;
    5 h+ u6 i$ ^% j: h0 `( n" p
  4.   uint8_t  *pData;$ V* s& ~; B- B4 K
  5.   uint32_t ByteCounter;, f/ ?# E4 T. M* |, m3 ]
  6.   uint32_t GetIndex = 0;& ?0 S* G- I3 g5 v
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;# @1 n! ~; h- M
  8. 6 X, ^/ ~" Q. L" L! \' u* J* }6 a
  9.   if (state == HAL_FDCAN_STATE_BUSY)6 c; {  V1 Z, W8 p6 Y/ P( Z- N
  10.   {3 G, h- c5 ?2 v  s( d7 {
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    $ |9 c, r, D$ [; f( L' N
  12.     {
    : v& _- E' Q  E2 H: f
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    5 M0 `6 ~# \" _+ F
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)4 H' w+ ^- {2 _
  15.       {/ g0 U- W2 }1 v$ Z1 c7 c. T
  16.         /* 更新错误码*/
    5 d1 P) H2 J9 ]
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
      T$ {( H: T4 @9 v. O

  18. , J4 B1 S% ~: Z5 k3 o
  19.         return HAL_ERROR;4 l2 A2 W; k' {7 l6 X0 S
  20.       }5 z: G5 Y% r& A+ P
  21. ' y6 y" d' ^  i4 i3 ]
  22.       /* 检查Rx FIFO 0 非空 */# C! L  P2 x1 S' g4 X2 Z) V0 Q
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
    . o7 m# _5 C, q' s7 F4 |& f1 q
  24.       {  P3 t2 }2 _/ D
  25.         /* 更新错误码*/
    . y, v! c0 J- A( S& Q
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;3 j. D6 K' q) Z' y5 i( ]  Q1 q
  27. 4 W. t; H1 K5 }+ X" g! C' z5 x
  28.         return HAL_ERROR;
    5 y  ~7 E5 G; v5 D; F- F
  29.       }% }" }+ Q- Q4 w. U4 W
  30.       else5 F2 o1 v/ }. ~4 g- f# m
  31.       {5 q! C  o- i2 j$ o& L9 Z
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */9 N4 B8 T  X' j% \- M) w4 H
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
    ; i: U* Q. I2 f$ k( b( ~8 b
  34.         {2 u) {& F" D, `2 f3 P2 A! a/ ]
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
    6 M$ C7 E5 j. y2 E3 U
  36.           {3 N, e7 X7 D3 k
  37.             /* 开启了覆盖模式,丢弃第1个数据 */) `4 e- `4 v- k8 [7 b% e
  38.             GetIndex = 1U;/ W8 ~6 \, y0 X5 H' u: h
  39.           }, a6 \/ |8 c$ a* U" H% r9 L# h
  40.         }0 M' w- G4 C1 H' x* L* w  }- c

  41. 9 d5 J5 H' F4 j- B) m1 c
  42.         /* 计算Rx FIFO 0 element 索引 */
    3 d$ y8 ?" Y6 u# _
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);. q9 w  B' x6 m* H& Y+ {5 d
  44. ; o" [7 ~# N. Q2 S/ R! O  k2 g
  45.         /* 计算 Rx FIFO 0 element 地址  */* k) {8 K- s" I! f) N9 Z
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
    0 S! h9 U7 Y7 @. M1 ]+ n
  47.       }
    / {+ A) s' r& }$ g7 }
  48.     }! n3 g/ Y/ k  _
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */. Q% s# x- [0 [" ]0 }8 U
  50.     {
    * L) q8 {) T# Q. z( A+ o" l2 U. `
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */
    : {7 @5 R' O7 N
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
    9 n, g& `0 r% W7 t0 B4 Q7 U
  53.       {6 o$ ^9 c' ?& k- g- H
  54.         /* 更新错误码 */
    # F- p, T( i* t8 X/ d! l: n/ ]
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;7 l1 J$ C) w2 T& M9 r- x+ f, w& T* ~" w
  56. $ N" _" U2 Y" [9 Z# q  w2 c+ C$ U! n
  57.         return HAL_ERROR;7 z% h3 s0 F9 |
  58.       }
    5 g2 V7 [6 {" L5 p3 R& P) ?

  59. 4 H9 a2 M% _+ q, e$ h+ B
  60.       /* 检查 Rx FIFO 0 非空 */
    & R: C- K8 T9 W: v: n: w
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
    $ q7 ~* Y5 ^7 C$ r  g& J
  62.       {* \6 Z' P( f! J8 |5 U3 s  l' p- @4 M
  63.        /* 更新错误码 */
    , z' |3 ^% @* P
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
    6 t% K, \8 {8 z9 c

  65. 0 a- Q  d, _: R1 v4 j% X
  66.         return HAL_ERROR;
    - A8 ?$ a5 b/ H1 J- B
  67.       }
    & i3 s# E2 t8 G$ V
  68.       else0 e% r. N+ \, ~- y6 x
  69.       {
    % o. Q; n( q2 n6 K
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */& p0 G5 v- O& _
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)
    7 l1 b/ @8 Q( @7 l- h
  72.         {& j2 V  G3 ]7 g7 x8 E0 ~/ e
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)% a$ g; e) U1 \
  74.           {5 P2 C. C0 R6 H& l0 k6 V
  75.             /* 开启了覆盖模式,丢弃第1个数据 */2 _1 r! c& I* }- @4 K6 R) D
  76.             GetIndex = 1U;
    # E' |% |  e  ?# v: ^; C) {
  77.           }; d8 p2 T( U# o+ G1 N8 c" a. j0 _
  78.         }
    , L/ s% t! U5 U, f
  79. - W9 j( H; U: k1 c/ v1 \' \
  80.         /* 计算  Rx FIFO 1 element 索引 */1 F6 u& G) H8 a5 u9 v
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);
    " A) A6 ~. z. `  j1 M# m6 O

  82. # \7 }, s, J% y# x
  83.         /* 计算 Rx FIFO 1 element 地址 */& P$ I! n+ C9 z
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));! H, M' s: r0 n: l: D; K# h4 ]: [7 H5 J
  85.       }6 X4 v5 S; d1 \: S
  86.     }
    % }0 J( F; f- O' l
  87.     else /* Rx element 分配了专用 Rx buffer */
    + I% m5 M: q+ H3 I
  88.     {5 c4 g4 w0 y- V
  89.       /* 检查选择的buffer分配了RAM空间 */  ^3 O) F5 l1 w; b. u& O1 `8 w
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
    4 L5 {3 J6 F$ W$ X! [( o
  91.       {; l0 K1 C# L/ V4 R# Z3 R7 |
  92.         /* 更新错误码 */9 k0 e3 b1 A; V" F1 g2 b6 d
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    , x& G% D: k3 a; A; z
  94. 3 N) G8 L# f7 B' r( y* V
  95.         return HAL_ERROR;
    ( l9 r1 |" C, i/ x# A
  96.       }& j, D/ v& E0 H$ o/ I  v, {( x$ d. h
  97.       else
    3 e* g3 a9 R1 a, k4 K. r
  98.       {
    % _5 \; S% k& ?4 {  a
  99.         /* 计算Rx buffer 地址 */
    ; |2 |4 Y- Q1 k- Z( e7 v
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));& D) r; r/ U  v' \: o9 c7 n4 a
  101.       }9 S0 A( }' C& g6 A0 Y
  102.     }& k/ }, R2 k, A, i
  103. 3 h2 ^: V7 M/ l: T% \- F  p- ~
  104.     /* 接收IdType */
    7 z7 ~, ^, V: a" m+ r; n0 u' u
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;3 v6 O6 v) @: K- o  c9 I

  106. 5 i; q* g- ~2 E3 Q
  107.     /* 接收Identifier */
    0 S8 i9 F6 F  _1 H* \
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
    % U, K% S6 }3 k  @' [4 k; T9 s
  109.     {
    2 v# {; \/ v' F) n
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
      I" i: M8 \* I. \7 T& @' a
  111.     }
    % w0 v' m" b) \8 L5 H
  112.     else /* Extended ID element */
    : J9 U6 U& o0 Z9 I/ s% `
  113.     {
    ( E8 o3 o5 K/ y7 L2 w
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    ) y  A4 ]1 ?. `
  115.     }
    * L# l; w) B3 D+ z6 y
  116. " |& V$ }) C* N& J0 N0 ?2 Q
  117.     /* 接收RxFrameType */. T! ]7 R( l- W) b9 R' E) @* l
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
    3 b5 n5 M7 p( }! o

  119. / {4 J' D# d/ T9 T4 i* L+ K
  120.     /* 接收ErrorStateIndicator */) J8 F7 E5 I: y. ]
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);
    ' H8 k; ]! r. L* H2 v$ Z! [
  122. 6 |( X1 r$ D8 l+ @7 O
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */' \' c2 \$ p' O* l# L$ W
  124.     RxAddress++;
    # R+ R4 u; r! A' Z
  125. : A& S, d+ _  t) e9 h* b) L/ d
  126.     /* 接收RxTimestamp */
      @0 d8 h; e4 H1 d  N
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);9 P4 x  l5 C; {, S: ~" A

  128. 2 s% q7 v9 Z# A, D% g4 |1 n
  129.     /* 接收DataLength */
    7 Z6 s2 _* P: a
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
    . f( o* p* G5 e' P+ e
  131. ( }1 \3 d1 ]0 J0 ]
  132.     /* 接收BitRateSwitch */3 C+ y( e& y$ @- Z3 v- t
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);1 d3 B" U' A0 A& }& f. \
  134. - M: e# `) `3 a1 V1 ?" `
  135.     /* 接收FDFormat */+ W' B/ n. [& n6 s3 h" g
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);
    8 J. Y& ], N( |9 z* Z- @+ T( D$ w

  137. - o# _+ l4 q7 Z: O% W5 a3 b5 r
  138.     /* 接收FilterIndex */
    ! B6 P8 r$ ?# S/ P; B1 L0 y# C
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);
    2 }$ n4 M( y# G. F% f

  140. - x9 k7 Z( W( M+ r! U# G0 }) U5 _
  141.     /* 接收NonMatchingFrame */" B+ o# D& C; ]
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);
    0 c# C) B8 \; \* `! }8 y( d
  143. % m( q% T' f  U& k- H* _3 t
  144.     /* 增加地址,指向Rx FIFO element的payload */
    7 w$ }' H$ w. ]  p
  145.     RxAddress++;
    & p# |) o" \) ^% ^' Y) {2 F( ?9 R1 _
  146. - S' E3 k: d/ y7 d4 x) z2 @+ _. I8 E
  147.     /* 接收 Rx payload */
    * X9 R1 p$ E, }# C4 I0 w
  148.     pData = (uint8_t *)RxAddress;
    ' ?* r5 X! h! E% W2 N+ J$ R8 \
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)! ^8 x( h- y% z: A" N' \: [
  150.     {" f- T+ o2 p; {% P$ y' e/ `
  151.       pRxData[ByteCounter] = pData[ByteCounter];
    1 [4 O4 N! q0 x: x* P7 J
  152.     }
    - |1 t5 c/ y! l. x$ l

  153. 3 f" _8 q, _9 }
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */; B1 p# H1 |+ T
  155.     {
      F# C2 J/ W5 y9 {% i, ~- o) Y
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */
    & y$ [/ K, y- J
  157.       hfdcan->Instance->RXF0A = GetIndex;
    8 L1 Y( e0 N$ o
  158.     }
    / S0 J$ s1 L' [/ [2 W& E3 G8 \
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    - l5 a$ D- c/ X( t! e
  160.     {2 O. `6 X  H2 q6 {* D! a
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */
    # j) _3 s2 `) z7 F
  162.       hfdcan->Instance->RXF1A = GetIndex;5 A% W/ s& k" r" l7 {& D
  163.     }
    ' F+ d5 {1 A. ]: f' G
  164.     else /* Rx element is assigned to a dedicated Rx buffer */8 f) h( b) Y' e; h) u9 Y! H: ^
  165.     {2 ]& \7 s* |$ U* Y$ O# g7 B  h1 A
  166.       /* 清除当前Rx buffer的新数据标志 */0 C* N6 q- Z( O8 L
  167.       if (RxLocation < FDCAN_RX_BUFFER32)
    3 x" O  o0 n: V* ]# P. T7 m
  168.       {
    9 q; J* X6 L! n. b( m
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
    ) i( L0 }) W$ F( E
  170.       }
    ( M$ i: g  v  V& e& u
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */8 H( ]) n& W, c: }; Z
  172.       {
    3 F) p& r9 L4 X" m3 E% \/ t+ Q
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));! Z& M* h: e- q6 }; v; ~4 p
  174.       }0 H3 g$ }' E7 [) h  N$ V+ p) |& i
  175.     }, f3 q) y7 I" `( ]& F. K$ Z

  176. 4 V2 j( m' J; |0 D' {& N4 l, z7 s7 }
  177.     /* 返回状态 */
      ]9 W0 @0 I6 W8 w8 B
  178.     return HAL_OK;3 y. J7 M8 q# L( T
  179.   }
    4 H) A9 t% r6 H- i* d' B$ h
  180.   else- @$ z% S( ]& C$ B: B6 U$ h& B: h
  181.   {
    . |- Q& |( g! Z- C
  182.     /* 更新错误码 */
    ; {& x, F& I! Q2 r: _+ J: a
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    " i/ F* i5 D$ T2 ~1 Z
  184. & X: G& t5 p  }5 A( L
  185.     return HAL_ERROR;
    $ Q( d! n9 i8 C6 E4 Q$ y9 e2 }- n; v
  186.   }9 x4 q( _, N+ O+ n% H5 p; H- Z3 x
  187. }
复制代码
; K6 ?, t' L! C! y. ~5 d% s' W" e
函数描述:8 O: A# P2 @' ^% P4 ^9 k- d: \+ @

' R# U4 I% Y7 b0 a; F, `6 V此函数主要用于获取接收到的数据。
, H3 X6 t: h5 C
1 O+ r6 u+ S9 |, Q函数参数:
( G% f; J8 a# e* Z6 d& }
; U/ U+ h! D  i9 E; N  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。, {( [* ]! H3 H$ D! ~+ k; S
  第2个参数是读取位置,支持如下几种参数:4 i+ g, q. P% k& I+ c
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
    0 O7 W( E7 S  v; ^# c0 P
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */5 u$ z3 L5 G2 H5 @# Y
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
    , n/ S2 u0 ~0 a. S8 K
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */
    , I. h( O9 \. R% d0 ^2 \, K
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */
    : r& K* Y' v; |+ c7 ^( ^
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */! \1 x* w" ?/ B3 I/ H
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
    % i0 g/ W, `( d
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
    ' l6 U3 w/ q* y# [# j
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */+ C- Q! c6 k' _" @
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    * L- S9 j: V2 N/ Y
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */0 V3 m0 S1 c* g+ d9 _( A
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
    ' ?) }1 R( c9 I) m$ `5 x
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */0 U& }( s4 A3 e4 p; Y! M4 x' S
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */
    - T2 A8 H3 }3 g" a1 f
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */
    # m' C. h* F8 G! b* H! A
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */
    & f' f0 o- x- i: b
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */# y  h* l+ H) L% D
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
    $ k% Q3 t" ?- P+ W& \$ R& o
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */- s( x1 M& K/ W8 {8 C/ S7 b( B
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */
    & z3 Y6 q5 E( j) H, p
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */) Q% c+ Y; e  U; q. ^
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */( ]. D+ e# b& |" E# x; T% f0 X
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */6 H/ x7 c! ^7 ?/ B7 m- i/ }" I
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */, |; h, s4 u* I6 F
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */! Z" q2 J9 I) u8 g
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
    , s- l5 v( @6 I( t# {+ d
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */! n4 B* A9 o. [+ Y+ o
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */7 o$ }9 B( l' b; x
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
    ) G" @$ `5 ^1 W; L
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
    * w' o) ^1 A; ?  W1 ?  d1 ?/ C  U# i
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */& z0 |3 [+ H( i  `0 O
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */' Q7 \5 x% X, P6 e/ Z$ I& J. v
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */" v. F8 h9 D  L/ j/ {! Y
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */& {4 H9 U- o: h* _" a8 |
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
    ' y  R& N# I/ h: _& G2 a
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */
    & Y) @  S7 w2 _' w. q
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
    1 M; J% @  \9 f2 P* H) l7 I
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
    ! y" u1 W1 I, a
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
    ' m! N) {0 i1 [9 _/ [) O
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    ' Z6 i! \& A8 w+ X; ?5 R( E" K
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */' c0 w! Q5 O/ @+ e+ [) c5 n
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
    % d- U0 ]% e9 Z' s0 s# l+ i- y. `
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */
    $ C' X0 L- Z! V) l% t% p
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */1 C1 t) O2 a' @7 W' R
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */
    ) i  O. ]: ?7 X8 C* k9 J0 }
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    6 m: K' O) q* |9 d7 h
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */
    4 @6 J5 Y9 P2 `
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */8 z, B7 G' W% F, A( [
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */1 x/ i  m' @2 j, q9 C
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */
    - X/ u* P2 j( E9 t3 `
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */7 S4 e5 P: p$ ]& |) X& a7 V, c( Z
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */
      B. P" d# k! n5 X- `# x
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */
    & ^+ ]& f3 D3 |: U9 a; I
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */0 k; K6 s  T; y/ O0 f, E% X
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */. y6 Z) R( P0 [! D1 O9 L
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */: M  H  U" y- b. ]  B9 J
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */# x+ v8 I* I7 |. f7 m: N
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */" h; \4 {3 u0 R) ~) f2 ~* G
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */2 ^; H4 M' d1 r0 b. ^2 H, Z
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */
    + V7 A. I1 z9 I& X8 R
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
    9 Y5 |, N+ H1 k# D" v$ ^/ \" F* S
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
    $ g: C/ W0 F" A0 F
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */5 h, c7 D; n+ _8 }8 I& n  T: Z
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */
    8 a( `4 w' c0 P$ X$ n( c- c
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */8 E6 Y+ ]7 X- ^& i% G* F2 F' V# x
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码

) |) I, c; I% y  R$ N' x! i  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。
* R, g& O2 b' U8 S$ T0 E  第4个参数是数据接收缓冲地址。% G8 w# y8 U0 s6 u; C) O4 l
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。0 I9 J- |) \& z( h& D0 r
使用举例:
3 ~) @7 j( u5 M& a; F7 m( H, Z+ A9 Q. G- R& R
  1. /*( y4 C0 \7 H3 _4 Y0 k
  2. *********************************************************************************************************
    ! \5 |1 U! v8 I7 Q5 [6 [  B1 N
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback
    ' O3 o# I3 `# K% _) e
  4. *        功能说明: CAN中断服务程序-回调函数
    7 W8 |  T5 m5 G
  5. *        形    参: hfdcan
    & o" F5 Z$ p3 I5 P! b3 x1 Z
  6. *        返 回 值: 无
    & ]: y" {2 ]) \% p# P+ [
  7. *********************************************************************************************************; p# C: Z3 ?% ]! ?
  8. */
    ! ?, @$ D8 M( H, ]8 Y( R  Q: X
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    4 O7 d; g5 Y- C' D
  10. {
    & u9 F5 C6 B' _
  11.         if (hfdcan == &hfdcan1)
    6 p  x9 i% W' Z4 K2 H
  12.         {
    * N# E# T: N0 F6 w' ~
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)2 E8 E. a6 `0 B
  14.                 {
    & ^& {2 t$ w) U: ]! j1 Q6 o, x
  15.                         /* 从RX FIFO0读取数据 */
    * n& d) c( ~# d/ [8 D( c
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    5 y2 s+ V0 f* ~, J& S- ^1 `
  17. $ W6 N+ R8 U& m' i( h9 ~
  18.                         /* 激活Rx FIFO0 watermark notification */
    + p. N* G* q! `4 c! e- j
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);" }8 N/ w- o( V, n8 K  a5 s
  20.                         3 y( b# ?$ B4 T, N! e: W/ {' E; D
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID). U" N8 e6 P$ k, I
  22.                         {
    ; T5 Q% j- D) r6 b9 C7 h
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */
    / u' v( b( }; l4 k* U" U
  24.                         }
    . S" I# n! D7 ?: G, }
  25.                 }4 u$ I& [8 U2 [
  26.         }
    : y& E5 i9 U. S! U
  27. }
复制代码

6 M) y: C* C' v+ L4 H+ b, E! K91.5 总结/ E% A, f1 Z2 f/ x" \' X) J: D
本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。& Y: _1 g6 o* f' a% A, X4 N7 O

+ l9 u! R1 A$ |( p) B- u3 B, L( F: b
! J1 U' n, d, {; a
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

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