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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示) ?$ l5 |" A! f5 z% T; d* I
  FDCAN基础知识点可以看第90章,已经进行了详细说明
" }2 y2 l: r2 I  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接! h/ K& i2 `. Z# k( i( u  h1 G
91.2 FDCAN基础知识
, e/ A5 P; b; h. P% l. T6 I3 EFDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。! U" c2 t0 j: I1 ~+ Y  }
& b% V3 [. q! y5 }; s: n
91.2.1 CAN FD协议介绍
2 s0 s% m, Y4 i+ o* `STM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:4 G. j3 ?6 ?' E5 C) i
  {0 Z" x8 U. c% B
(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。% R% {$ f, V% n

& y! B& V1 z0 r$ ~(2)可访问的10 KB RAM内存,最多可分配2560个字。* ?* s' Y1 F$ l) ~4 r6 p( ^; A( g
9 v( t( r. L# K! p' W
(3)改进了接收过滤。
) ]& K( ?1 [& G  a  H- _. ~  ~* F# T) ~& O. E3 w( B
(4)两个可配置的接收FIFO。
9 R! T& q% w" X% |5 c, U
: q# `* {; d* u( z3 T4 m- s8 g(5)多达64个专用接收缓冲区。
- Z: b. W# t6 a5 N  l9 Y% h
( \! D3 h( e; R; a& t$ L8 k(6)接收高优先级消息时的单独信令。
8 f, C) n# e& ~% X
3 H$ n6 ]! w* X8 W: a# ]# V(7)多达32个专用发送缓冲区。
& d. e' @! `% ?5 h: Z) I4 `$ k- u! \
(8)可配置的发送FIFO和发送队列。
; D9 T' W; @8 d* I8 x" S1 O# U( m5 A% j
(9)可配置的发送事件FIFO。
& j$ _9 }; b% o! _$ M" J+ x( g- ]+ m. f/ Y6 v+ N% Q
(10)时钟校准单元。
8 r/ Q" X4 F' P6 m) Y% v% [' P+ S# L6 y4 Y0 @7 i( Z5 k
(11)收发器延迟补偿。
% Z' ?' H& ?9 P  Y3 N0 A  ^+ S4 O' b
下图说明了FDCAN框图。& |6 F0 E! O" S% v
8 q. r: N5 M- `" ~/ p  _/ a

- n: C. B" v" S; Y+ W' v/ v8 r& Z
f4f1d5cd872648458911e8be8ddfffe0.png
* N% H) Q- r+ ?9 P

) D4 s  Y) Z- N5 p9 i1 N6 I- k6 A
通过这个框图要了解到以下信息:
) Z8 J! m8 @. q  M- A3 s  ?
6 n/ p. E# B' m7 q4 M& v(1)CANFD1和CANFD2共用一个RAM空间。
9 t/ F; E% A0 q: B% O9 {: l
' u3 P3 u6 D) q% T8 W(2)每个CANFD都有自己的内核。$ ~8 q; ?5 ^! r
7 O" L6 y# ?- g& S. Z! S# s
(3)CAN内核实现协议控制和收发移位寄存器。
1 c" B, [% P2 z# u& E
& a# v3 l% k/ ~: _(4)Tx handler控制消息从CAN消息RAM到CAN内核。
6 a7 g& O* D# A% X" o' T6 g, C" H0 i; _* ~3 d% N/ v2 u
(5)Rx handler控制CAN内核到CAN消息RAM。6 [+ }, z* E$ h8 Q5 G

' s$ _" p7 {; D& m( n! n91.2.2 CAN FD特性
  x0 N: @( l1 Y# b(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。# r( W" C% c( |* g  a

( Y$ F' L5 q& E- H' V+ A+ z8 d(2)提升错误检测,支持高达CRC 21位的校验和。: g! P6 `. u. I. J3 e( ]9 n
6 }8 C* P" E% R4 H/ C3 m0 Q
(3)消息优先级。2 v5 M) f$ ], ~: u+ I5 f( Z' U

7 n8 p. |" I' s- G" @) `9 }% F6 l0 ](4)保证延迟时间。1 D) H1 c! I* g

* ^6 q7 W" k  p8 ?, G+ Z(5)配置灵活性。
- Z; B  [4 L3 m6 ^
% E8 Z4 ?# S% i" i) e2 P" i' A(6)具有时间同步的组播接收。0 C. C! E( ]5 ~% T5 K; o% \& F
) K6 e, [1 l1 \/ y, k0 V8 D* V/ o9 M
(7)系统范围内的数据一致性,每条消息最多64个字节。
/ f( @) {7 K, f- g, Y
0 q+ l/ C2 y" F, ~/ W) r(8)多主机。7 v# ^. x% ]* L# l

/ u/ y- }+ d. n! M8 L(9)错误检测和信号。
6 N1 |0 m+ Q  c
8 E3 g+ g* N( \$ H$ F+ L(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。2 Q- j0 q! g/ |  K3 O6 J! j
- @0 w8 j& i" {$ }
91.2.3 CAN FD格式2 j7 ?0 t# I- r. E  y+ q

' K: X& s: Q% t7 Q8 N
c692adda5a1149b0a6e3d8a30745fd62.png

5 i. D$ [7 Y* {' ~8 |
! [' Z" g7 B7 |9 f5 @- k
4 d; h4 ^2 N( [6 X5 U第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:* V3 L( H% R1 g& \
, }+ ]) B1 |7 b2 `
(1)帧开始(SOF)。  m7 b! S7 I; l
/ T! Y% _9 @: {' V- n
(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。
3 s( c  n: y5 @& c" M9 \7 j. ?% k. H. q6 X' S* K- u
数据传输阶段(The data transmission phase)包括:
! E$ t9 t# f+ F# J/ @7 V2 [# P8 J# H8 X
(1)数据长度代码(DLC),指示消息包含多少数据字节。8 ~+ j/ D3 j1 A$ `7 ?

; O, d: y" ]. U4 H2 J9 _3 i- K(2)用户希望发送的数据。, E( ?  f2 R8 Q; g

0 E, ^) @2 G; q3 D3 _- ~/ t/ T(3)检查循环冗余序列(CRC)。, M! O% r- y; ~, X* G7 y

8 r& t' {5 ]+ E- e(4)显性位。7 V. U# y/ G# S
9 v* N2 q) u, H  z1 ?
第二个仲裁阶段(The second arbitration phase)包含:
# H, i! E- H  C
! `. e4 X- R3 J0 G4 x% y(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)
! ]" w% t. V3 R. p- ]2 n$ J% Z: {9 h$ h! s% Q
(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。4 `4 w4 Q" ~3 A

- {- n6 l' r5 L  ]注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
% K# I6 d: k# l8 Y1 [4 e/ N
) s7 m$ q  a9 J! i91.2.4 CAN FD相比CAN2.0的提升
! |: z5 q7 n' ~6 ?CAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:0 X$ ^' T# D8 b- m4 H) Y6 Z8 k7 C
" u  k# L1 X; H
(1)17级多项式对最大16字节的有效载荷进行CRC。
# F/ r5 f9 O4 y9 ]5 @+ }8 U4 C5 Y! X  i8 K) x% D2 L( F8 h2 D
(2)21级多项式对16到64字节之间的有效载荷进行校验。
: F7 j2 w$ b8 v; U
2 q9 {2 K( W% Q. X2 b" }6 D* N标准帧和CAN FD的区别:
( w( ?0 U! @) t7 h
. V. _! j/ a( s9 q) x2 W* U
$ ]4 X1 L8 d5 r/ k
050433e4b8fe4f4d91de7eb85d5e6bdd.png
6 A8 j( [# m1 a- h) @4 K" ?
7 ~+ k0 B) [4 m& e
+ o: c, d% c% {
标识符后,CAN 2.0和CAN-FD具有不同的作用:
. p/ S' K% e! E, Z" ~/ L1 P/ n+ m; ~5 r& f# P4 I; R
(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
2 R& A7 w: G% k. t& n2 O' l: y9 z* `8 P" F% |
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。9 f9 u$ _2 m# r. Y5 G8 m1 e4 |' `

; @, h0 d' h/ f: A# i4 K* WIDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。- D2 L1 V& b9 B; _  F# @6 H4 E
2 L4 }0 [( s6 \5 x
与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:# s7 q* d9 R8 Q3 E6 w# p% j' V
3 [2 T* T, q4 p& Z# [
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。( i! @/ Z+ X& R+ g1 d$ a: _( ~

: c% N5 u5 s, B( g; I$ y, C(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
- M( H7 p+ C* i: _3 J
/ I2 S  t& Q. _  C4 u) X(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。2 B: N4 B7 o$ i* J

8 J- d- c) y8 g3 F; f4 }* @* `控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。# ?8 \. N) ^6 f% X2 M5 K3 v

3 Y6 @1 B' y2 P
3 F& C+ p- y( o% \2 j; g
c4fbc9fa3f184422a77784de5280382d.png

" F8 }3 e( p; K/ _, {6 |
4 z( B- S6 l  J# G, b0 c! v& ?8 `" o. k( P6 p  d
通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:" L! ~6 P3 y1 F( P
* J  N) S) J  n' r$ I+ u, Z
(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。; s/ S6 E0 v) _0 e/ w/ d
, p$ Q% [! y( x2 X' B
(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。
& R3 u. `& M- ^! }9 L& y3 A! u3 Y1 g; k7 U; \
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。7 @% J. J) G" F
9 m* {  p5 z' u- ]

" A" Q2 P) U7 T3 f8 i- K
a00dca8056bf40dc860b52366afa5197.png

  \5 T9 ~: K- u9 b" E- x6 u6 [" U' ^: L
: g8 ~4 v# U+ r4 ~% @+ y' O  U
91.3 FDCAN总线的HAL库用法7 E5 x+ v1 h" ?- d3 b5 Y/ o& x7 n3 ^
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef
3 \& A: t$ ]/ n/ z/ L# H6 Y2 J6 hFD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
1 u0 U) G1 J- I1 T" W* x" J% N: e/ J& x9 b7 x  y1 t
  1. typedef struct
    / p# b* N& k- X0 J" X0 _
  2. {# i- ]$ \. M$ d$ h
  3.   __IO uint32_t CREL;   % t) {& ^: S! p$ x3 J8 b# K, `; B1 E
  4.   __IO uint32_t ENDN;        % P0 b! ]) o  j' L& M
  5.   __IO uint32_t RESERVED1;    2 K( L" Z$ _. K' `: R
  6.   __IO uint32_t DBTP;        # s$ W/ \: S9 y7 t/ ~+ C
  7.   __IO uint32_t TEST;        
    0 |9 o. I# R- N  x0 ?! T1 C/ ]
  8.   __IO uint32_t RWD;         
    / J7 X% Y$ A3 a- D2 J( H
  9.   __IO uint32_t CCCR;         7 q; x) l6 _3 D1 [3 V
  10.   __IO uint32_t NBTP;         3 z8 n) q( b) H7 ]6 @/ V
  11.   __IO uint32_t TSCC;         
    / [+ f$ q  Y, g. V: @7 x
  12.   __IO uint32_t TSCV;         # Z$ \, g' K2 D
  13.   __IO uint32_t TOCC;         % L$ P4 q$ f6 H
  14.   __IO uint32_t TOCV;         
    & M# }9 P) x- f+ v5 Q
  15.   __IO uint32_t RESERVED2[4];- Z( N  r6 t- D9 F1 x" P
  16.   __IO uint32_t ECR;         
    . I8 P4 K( d# R. x
  17.   __IO uint32_t PSR;         
    # h( F( s2 @  r5 d2 `% y- c
  18.   __IO uint32_t TDCR;         
    2 G- R0 B5 g+ [" [& M
  19.   __IO uint32_t RESERVED3;    1 f1 b& S3 R: m
  20.   __IO uint32_t IR;           4 F/ i3 L( _% u" V2 o/ Z* \
  21.   __IO uint32_t IE;           7 D2 Y" e/ y/ _1 n7 j1 J" p
  22.   __IO uint32_t ILS;         
    3 N: r# H+ u3 L& G/ \  ?
  23.   __IO uint32_t ILE;         
    5 n. t, W7 b6 Y. q  g' M/ O
  24.   __IO uint32_t RESERVED4[8];
    + E2 L8 I6 v7 t5 V5 f
  25.   __IO uint32_t GFC;         
    4 a3 [- e' k; r% \
  26.   __IO uint32_t SIDFC;      
    2 o8 h2 L4 A. S, Z/ c( J3 ]
  27.   __IO uint32_t XIDFC;      
    ' _& a( O6 m! j
  28.   __IO uint32_t RESERVED5;   % \5 I5 v! o2 I/ M; ^) Z) c
  29.   __IO uint32_t XIDAM;      
    8 ~  f9 X/ U+ Q. {
  30.   __IO uint32_t HPMS;          |7 [0 k* ?- E' _0 s7 G
  31.   __IO uint32_t NDAT1;       % k3 }2 c* G9 a7 z3 B0 y. A( c* s5 ]
  32.   __IO uint32_t NDAT2;      
    5 U7 b4 I! b, k( q, {; S
  33.   __IO uint32_t RXF0C;        . l! S7 Z7 p: q  d
  34.   __IO uint32_t RXF0S;      
    3 j0 |6 w+ h- ?# M+ J5 r+ `
  35.   __IO uint32_t RXF0A;      
    . P/ a! Z+ Z3 O
  36.   __IO uint32_t RXBC;       8 B" x# d, x8 |
  37.   __IO uint32_t RXF1C;       ! P9 k. v: u- W5 F
  38.   __IO uint32_t RXF1S;      
    9 T4 |. g! l% o9 v
  39.   __IO uint32_t RXF1A;      
    % T  a% W  H/ s5 Q" u% M
  40.   __IO uint32_t RXESC;        
    8 W7 _2 h+ `7 [9 ~  t  _
  41.   __IO uint32_t TXBC;         + H6 K7 |. b. l* ~
  42.   __IO uint32_t TXFQS;        & l: C$ S: k& ~4 V4 F8 W
  43.   __IO uint32_t TXESC;        9 L- n  Z. H! B# b
  44.   __IO uint32_t TXBRP;        , X- k+ u2 y% h( G
  45.   __IO uint32_t TXBAR;      
    $ B( E9 B. U; K* U  E
  46.   __IO uint32_t TXBCR;        
    ; A5 K2 P+ C, k1 V2 O6 r9 x, u' z
  47.   __IO uint32_t TXBTO;        
    . G# M3 ^, Q* V, e) i) e9 s. o* V
  48.   __IO uint32_t TXBCF;      
    $ ]2 [7 a% M8 q; b6 ?6 _0 W, z) e; B/ M
  49.   __IO uint32_t TXBTIE;      ) t/ T2 t  F. }4 o; o1 ~
  50.   __IO uint32_t TXBCIE;      
    8 J3 h# s- O! b& P
  51.   __IO uint32_t RESERVED6[2]; , g6 D1 M5 s4 i+ d
  52.   __IO uint32_t TXEFC;        4 L8 X; E3 ^5 |* S' Z& u; u  D0 }5 w
  53.   __IO uint32_t TXEFS;        $ E1 Q8 i+ K9 \  X
  54.   __IO uint32_t TXEFA;        
    ( Z: K8 p- `+ ^* U  E, {$ T# _' L
  55.   __IO uint32_t RESERVED7;   
    4 ?* \& U  J9 n4 T, W
  56. } FDCAN_GlobalTypeDef;
复制代码
; ]1 ^) i$ F! P5 L& A
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
& _/ P6 \9 `  B: b' b6 n" a1 ?
1 \; B2 b- b" \__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
; F$ M  Q% ^2 M% W
/ g& }  O0 [/ f$ n2 L
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */9 D& T9 b' i  [* B3 E( S
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

% j- y- j6 [% L( M2 g7 R! H! z下面我们看下FDCAN的定义,在stm32h743xx.h文件。# m; I3 U$ f' T9 E( u# W
+ _9 s$ q8 a  o( G9 f! j) s
  1. #define PERIPH_BASE           (0x40000000UL)
    3 d# V0 e+ [: f/ o- ]
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE1 Q: {! D+ U$ I

  3. * Y# C, @6 K% J$ f8 P
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)
    $ i# c$ I+ x/ {8 [: u
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)
    ! ]9 w) u/ A# @1 r
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)2 z9 x; _$ h9 X4 Y+ G- H
  7. # T- c+ N) ?6 c) l3 u. p$ G$ S" `+ G  M
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A0009 c/ A2 A3 N# a( T9 j
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
    ) `! i0 b" {- H9 D
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码

! l1 p% b& G9 b7 K) y) P/ Z+ n我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。
! e. Z5 U/ g, W$ T
5 m7 C% X  a7 i91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef, F4 M% ~8 J# n- w4 i
FDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
2 O, }9 c' o! b* J5 `- j8 `$ n# M+ |& Q+ y3 j/ s/ Y+ E
  1. typedef struct
    ; I! x3 m9 I' @8 X/ B  B% d7 g& D, u
  2. {8 A! }3 j! @, X8 ^! }/ v
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */4 Z  _& f" H# l4 s
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */. D) h7 G$ ?, E- x, |$ k
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */
    ) t5 S5 z- o. Y
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */  I) J0 c! @: L. s
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */
    $ J+ k  d9 k- f' U2 f+ t
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */
    7 K' f( H, H9 U: B& b
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */' W# c! u2 e' F/ @
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */& T  y- z5 I& Q& T. r
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
    $ [( Z  ]1 {! \( R$ L3 R) |: n: X
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    % j, c6 N7 R: I& J9 x
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */  n( X& j' _0 p  w. C, _( a
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
    : L& }( K) I# g/ k; O) H. S# T- C
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
      i: j& i% s9 n, H8 g
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */# V) `) f* U& E4 }5 F8 Z- D
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
    5 P6 F/ d. u( _8 y" K  f
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    6 ~, j: q& X" m  o6 Y
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */
    # ?, Y% e( A8 W/ |  b7 g9 c
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */& `$ ]( V4 o1 G+ n6 f  u- n
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */$ U& z' D0 M% ^3 _8 H$ S% ~1 \
  22. } TTCAN_TypeDef;
复制代码
2 v# g; b5 w3 i4 k. {& `0 j
91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef
4 z8 ~1 H& I8 u. D下面是FDCAN总线的初始化结构体:
' {# t* p3 h- Y7 K' C1 F; f* E5 p6 A# G* P' x0 m( F) u  q
  1. typedef struct- F: ~5 N; k8 S0 F/ N8 p1 }/ A
  2. {
    ; l$ b1 y7 r: b6 ?
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.
    & u8 S9 g" Q  V  N" I6 V3 J1 E
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     */3 R; u2 O& _1 P: `" c

  5. 7 h$ S' Z! X' w5 \
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.5 T) ?; D$ d7 X  d4 |; L, f7 o
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */
    ! V8 {/ M- Y( J
  8. % @+ t$ F0 F5 b
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.
      ]: }" R3 X' s, Q
  10.                                               This parameter can be set to ENABLE or DISABLE               */
    & y- h: @; ~4 h& K9 u

  11. 8 L- P: k  z0 W. K
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.
    , T( d: ~/ l. L9 f8 n4 f
  13.                                               This parameter can be set to ENABLE or DISABLE               */2 n/ X: w" m* |$ l
  14. ( D: W4 q$ q: }+ t/ W8 S
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.
    $ R* Q  C& F( ]1 w! J* ]1 s
  16.                                               This parameter can be set to ENABLE or DISABLE               */, K6 a* N9 l( Z- v: p

  17. 5 K" M$ V+ {: W- y! K) D4 D$ G" M
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is
    * a6 m9 z) F, U* {
  19.                                               divided for generating the nominal bit time quanta.
    - |( b: Z$ N/ a; L  C( i
  20.                                               This parameter must be a number between 1 and 512            */% |) o7 a1 f' ~4 V" M' x

  21. , {% s  r6 ^, t4 k! A. s8 @
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    ) j4 D. u8 z+ L# F  v
  23.                                               hardware is allowed to lengthen or shorten a bit to perform8 Z9 r6 o; b6 y; ~% u
  24.                                               resynchronization.
    $ P1 j/ B. c7 t( ~5 L) g
  25.                                               This parameter must be a number between 1 and 128            */
    + [) m. R1 m  d( h6 Y

  26. # D4 b2 t* V+ z% B5 l
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
    : O$ E# {9 v3 b0 o0 j: H, ^
  28.                                               This parameter must be a number between 2 and 256            */
    . s; y3 O+ m8 p5 K6 I+ {
  29. ( O* x( G' G- F. T% e& {# \
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.* m3 _) H9 G& b* J  f
  31.                                               This parameter must be a number between 2 and 128            */1 J3 `+ y8 u4 J. X( N  G8 ?
  32. & T2 l# L- t7 u$ T3 i
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is
    $ a7 H/ n0 K1 X& U
  34.                                               divided for generating the data bit time quanta.
    ' ], b$ S2 A1 j
  35.                                               This parameter must be a number between 1 and 32             */6 L. C9 z/ m1 M5 D, k/ J/ |' ~
  36. 4 @8 g$ @* q- f% v+ ^8 I9 y& ^: g9 {
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN9 K( f  T) R4 `" O' D. O+ h$ X. p
  38.                                               hardware is allowed to lengthen or shorten a data bit to7 {3 g1 Z* e4 @
  39.                                               perform resynchronization.
    * V; G8 y' A) T$ d& m6 _
  40.                                               This parameter must be a number between 1 and 16             */9 q2 g, L3 u2 K, X

  41. ( j& Z0 j  i% V7 Y
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.
    + n  @% r" k* o6 V* B
  43.                                               This parameter must be a number between 1 and 32             */# k5 b% O8 a& W. z0 N' n8 u. x

  44. ( C; d, _+ x" V% c4 N2 i
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.* k- G8 ]! f6 {
  46.                                               This parameter must be a number between 1 and 16             */
    + V% B& q- ]) G
  47. 8 Y1 ^& q/ g0 g; d
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.% w3 J# O& E8 |' l
  49.                                               This parameter must be a number between 0 and 2560           */% g& x6 w% h% q" P

  50. / T" O% K2 t. _+ j! U
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.+ D, |  u) j2 a) w4 \
  52.                                               This parameter must be a number between 0 and 128            */
    6 C6 O. P9 l+ z4 _! ~& H' ?

  53. - H+ T" O& {3 X- M) F* e! q
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.
    ' G" k$ O9 O: z3 X2 J
  55.                                               This parameter must be a number between 0 and 64             */
    5 p/ o' ~8 S6 l$ c
  56. * D5 M: J" G4 `/ e
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.% X) T6 Q; p4 B( A6 k3 N
  58.                                               This parameter must be a number between 0 and 64             */" L& b' e/ `# N  \2 e

  59. 2 H6 Y2 p9 O4 c) ?2 ?% D8 a
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
    1 m+ j6 u$ M3 X
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    . L5 b, W/ g. j4 d# P; I/ P
  62. 4 Z) F! S2 [4 c5 t
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
    2 p" o0 t. X* S" Q% m
  64.                                               This parameter must be a number between 0 and 64             */
    & f9 r- t3 `0 e' e  S5 l
  65. 6 m0 T  A/ N0 c% b# `& @- S9 r7 c
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.; r! L6 E0 l+ }
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
      o8 m$ y  s/ {$ r; x* |
  68. ) X9 K+ ^- @4 a' V' D
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.: l" ?  t# @9 A/ ?" |( t
  70.                                               This parameter must be a number between 0 and 64             */; S) M" P6 l; U# c" U% G& |1 H

  71. * g1 ?% V) n$ e$ d
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.& K; [/ y5 a% G9 t' s2 m  a) N
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    $ Y' V  e" E" F9 c' K, m* f
  74. ! e  j8 T& o' k/ E3 i, N2 h( E9 h- [
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.
    & d" z2 _, e" y* a
  76.                                               This parameter must be a number between 0 and 32             */2 p" Q& [" F; K* ^- A

  77. . k( x3 R) s4 b
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.
    3 s5 K/ U8 d3 X4 j' ^+ J
  79.                                               This parameter must be a number between 0 and 32             */" q- s7 ^; `$ k4 K

  80. 4 |- [. W, z; P9 R  @* ~7 @
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.
    9 M- s  H/ X" |9 w6 k4 M
  82.                                               This parameter must be a number between 0 and 32             */
    $ L$ ~& S, M) |

  83. ( F3 `# k" m4 R0 O  Z
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.
    $ b. H+ h! I. |6 V3 w  {5 g
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
    ) k4 Q% G) V. x/ i, _! Y& ]
  86. 5 d; y: \$ v# j  q) E
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.2 Q8 }7 Q1 G! R7 E8 S) c( q
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    ; T: A7 U# q7 _8 n" r/ i

  89. ! q' t. D5 S4 }/ y
  90. } FDCAN_InitTypeDef;
复制代码
' d/ Q# Y: F  _& G& Q+ F$ ^
下面将结构体成员逐一做个说明:1 A! t, p8 E$ D5 v$ P* e2 j
+ w3 l; C% i# U* E: J
  FrameFormat. t% m5 z6 N- Q7 _, e
用于设置CAN帧格式。
2 r$ \7 I  b% p) `8 I
) ~% G+ m( i. j
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
    " p! X6 G9 W* H% I: i, m
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */" K6 A. s+ u. \# _/ ]: ]- O
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

2 o5 u8 I) V: P- o, G5 X! m4 @  Mode' A9 P$ \4 G* `3 S' ]
用于设置CAN操作模式。8 q& Z+ E- ~' k, @, `

& R1 I9 Y  x4 f, F- U
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
    / ?7 K, t- S* Z7 `. o
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */# [: @  G) |0 E& i8 t
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */' Q8 q) g& V& p1 D$ X
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */: j" H7 z: I. ~0 X
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码

9 }7 t/ y# {' c$ j  q  AutoRetransmission
! h' Y. A. [. Q' C' w- k0 H# F* h使能自动重传模式。
: h& W' u, `  `
9 M9 Q# R; I- ^% `2 z8 C4 ]使能ENABLE或者禁止DISABLE。
  R3 X' K# J6 z) n4 d# ]% Q+ i" E$ L% R1 ]/ F
  TransmitPause1 b5 A6 e, l9 J2 I4 o) w6 U/ M
使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。! [* L3 V$ F! O( S

% y2 j0 p( s: k, h  ProtocolException
. Z' C5 Z( `( ?$ L2 ^7 @使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
2 L, k7 l) ]; E/ o; ]$ X5 d. V6 Q3 L
  NominalPrescaler
8 ]% _' G( }: S/ F/ ^用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。
1 r8 V  T  f0 z9 n0 p
* ~$ W& H) L) y- _  NominalSyncJumpWidth0 b( J# G4 c* f5 w9 D+ A8 _0 ?
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。
, M' o- t* O' K
7 B2 H  z5 I8 p. G  NominalTimeSeg1
5 c. A  Q  f3 m( C设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。+ ^$ B1 V2 l; G* D# ~
( D+ U4 Z: W5 T& H, h* E: T" P4 j
  NominalTimeSeg2# a6 M  y) H- Q7 g
设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。
- L  P4 U/ t; Q
4 r8 F$ @/ _: G0 L3 [  DataPrescaler/ L2 [  d: L% ?( |' i% \
用于CAN FD数据阶段分频设置,范围1-32。- h' x* K( N! s( K7 z/ i4 L& y8 _
( q& a, a" b/ g- W" D- S  g
  DataSyncJumpWidth
) R3 j9 j$ x' g, J1 v. B1 |设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。
: e9 S* N- ]+ s+ Z& f" r+ }) `/ M) Q$ T3 P8 b1 e& e7 ]
  DataTimeSeg11 f. W4 T# q/ i
设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。0 j0 K* I4 Z$ d
$ V6 n( q4 I: k! L: e) V
  DataTimeSeg22 [$ ]* t# ~9 k. K0 I
设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。& _0 T; M9 k" _4 z' g5 q

1 G- q3 b; q0 Z  MessageRAMOffset
0 N9 ~2 S. K) s设置消息RAM起始地址,范围0到2560。
3 n  B# G9 ]! H% z, o! ]+ N( I1 x7 F* G# `" P1 T5 v! ?
  StdFiltersNbr) x( Z! l* H' ~+ [# ~+ D, U
标准ID过滤个数,范围0到128。: ?* q5 v7 T: S) a3 B9 v
7 F9 A* q$ h. ^5 W
  ExtFiltersNbr
' d$ w4 d; y: y/ F扩展ID过滤个数,范围0到64。
4 t/ Q! g. h. {3 M+ E) _" c5 _7 A( _2 Z" F7 {6 {. v. u1 \
  RxFifo0ElmtsNbr, G7 h* |/ K% a& N. ~) \* f
RX FIFO0元素个数,范围0到64。
' \; i: n1 R0 z5 d, k% m& b$ U4 X4 P7 G( g3 C0 b+ O
  RxFifo0ElmtSize. z; t4 }+ w5 c& X4 W& r
RX FIFO0每个元素中数据大小,支持参数如下:% B+ {8 [( \+ T8 a
! ~& {1 L( _0 V0 z
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    # ]. d  X; d0 g9 G9 }9 R( u: @
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    . C" A4 ~5 r8 t* V. G2 E
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    / x- r) l0 h/ G( |5 g) a" f
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */7 x8 }7 u* s' M
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */6 `4 _+ W+ z8 [4 U8 R
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */4 l/ I' F6 c0 M  C
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    ) U, I# X: o! k$ q8 ^8 @# X$ J/ @
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
+ T* o( b/ J9 R  k6 e# n" Z
  RxFifo1ElmtsNbr0 N4 t9 v7 m) d' [  q5 K
RX FIFO1个数,范围0到64。/ i4 @; _9 W) \: l( l

, U' u0 F' K, M5 V2 t) u  RxFifo1ElmtSize
3 V8 u6 R. \( r( l& d5 IRX FIFO1每个元素中数据大小,支持参数如下:
" x& U/ C" k  |; C4 M  H+ \% Z* U% t: M1 }% i- \- v1 J. Z5 D
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    3 L& ?7 X! i$ i! b
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    ' ?4 F3 Z' `5 W. K' B( i
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    % O4 `# C' C; w: F6 ?0 }/ D
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */4 [: N0 @9 u: l6 [# j
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    ! }* v3 y2 l8 F
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    # F) l& ^$ K  t0 V7 Q
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */; z5 `, c6 e4 U
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
; J$ c( }* v$ e: }0 ^
  RxBuffersNbr
* a* |1 I/ l8 o设置Rx Buffer元素个数,范围0 - 64:
8 R% g/ u2 @+ y, C8 v7 Z
' |9 u# I* ], m. I9 q  RxBuffersSize
+ A  \6 D7 r/ m4 J- _设置Rx Buffer元素中每个数据大小,范围0 - 64:' z! }2 m7 N, n
9 ~$ Y* @6 X- |% C9 L* \( J+ Y# X1 s
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    5 g7 G* R# f- \- l) y4 F) ^1 l
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    - _0 Q* o5 O! p# c6 l; W
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    ' @4 p+ }$ Z1 Z
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    + I; }1 C8 u) D$ i3 S2 g: O
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */1 B- y8 y4 @2 H( H
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    4 A! P8 R, k, m) s9 k# M
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */: u* ^( X$ i2 J5 B$ ?& R9 }
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

1 u: g8 P: ^2 P3 h+ A  TxEventsNbr0 j% X9 b. I0 e  A2 P% y: Z
Tx Event FIFO元素个数,范围0到32。
1 n1 F' M% C1 g' D2 M5 _' l* w9 V7 r0 |
  TxBuffersNbr$ `, w. _' x9 y& U  V
设置专用的Tx Buffer元素个数,范围0到32。3 ^  m4 \4 s. U& P  l# k. C
  n' A4 P5 ^4 R( _- E, G$ I5 L
  TxFifoQueueElmtsNbr
/ h6 C5 H& |2 r3 S- O$ o& H设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。/ q6 E) y5 F5 f& n+ c

* a+ A3 |5 g/ ^: b  TxFifoQueueMode
1 H) [* G2 E) s8 e0 }设置FIFO模式或者QUEUE队列模式。
: n3 y5 r) S8 V% F* i) s
" B2 t6 Z$ h. _9 q# D$ D3 P$ u
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
    # k# l* n$ c: [5 u1 n2 T! i
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码

; R1 B7 c8 O9 W5 ?* k# H2 Q  TxElmtSize9 \) z. y5 P9 @4 H/ C9 M( O  ?3 h2 |
设置Tx Element中的数据域大小。支持参数如下:2 b( \! {) y) Y& y: K: T1 e! r
2 j( Y# i3 N* `8 P* {
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    " m# k' J' B+ G5 U
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    6 h' [3 V* s; f0 d) l5 c' [* ?
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    + I( e7 C6 F" E  @' w
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */2 J+ z  r  i" i& |, r2 G0 A
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    & x+ s0 u- a# S& K
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */3 ~8 F+ s7 J" B" ?& u
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    ! N8 Z7 i" A1 }& |" f. E+ p
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
8 f( D4 t! M; o4 F5 _
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef- q0 o/ R, `# {. _* w7 |$ [# a% {
下面是消息RAM结构体:
! L6 n7 X- d* [" f
  1. & |. j+ i2 y4 f: x* q" ?
  2. typedef struct
    $ N7 {. M/ U- r0 X
  3. {
    " }& V+ C8 _0 Z- J
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.; ?( Z! k% W+ C. X
  5.                                   This parameter must be a 32-bit word address      */- [3 z' E0 ^9 v$ X1 `6 n- b* h

  6. , w1 q4 W1 D' h' X, ]
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.
    1 @$ C) Z! T4 N
  8.                                   This parameter must be a 32-bit word address      */' F6 `  Q8 {0 J/ T
  9. ! ]) U+ p- i0 N! F
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.
    8 O5 J! ~; d6 g( a
  11.                                   This parameter must be a 32-bit word address      */
    % ^3 q  n* S# w$ `" A

  12. - }& t% A+ C- m! w' b8 @
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.8 u6 L$ S6 x: g( u0 t7 S
  14.                                   This parameter must be a 32-bit word address      */
    ' F' M' g+ V! A

  15. + P/ H  d- S! C% _' {
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.
    * ~% D4 P; w/ F& U
  17.                                   This parameter must be a 32-bit word address      */) w. M) G/ |7 r8 G
  18. : d: T) u$ |+ M
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.6 S, i! S$ d2 _0 i% }4 S; ?
  20.                                   This parameter must be a 32-bit word address      */
    5 s- W; l# C) H) c1 d
  21. 6 W2 f1 Q, u: F# z2 H* n% e
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.
    ! v" Y9 e0 j. s, `6 E# l
  23.                                   This parameter must be a 32-bit word address      */. s+ P( M; W' y7 j+ E, K( G" J
  24. . f1 n: M' j2 W
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.' v. B. j: n8 G  G
  26.                                   This parameter must be a 32-bit word address      */
    . n: n( G* n# o% p% K; |
  27. 7 X9 @* Q, Q# {0 b" C* v% O2 `
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.3 B% S7 f8 o0 f* q; @
  29.                                   This parameter must be a 32-bit word address      */* m. q0 X: B5 U6 g4 Y# F$ l

  30. 7 L1 l. b) s6 }; g" a! a- i& Q1 z
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.
    ' M* r! X8 R, _: d/ D5 ?- [
  32.                                   This parameter must be a 32-bit word address      */
    & G3 A/ K( u  q7 n+ B7 p4 @

  33. & a: d  ~8 V1 T: i. u- X$ _6 ]' ]
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码
& ^  _) j# w, w0 P9 }* u+ G
下面将结构体成员逐一做个说明:
9 }  i. y- R9 ~9 J1 O) N
" C% R. _5 [! d0 i. y! L: z  StandardFilterSA
3 ]5 j8 [3 ]& B$ [/ i+ E; s* f设置标准过滤器起始地址,必须是32bit地址。
. _; E/ j2 U4 B
9 f+ W( m5 L% ~  ExtendedFilterSA. u+ z* J2 o% x+ _
设置扩展过滤器起始地址,必须是32bit地址。4 d" y# {) A8 c+ n
" F5 w  e8 X" M4 N
  RxFIFO0SA$ d/ X2 w! b; y
设置RX FIFO 0起始地址,必须是32bit地址。
; i5 X) x: }0 a+ H
+ w, i7 C0 _. W! N- Q6 H  N8 O6 u  RxFIFO1SA3 L; `2 Z; o4 v' ?) t
设置RX FIFO 1起始地址,必须是32bit地址。2 j- l3 w0 u8 S& P; ^
$ z/ \; _! B3 D# H
  RxBufferSA
7 O4 ?" m1 F! V% S设置RX Buffer起始地址,必须是32bit地址。
6 W$ ^  z5 ^, R" t4 e/ H4 T8 x3 x. q
  TxEventFIFOSA
5 g" G$ L, |+ w) n; i' _# A设置Tx Event FIFO起始地址,必须是32bit地址。
6 N/ D" g% G/ A5 h) _
( X' s6 p" H8 U" ^  N; Z8 `  TTMemorySA: s' i1 q! y& E8 }8 }
设置触发内存起始地址,必须是32bit地址。, u1 b: Q+ B3 J  T4 T3 E8 K& K
1 H! F  H9 |0 ~6 J4 {
  EndAddress
/ M" W+ I: k3 H) s9 g4 X9 O* \设置申请RAM空间的结束地址,必须是32bit地址。, Z7 B+ R7 `% a# G" _

/ A% _+ T" e+ M# V. X% p91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef- S9 q4 E, t5 ^) U7 X; u1 P
下面是过滤结构体:
/ F$ Q# \& Y* x3 o/ m. B  f9 ~( V
5 U, m- ^* k; G2 [
  1. typedef struct
    5 [8 w7 g6 b$ b9 ], _( v
  2. {
    - X1 d- s0 \* ~; s: T1 ^
  3.   uint32_t IdType;           /*!< Specifies the identifier type.
    9 M: q8 _6 A7 a7 C7 O  k, H
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */
      d; U2 k2 i5 b! X9 {* K1 L
  5. 7 O) e) b9 Y9 R& W; V4 |" W! C% m/ e
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.
    8 ^; ?1 t0 `1 V( w# u. X/ R
  7.                                   This parameter must be a number between:" g5 I8 i1 Q- E: y* [( |
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID
    : w0 e0 O; S% k7 A$ A9 o
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */6 S' w& [, I6 N* V/ Y( k2 z
  10. 2 {1 C# I+ V$ \, l, T, `0 p
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
    , j! F7 m, ]- {# |, ]
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.
    / }) g% `. Y# u
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted# x- U: c! }% d
  14.                                   only when IdType is FDCAN_EXTENDED_ID.% S1 P0 u0 z" D5 ^
  15.                                   This parameter is ignored if FilterConfig is set to
    ) k1 K; C4 J; Z1 Y
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */
    $ c5 t* |. [* t" X1 u/ S" q

  17. . O  F5 L: @$ v( x1 ^
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.' m. ^0 D2 v7 x: b0 s2 c' C# J: J
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */9 ?( u$ p6 e' \" ^
  20. # |% O) `* q9 ]: j! y
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.& l1 ~/ W6 V$ t0 l" J
  22.                                   This parameter must be a number between:
    ' c  L! ?& p, o/ A$ W9 M
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID2 q" F0 z2 q) t3 M. q
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    5 z! g& c: p+ p5 f/ G5 ~5 x
  25. ' |6 T2 @" ]* k0 {  j* N' m
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.( O5 P, E7 m# s
  27.                                   This parameter is ignored if FilterConfig is set to
    . @1 V+ N4 T- V* W. C* k/ Z  E
  28.                                   FDCAN_FILTER_TO_RXBUFFER.! f. V3 R; b" x2 l6 `
  29.                                   This parameter must be a number between:% C+ v% K* \* G" D! X* \7 k. g
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    1 k& b0 p. {' d1 a+ `1 ?
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */* ]1 V. B1 `) n. f

  32. $ J8 c, H" U7 N" R* G' K
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the) R$ u4 A# @8 j$ l8 F) p6 P; ~
  34.                                   matching message will be stored.  p. m$ n6 D7 {* B
  35.                                   This parameter must be a number between 0 and 63.
    * x7 t! a( d8 V* ~
  36.                                   This parameter is ignored if FilterConfig is different1 g+ h' q/ Z2 |0 T( }. M8 @( V
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */
    " G* B5 r; f, M1 ]8 a
  38. & C9 o, v/ }8 q$ D/ W% p
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
    7 }3 r1 A1 t$ L. Z4 ]3 f
  40.                                   calibration messages.! w# K6 B9 o4 G/ B% N  L
  41.                                   This parameter is ignored if FilterConfig is different3 I; `$ n( b: c! [. J3 b
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.
    ; @; ~( t) W2 n2 M% ~# M/ j$ E
  43.                                   This parameter can be:6 y# E. ?/ z3 G) ?7 e8 q
  44.                                    - 0 : ordinary message
    7 [3 k) W7 [8 w4 }
  45.                                    - 1 : calibration message                                */
    7 y6 B0 o1 Q; Z5 x0 U7 @+ P! j9 f

  46. ! [! ?1 b4 l# g3 F& b8 c4 G
  47. } FDCAN_FilterTypeDef;
复制代码
5 T  E7 J% ]3 F* C  M
  IdType
; Z# n4 V" i) q; y2 v3 \用于设置标准ID和扩展ID。4 d8 S4 j6 o0 a% _8 d$ }5 A8 K8 T

7 _! }% `5 x9 D& Z8 G
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
      Q, t/ f5 p' h; h# x! `' }
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

/ s* H' U# o1 O/ R8 b* ?! V4 y  FilterIndex4 F2 t7 L) h8 N. l/ X
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。
, c: s5 Y5 m* i0 D5 h6 L7 G/ q8 I" l( N+ B
  FilterType
; ?% x+ B! y+ A" H; g用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
& q( V  M1 O" O3 F' a  H7 x5 Y$ f1 B7 `- J: y
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */
      b- s8 |& [/ U; T) J9 [
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */
      D+ E: \* n" f* T1 ?

  3. 4 E3 q( M% m4 k2 U" F( p* O
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */8 `. X" C1 g; ?3 |
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)   r" Q- ^% n% M7 _( {

  6. % f6 Q8 h! z% c- w, w" k
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */5 d, m% G' S' l1 j2 t' p
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

# L/ L) X# p& l, @9 S' G  FilterConfig
8 E2 L" p4 T; J$ N% S8 ~用于设置过滤类型。
8 z- L+ c: d4 u( t4 Z. {9 J7 h! o! M5 `, w% M0 |; G$ j  H
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤* E- f3 X8 \6 U0 I% [6 ]% b2 h
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    2 e6 g) Z9 F- f& b
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1; m1 O: t5 N6 Y) @2 q5 v
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID' o" C# T% y, ]% y
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
    0 R3 w4 B( b4 f8 x
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
    ; G3 K1 S* l- r+ C. O( M% i* y
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1
      b1 m; A- z& j( J& [2 K
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码
- K- o) h% _1 ?+ Y7 X  e9 l
配置. [! `' @! _: |" X. j# H5 h% ^6 _
  FilterID1% ^9 N5 d- v5 ?( @' r
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。
* D% z$ o! D, u% _% S& y6 l# G/ l; O& K
  FilterID2
( U  R! B! t$ G8 ~2 ?# D9 t; E用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。+ O/ Q* h, ^) N' D( O" r, m6 k  Y

7 P1 p1 s4 o: J+ s  K' M" x  RxBufferIndex
( s. J1 }  b/ a/ H: ^! n4 M3 n匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
0 M" |( D/ s% D& S' Y
6 e- b; x: e# q! H& F  IsCalibrationMsg0 E! U8 V0 c2 g) i' y
用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。# ^( x1 x4 l! T0 c5 n5 r+ Q

+ j* r! p% C3 R9 m1 L6 @0 : 表示正常消息。
$ d/ {* m  ^1 q! |5 i+ c. S
# s; y% C4 P# t# r( o, u* G6 u3 |1 : 标志校准消息。4 B4 O4 I4 A2 o! e
* A) H7 M7 x8 G4 n$ l7 I( ~9 V
91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
7 M% |; w3 h% m8 J. w下面是CAN FD发送消息结构体:
) @  v2 w) J  L1 \: U! F7 {5 P1 o  ]3 E$ G, C
  1. typedef struct
    ( M; \& C6 K7 A. H9 H; `) {
  2. {
    ! l- q9 x* y: B
  3.   uint32_t Identifier;          /*!< Specifies the identifier.+ {$ R8 W" ]) r4 Z( X  X3 l
  4.                                      This parameter must be a number between:
    - A( r0 M0 C* ^: S: W, h
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    ! I1 X2 L9 p* ~' z* i0 f* l
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */) u" ]& s3 e3 s0 ~% e  e7 t

  7. # ?  i6 h; z/ Q) N# D
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be+ ]4 Y- _2 d2 n0 U# F0 Q6 G5 h
  9.                                      transmitted." j& w* ^7 _( h# n. K6 l, U
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */
    4 v& [5 g3 T6 D: o9 O- i. r

  11. / A2 s! q9 X% i0 `) f( `+ s
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.# E' l' ^% V- m" h3 ~* A' P
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
      d/ W# \) ^$ |" y

  14. 0 H1 U+ x+ @! N3 U/ ]- u
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.8 U3 g' D# O$ m& p* Z
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */7 K. a% g6 R4 i3 w! G8 w2 p2 \6 n

  17. : [* j0 |: L7 h1 Y7 H/ v7 I1 {
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.+ i% r0 R, R9 G( m+ D# k4 T0 Y
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */
    % F4 t0 M! E6 q, O/ y4 t
  20. 7 A; V- c# E5 O4 t: w# _
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
    + {. s* ^3 p5 s" s
  22.                                      bit rate switching.9 P" D+ G# `# d6 C8 S+ ?' U
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    ( O) k+ ^# n1 A) b$ F/ X/ q: y: x1 \

  24. * l; ^  K5 s2 E" ], w7 L. O
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or4 X/ `7 b7 {/ B& ?
  26.                                      FD format.0 }" R$ R. b' \# u
  27.                                      This parameter can be a value of @ref FDCAN_format                */
    ( f3 e7 t, \) m
  28. - F& d1 z3 |" Q1 P6 p0 f
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.
    - @2 m0 B+ W; b* P
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */. M$ H! e) N% U
  31. : F7 ~8 I8 b2 g9 R* a, m+ T
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO
    + D+ e( c) ]  V% R
  33.                                      element for identification of Tx message status.+ W, c+ ~6 s' _. Z
  34.                                      This parameter must be a number between 0 and 0xFF                */
    ' Y0 ^& }3 J- V7 F
  35. 7 \, G6 L9 f6 T+ y% E
  36. } FDCAN_TxHeaderTypeDef;
复制代码
0 e/ Y+ q5 ?( W+ b  j( ]
  Identifier0 n) h  y( [2 N4 t* O" o
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
& z. z/ A, M% I' f+ Y: [4 J5 x8 v5 q2 Q2 c5 i5 F0 u
  IdType- ]* a5 ]8 b' t& _7 w$ J+ r
用于设置标准ID或者扩展ID。
8 v( Q* V7 |+ H2 @
, l3 M4 c. v- l" |
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */' Q/ z/ @) N$ b7 U8 J( j
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

3 ]6 y2 y5 [" s# R; U# Y" W  TxFrameType
- z( T; u7 O" p2 e3 _$ R用于设置帧类型,数据帧或遥控帧。
" D9 P, N7 O, Q$ z5 p8 h& A& `) O; W2 z
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    & ]' s1 l& Z" g+ b4 P
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

7 I9 Z- {2 u) {) l0 y+ ?. p  DataLength# H& B/ U" R" O
用于设置数据长度。
6 e6 Y; U2 U. o8 H' s
; F8 P1 c1 k3 s: H3 R" ?% V2 H% n
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */+ t! M4 l8 q( I3 i  L; j# H: T1 X1 w
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */; y3 L! G& G* _( \+ B, H5 c
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
      X6 b" ~3 }6 ~& m0 m8 e* s* l
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */" {6 [/ R1 ^$ h- I6 T+ V4 U  h
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */7 Z1 v5 g2 ~; @* m  r
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    1 P% C8 L2 }: @9 l, X
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */, d) s; }* h, R7 W# W. E
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */1 t( y4 x3 m3 [
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */, d6 a( `, x, m# A- Z7 d, F
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */6 Q$ |8 @* i: T' F; p
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */0 Z& \0 u6 j% j/ r  c6 n+ _8 B
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */. W# R- v2 o. T: b# w
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    $ H) |" `( m0 j1 a
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */* F. y) A5 w8 y  O2 m6 r) D* H1 g
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */2 Y- _  f. ]5 C9 f" j9 ^5 z
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码

7 K# J4 {8 \, q7 _  ErrorStateIndicator0 P7 k- M6 Y" T9 D# v2 C. t" d
用于设置错误状态指示:
- e& V5 l6 v( u* j% R
# h/ g2 l: w  s6 }& R) O
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */2 Q1 @, O5 H' J1 S# h0 j6 O8 f
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
7 a; [  G. @" H2 y2 w0 M
  BitRateSwitch+ U3 V$ y- v) ~4 {$ _# E) \7 ]) J
用于设置发送是否波特率可变。
3 ]( U4 |6 f' Y( K5 l4 h6 J$ a; d! e1 R1 j
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
    ( f2 e/ K. v' Y$ @
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码

: o9 V) W4 f6 |  FDFormat
$ N4 t/ \9 n0 z) j- {1 ]用于设置发送帧是经典格式还是CANFD格式。1 k5 m2 C( }1 I: t$ r

  1. 1 _- ?0 @4 ^, Y- q- O
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
    5 b6 S% X& C( e/ R' l& a
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码
+ w. ]( Y2 ~: F5 g
  TxEventFifoControl
5 _- v" F& i- @) |0 L) z6 G0 E1 o用于设置发送事件FIFO控制。  W* U6 s0 y$ j0 l8 I8 p

  a2 D# a6 G' \" ^* Y" `$ m- h7 Q
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */% \& {2 z" h1 B/ @  C# o0 T: N
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码
% X4 h: W5 {# }  I! B6 O9 c; n
  MessageMarker- j0 [+ E$ ]- G  S. Q
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。
+ z1 [/ N  h1 g9 a: x
6 [3 q# X0 @; y$ _91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef( {* i7 p7 c3 K) m5 H
下面是CAN FD接收消息结构体:
8 Y- l; a. `0 p. |7 U0 F4 Q
% p4 Y) R, c% i
  1. typedef struct+ X& \: I( r" ], B5 i
  2. {+ v8 k2 h% ]' y' q
  3.   uint32_t Identifier;            /*!< Specifies the identifier.3 l% w6 s0 J( J, n* |+ H4 c
  4.                                        This parameter must be a number between:
    5 q: ]1 V. l. C6 K( {+ H
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID9 \6 j: `$ v$ D& U0 p. P5 ^! Z
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */% _+ D6 k* L5 r7 z0 [$ c2 l& I1 [% j

  7. + t1 M- R9 w0 ^# v
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.6 g1 j6 t- k2 O, _# {2 z( ^
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */
    % z  d, V7 {( u. s/ I
  10. 9 }. N4 B5 u! F
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
    ) \5 x5 Q: W  p6 U  t$ L' g* r
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */
    * @; s# G3 L' Q7 j

  13. ) R% s% ]8 f4 M! N
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.
    9 k, c! H) f& ~7 b  Q/ W: g
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */' \" J6 O5 f9 s9 W
  16. / f) d# e. _8 f' k
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.
    . ^+ y( I( {8 b* v" L
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */
    6 T# Y" Y: J# E& R. h2 z/ V* W* o
  19. + C6 r- K) C6 ^/ ]) r$ g
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit1 y4 G+ k2 L/ Q! B+ N$ f$ ^
  21.                                        rate switching.  u6 j$ s9 X' P* S3 j) D
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    6 z' _0 F" j* c
  23. 4 m- h; F- n  [) w' ]
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD
    , H9 v6 m, B5 ?) M
  25.                                        format.
    4 t; q6 q% O: R4 ?5 n: R  ]( R$ Y
  26.                                        This parameter can be a value of @ref FDCAN_format                */
    9 @' b. t6 @0 ^$ ^* c8 f
  27. ' q7 R, N: O2 h+ |' @$ K
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame
    0 J4 S5 L! ~  j3 o( P
  29.                                        reception.' J& i" e. N7 I3 d% _! W
  30.                                        This parameter must be a number between 0 and 0xFFFF              */! M) Z' t/ }$ |8 P! U: I
  31. / r4 c$ K; c: N( Q, @. t
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.
    9 v  b, B7 r5 R; i
  33.                                        This parameter must be a number between:
    1 e" F" ~# z4 Q% f" ]& e
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID
    ) k9 Y( u: ~$ ~5 j' }/ S
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */9 p' h5 @# [& T% `; x, S) {
  36. ( t+ H' ?2 \) a1 G$ a
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    / z# T& \% \3 N
  38.                                          Acceptance of non-matching frames may be enabled via
    2 O; b2 y9 k. j) b
  39.                                          HAL_FDCAN_ConfigGlobalFilter().8 F, J# U  x( B
  40.                                          This parameter can be 0 or 1                                    */! V: f' H( K" D$ q4 }7 j
  41. $ s7 r# T6 @# @: u
  42. } FDCAN_RxHeaderTypeDef;
复制代码

0 d1 q8 ?7 {; y" o' T2 c- J6 `  Identifier
# T, v' \& t/ m3 l; V8 E; F用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。3 X0 l& s+ q- M
. ]$ x5 q& G# F4 `4 _7 ~
  IdType
& Z  }7 }9 p" M+ Y4 f7 H$ n用于设置标志ID或者扩展ID。3 ]9 z6 _" J# D5 R* B; t, M
- j! m2 l& c) `- a, M
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    ! d$ h2 d1 |- Q+ [  A* V7 i& f
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
) X/ B- B2 G* V" i
  RxFrameType
* u: T' ?/ }4 C8 L8 ?用于设置接收帧类型,数据帧或遥控帧
, h$ U' g- t( [4 b
: O* g0 H8 K9 c# e  {
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    0 t! |- }; R. n
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

/ B( l7 t: [! ]  DataLength
* H) `' a. q% L  e# |: c0 v5 Y用于设置数据长度。
4 t; ^- }9 P/ ^& S$ K
6 R& ^% L2 R5 d3 q2 `1 {& }. Q2 @
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */" L( i+ x( b5 P, z0 i$ Y+ y
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    : N5 f- {" O- c9 p
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */; ^, e* [# I) C% [/ W; f
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */! Q% h( O$ n4 ]: B
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */, y. q; a$ x5 ^, i" v
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */3 q, F( @! \* q  X
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */. h6 T( _7 H6 J8 j
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    : @$ B( ^# A/ ?5 A( h9 b
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */: A" O" {$ k8 ^1 y
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    $ ?& A, U& z& L, m* m
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
    $ k4 Z& u1 s9 k' ]/ x& W
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */- k' J: E4 X4 i
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */5 w: C6 \* u3 g
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    0 E9 D" F" T& d. k0 e! r/ \6 O
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */
    $ F0 M. K* k  z
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */* G2 g3 c. j& `7 s' G
  17.   ErrorStateIndicator
复制代码

0 U, J7 Q$ w: V$ z用于设置错误状态指示:7 G$ Z) q3 D, w, c! }

$ m& w9 S4 G; v  b, D
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */  d- t1 @9 ^7 T. d1 i9 C
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
$ h+ C# y/ h( ^( @0 C& w( ^* ]* U7 O
  BitRateSwitch
! a3 [7 o" r  a用于设置接收是否带波特率切换- f% ^/ N7 q, Y& B' R2 m

0 o; i$ Y/ x9 J6 c9 l
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/. |; s2 I" F& B; G
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

* J/ B7 n( ?$ N) c' g  FDFormat! y" d* T3 b% m1 Q
用于设置接收帧是经典格式还是CANFD格式7 I: e* q& q5 ~6 _2 L9 ^$ B* g
4 ?  r1 K; A! e9 S
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
    2 e- U2 n/ T! }! O
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码

# G* b+ n8 \2 M( c9 B# t/ N: g  RxTimestamp/ [( g, ~7 N3 v" \
用于设置帧接收时间戳,范围0到0xFFFF。   " p3 {% G$ M- Z, ^6 k: m7 l
6 ~- J8 u( `& U( t/ c1 F
  FilterIndex" k0 X( k6 W/ p! u( ~/ N4 J
用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。
/ ^5 [& J5 A8 }& _  \- a6 D0 L7 [6 c
  IsFilterMatchingFrame3 I. m; K, b1 b# T# [" x3 t
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。3 K% ]* X4 F. i. r; N

! C1 u6 n% W* @5 N; i0:表示不接受。2 @" m! k, N, @, k

' z% v+ y: l! i$ \' k1:表示接收。/ T. _0 k4 J. \: L3 |& n8 V
4 u) A  ^3 n. Q. o
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef: J7 ^7 X9 F* J8 k9 `1 R5 M9 G
下面是CANFD句柄结构体:. Z( C* r- b2 p+ l: A1 d* C

' K# R! T/ ^6 `; R4 |9 ^- J) u
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    7 x& j3 M" [4 o; [# x% L
  2. typedef struct __FDCAN_HandleTypeDef
    2 y# H; y1 w, A. K: D
  3. #else, F8 a7 ]$ s0 R& T! L
  4. typedef struct
    " h/ [/ B2 [/ k  t
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */* R2 [; ]7 A* B
  6. {
    + I+ ?; g& X. k) T& {
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */5 e0 ~$ c2 G+ X* W

  8.   |! C! i  \" V6 ^" f' k; {
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */
    ' X- B( O  u5 P2 l/ r" @

  10. 8 j% m/ Y; j) u9 u) U/ e
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */
    % b! b# j- P, H: T$ S+ y/ _
  12. 0 P# r: ?  L8 Q, O- _
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */
    ) s. Z  m3 ]% p4 g: o/ ]5 ]8 T
  14. 6 Z) u) T7 i; \/ n  _9 W
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
    % T$ c4 D# Z' f
  16.                                                of latest Tx FIFO/Queue request */& n8 x) w6 z3 [+ d# c) h+ s* U5 L

  17. ! N# A0 \: w2 b4 m. G/ G
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */, T, n1 I: r0 K7 x9 Q- m* c3 U

  19. 0 J2 Q; F; B' s7 M
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */
    2 t" U% Y/ X- v* m7 t) x

  21. $ M: W* ?  A& @) n7 ~
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */
    9 d% e; |( \" P/ @
  23. $ U$ d% ~4 `) z7 A- s- P  ~% x
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    # T* M8 L) }" l, P1 c4 k) w7 k
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */0 t9 z* o  ]$ t6 v2 p  C
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */) ^( r* ?5 g; J- Z7 m
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */
    2 g$ I5 a$ O5 Q: C; h6 p3 D8 |6 ~
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */
    7 U  g3 d& L& {8 f! {% [& I
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */
    ' r& N2 Q8 G1 N9 g
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */. J) ], f( X: R9 L: U0 t9 g
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */
    # j. f5 |. q8 o% @( T4 F
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */0 S9 ~5 _4 Y+ p
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */; w9 e% [/ p0 M+ d" M
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
    0 v3 D% S7 R  }) L9 Y
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */& g2 U1 a9 w6 b! K
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */
    $ a' n  ^& ?3 y* v5 |8 S* ?
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */- Y9 x! }5 G7 S. _
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
    4 X1 x* I, W9 f! U2 k$ _2 X  \
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */
    2 k* z; H- U3 x/ Z
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
    ' ~% V1 b/ D0 j9 W* m+ Y6 ~
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */; _0 V0 e2 O6 G+ a# M$ j8 o

  42. : R: D+ z, q7 g/ Q8 u
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */9 M$ w2 u3 y# w/ J
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
    & V# i) o- S& S) Y5 K5 \) j
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */; i1 \! `/ i% |8 l. {7 z# ~( d1 P# l: w
  46. + c- Z' ?1 v- \  a
  47. } FDCAN_HandleTypeDef;
复制代码

! D( c% X5 ]4 H2 }' a注意事项:. i, x# [/ b; I/ c7 X7 {$ W
3 m* R$ L; ~. l/ X% l9 I
条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
! ~/ i/ g( |2 Z* ^- [* {0 }' V
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码
5 R, {* `% r/ s8 K
! H) \% \; T# D, Q# n, q4 x
函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。
7 `9 T8 O( B) h: j) L. |
) K; a8 s) F* u; H: Q! Y( Q这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
' P( n- ^; P/ f& s" m3 ~/ n' s7 v3 v' r* E
  FDCAN_GlobalTypeDef         *Instance0 c0 s7 G9 Y7 J  R) v
这个参数是寄存器的例化,方便操作寄存器。- L$ G8 b# z; a8 e9 R

. P, D8 ]: M! X. N* K2 ?# I* _7 h  TTCAN_TypeDef               *ttcan. K" b: `$ Y  W
TT CAN时间触发寄存器基地址。
, e: A  t+ d) W- Z1 z& U; p$ v; \9 A8 J" }2 V
  FDCAN_InitTypeDef           Init5 ~4 ?% |& p  r% `
FDCAN相关的初始化参数。% k* D0 v5 X/ e5 D+ _

2 X6 {, W1 Z/ Z9 f( O  FDCAN_MsgRamAddressTypeDef  msgRam
& [7 S2 k# A% N消息RAM地址。% n. c8 p9 k9 j( Y
, `% b% D8 [' J; l$ B; R- e8 w; x
  uint32_t    LatestTxFifoQRequest
5 x: j$ x% f& _4 {4 N" {, E+ cTx buffer索引最后一个Tx FIFO/Queue参数。
& s4 T: C( J2 l+ p$ U' f" E3 _; t( p
  v( Q$ q2 p9 V  __IO HAL_FDCAN_StateTypeDef State         
6 q$ v; n/ L7 C* B7 xHAL_LockTypeDef             Lock          * O7 |# I$ a% B, @% b" d
7 U' H. b0 u4 _/ Z- R- T
__IO uint32_t               ErrorCode
) L; w9 s6 e# F/ ^  b1 Q
  t4 F- y& N# W$ a) p. s% j程序内部使用的状态参数。
8 ^1 q: p) [3 H4 y9 H$ g+ e
( B( }6 @. V1 s" t( V4 M  R  剩下的都是回调函数4 D% H6 I9 D6 r
91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
5 o8 [$ X4 f& R( w1 p此文件涉及到的函数较多,这里把几个常用的函数做个说明:6 _" m4 {0 ~! F: G* R; l6 c# k# o

8 q* ]+ G( s5 X  v! \91.4.1 函数HAL_FDCAN_Init) _' y) `$ ?% r! S1 V2 @
函数原型:
& e) x3 e+ ^5 _: F7 L8 _6 L, q; b% |- U2 H( e6 n8 p
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)% J3 A5 x6 V0 s% @
  2. {& G8 p6 m4 S6 N( s# z
  3.   uint32_t tickstart;
    $ g& G( [# S& E% `
  4.   HAL_StatusTypeDef status;" U# ^5 B0 V* L* G6 D
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
      f  U4 `6 G5 q: I; I

  6. , y3 T" z' f  w8 |/ u
  7.   /* 检测FDCAN句柄是否有效 */
    / w4 i# K/ B7 [/ i
  8.   if (hfdcan == NULL)
    3 `! b, U" R( o2 G! f4 i* b
  9.   {* o; b; E0 p8 ^+ x
  10.     return HAL_ERROR;& Q9 _- ~4 ]) x) y' R$ {7 r
  11.   }+ F. |$ [& n( q8 e2 E

  12. ! g: ~  y) Q' P9 }  g, Q+ u! S
  13.   /* 检查FDCAN例化 */
    6 d0 O5 O8 p7 H9 S9 \8 ~
  14.   if (hfdcan->Instance == FDCAN1)
    : D# F) ]. F& [
  15.   {
    0 {0 b4 E2 r6 W) P" i7 P  }
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
    7 x4 B4 e+ h9 N+ H
  17.   }$ g" }3 W' m0 }9 u

  18. % d# p# D2 @' F* T- |
  19.   /* 检查函数参数 */' n! A' n2 E  ]7 }; V
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));5 m' t+ E3 X  `2 U, z
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
    " ?& n" G# }& I" d! j
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
    - M: C6 v7 `! \  v% c
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
    7 [0 M, t3 L4 w- x& n, N
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));( P% I1 ?1 `6 @
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    2 J8 j4 \! y: [& h; y! S  v! z
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
    + n: K7 ?( c1 i
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));! Y, r* }6 M1 R- ?9 T: t3 Q
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
    $ U- T9 {6 }$ Y" @  Q* M5 r; V1 r
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));6 e0 i& k" Z1 J" C
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    + v  t4 j1 y- _
  31.   {
    & j0 d, h9 b( v2 U4 E
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));, N( S; F. I! K, J# C$ M( y
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
    , E4 T- V1 z' d, M5 ?
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
    ( @3 Z8 Q2 @; j, G/ _, [
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));( E$ S5 \3 B( w4 h
  36.   }
    2 K0 w7 w- ^/ X; _+ j- x
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
    ; [+ T3 Y9 r4 J/ n% b
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));# ]( a3 f7 r6 v
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    * z9 }7 T1 y: a9 r  }
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)+ Y% Y+ r, G' W% @* l: k% k3 N
  41.   {! A4 q! C4 s. A+ |: K, c/ c) ?) G
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
    , u* G/ C/ y2 H+ U' j* O1 a
  43.   }
    ( K* X- J+ v7 J
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));1 \4 Y: C  _& Y7 w2 ^
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)4 V5 _3 L+ s( v$ c8 h
  46.   {, U% i4 M2 P) `  n# y
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));+ k! `" n( Y1 Q/ f: }+ c. ]4 b
  48.   }4 K* [- w6 Y  X# V: u
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));5 X, D# ~# P5 H9 p
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    - x- h: y# B8 l0 B
  51.   {
    ! q, Q% o. g4 P: h
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));4 p9 i$ Y2 U. p2 D- F, k
  53.   }
    1 O0 {2 v: `/ [, r
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));8 v  t9 o1 u1 P
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
    1 n* L# H' j1 f- t' D* V1 [  y
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    4 L' f9 x* Y0 o# p0 ^9 ^
  57.   {! {/ r' z+ R* \% A3 o$ O& N0 I
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
    0 Q& `+ J# t+ }& r( @: F7 ?% o; O+ v: s8 p
  59.   }( H+ L! f- W5 s* v% D1 B7 e2 G$ f
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    ' k2 O% ?3 v2 H  k
  61.   {
    $ Q8 C1 s. ^; T+ N6 g  e
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));' R- i/ @, d9 B5 F' Q3 w9 O( F1 p6 ]
  63.   }
    ' B. K9 w% M' c7 k( v: w4 a: m$ [# c  H

  64. 3 i0 `, A3 T) U3 K, O, X. T
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 19 l5 ^9 F& ?- z  v% q: r4 Q
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)6 O- b& F& R1 Y7 l: T9 [5 J) D# J
  67.   {+ t$ W9 T8 l. o& G( a# S
  68.     /* 解锁*/
    4 [; Z5 t/ C" n9 M8 z
  69.     hfdcan->Lock = HAL_UNLOCKED;: X' ?& l3 ~0 @8 W$ Y$ T

  70. 9 a2 u& J5 ~% M, e$ ]
  71.     /* 复位设置默认回调 */% d% |; Y% S9 I0 h4 A- @
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */2 e% y1 _9 a/ o% ^
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
    4 R9 I( V% ]% {2 [+ s
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    - K7 y  D# E) B; n, Q' H
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
    0 B" g  C; g) w- L6 D
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */3 ~/ _; ?0 b- n+ x, o
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
    7 B& I7 F- G4 F; u5 t
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    : u5 b7 ^' D8 j
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */: E4 y0 q, Q. a7 w8 c5 h: n
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
      G6 d% u  Q7 _0 @: I
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */: W* e* K2 E* b
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */" D: R9 X3 y- ?" i
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */5 t1 M- K+ C2 a! P% @9 j
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */1 Y, s! x  Q5 G. V
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */
    ' D2 @2 ?) }# S- [4 V( W+ E% v
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    " c! p; i; C( A- d: l! E) w. m
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */
    + q0 {( d! s8 J8 c8 B; w1 j$ l2 q
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    ' z' _# d* g/ Z- H

  89. 9 ^" g5 S/ w7 G" t) Q) x/ U
  90.     if (hfdcan->MspInitCallback == NULL)  G6 _9 T* _1 x; v4 Q  ^
  91.     {
    6 i6 g' x4 E  e' K- Q
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */: L* W4 W" o9 W2 a! F( i
  93.     }
    ; J+ {/ R  Y* l9 l& A# J
  94. & K9 j/ s0 A3 D% N" a
  95.     /* 初始化CLOCK和NVIC  */
    ; O4 X' `" o. h4 n+ p" |
  96.     hfdcan->MspInitCallback(hfdcan);
    1 |- s$ s  Z+ h0 g6 S
  97.   }
    / g  F" m* e- u* _
  98. #else
    , {' q3 `% @# F* f; [! Z; l
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    & ]) K  R! m- W& k6 M' B5 x
  100.   {3 F5 E% H' j2 X
  101.     /* 解锁 */
    ! H$ X! w  M, u' E9 V% y
  102.     hfdcan->Lock = HAL_UNLOCKED;  o4 S- D* V1 {% q5 s) f* ?, U
  103. 2 h: H  w& u3 u6 _: h1 {* t
  104.     /* 初始化底层硬件 */( v% {# z+ o# g6 p" |
  105.     HAL_FDCAN_MspInit(hfdcan);
    2 s/ }/ |3 @& c! O' [1 f" l4 B
  106.   }
    ( m; b9 R% R+ O: s
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */9 s% Z/ N) g# ^/ b1 I7 J0 l8 n

  108. & q+ J4 n% p9 f' F
  109.   /* 退出Sleep  */
    $ J# t" n) y- w3 r3 F, V' Q- G
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
    8 M; X9 S2 g3 ~8 i; |5 a1 Z, ^
  111. : {# s! g; m* w* t
  112.   /* 获取时钟 */
    ' n9 }2 m. A/ e0 b/ ^
  113.   tickstart = HAL_GetTick();
    " Y# Y; f2 [  \% b
  114. $ ^" `8 `' N* \3 M7 V& h4 T9 F) r
  115.   /* 等待Sleep模式确认 */* R& @% B( z8 H. O( {+ U
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)+ T# H" w2 N$ E7 ^
  117.   {& A/ K. a5 w  h. ^) X6 v
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    $ G" u/ e( v0 m; ?' b
  119.     {( V/ Y" i/ z8 b6 a- O. o  r: h# K
  120.       /* 更新错误码 */
    , a: _3 {+ q! O  O7 Y4 Y6 E# l$ [7 X
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;: q8 C2 u4 u) e' J6 U
  122. + u2 P/ F$ z  o6 f( N6 G4 a5 p7 T
  123.       /* 改变FDCAN状态 */
    " C$ e0 f* e$ E' M
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;& e# I" Z3 s, {7 H( W" T) j! Y) t

  125. 2 o6 t: y, q; [7 f5 c4 v
  126.       return HAL_ERROR;
    5 {2 d! E! b# [% Q1 _' H$ g
  127.     }* Z# S) C, b" |3 ~
  128.   }# S- d2 [' F# ~3 M8 \
  129. - N6 I' d/ H% e6 n
  130.   /* 请求初始化 */; z6 ~4 Z) ^  p7 Y6 j6 E: X
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    : o) x, }- m- V  J) {8 t

  132. 1 k( w+ }0 M) C; E+ e- K
  133.   /* 获取时钟 */
    8 M- q; f9 E* v% ~
  134.   tickstart = HAL_GetTick();3 Y" e; `# c% a2 E+ C
  135. ! D% E% P1 }  |' k
  136.   /* 等待CCCR寄存器的INIT位 */
    # m. i0 T" Y+ B7 A
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)/ i! @4 G$ z/ n* Y# z7 O3 X
  138.   {- o0 p( O7 f, q2 p: y
  139.     /* 检查溢出时间 */
    4 j+ @) z5 d7 |& }+ ^) I0 l
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    / f7 B1 B2 B  y: t1 o
  141.     {& R7 J0 L/ d9 j) |
  142.       /* 更新错误码 */2 d& U7 p3 q* R+ ?: e+ b3 o/ i* O
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    # J0 v3 j% v. H1 o
  144. / \5 p$ _: v) _/ z
  145.       /* 设置FDCAN状态 */
    9 B% E2 s2 }7 u: _+ o% N0 y
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;/ M3 A! R' s( r
  147. ! G7 K* p; f: ]/ d- `
  148.       return HAL_ERROR;1 `7 L  z. q7 d6 e; P
  149.     }
    4 I$ p, m- d6 I3 Z
  150.   }0 M% m, t# k: F' ]8 P0 _: S

  151.   E* s( s/ i! t3 x
  152.   /* 使能配置修改 */
    $ l/ |7 N, X& _- V# o, i$ Z
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
    6 \  h, B4 S" Q' ?+ Z0 E

  154. ' a( N- W1 U  y) V) x6 R
  155.   /* 设置是否自动重传 */( I3 A4 u4 \" n/ h6 g- Y
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    6 `( `1 ]* Z  R  t- m
  157.   {
    . g& ?2 w$ D3 q, W! T
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    6 i9 v; N% B1 A- a. P
  159.   }
    & t' R$ g' D, Z1 g
  160.   else
    # `9 k5 W- V) H' e8 w
  161.   {, @# u) [2 X, b& a- U/ S, G
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);) S$ ~" ?) z* \$ [$ _9 Y
  163.   }
    - {3 ]$ z+ m; U/ S- C4 Y$ q, o

  164. - A* }& G* U$ A, R( ?, u) [
  165.   /* 设置传输暂停特性 */7 T, m+ P: t$ L9 c1 B7 J6 B
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    & o4 Z) E( D  o# n# i( t
  167.   {
    * r2 A0 u6 F; W& |0 I5 M) E  E4 b
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    & n8 B9 {  O/ ]/ V
  169.   }
    : |  X5 J( @* ~5 ~* _, j
  170.   else) ?' D* Q) e8 i+ L
  171.   {
    " }+ u% ^% @' H+ o# T
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);4 ]2 U+ g* y: G9 ?! `0 x
  173.   }
    * H5 A2 s5 Y, S

  174. ; d, o' e2 Z3 e: E
  175.   /* 设置协议异常处理 */* l5 P. [$ f% m1 k* p
  176.   if (hfdcan->Init.ProtocolException == ENABLE)7 X$ y. B" W+ n1 o3 j
  177.   {
    ! U8 M( z& _7 ?" T2 k, ?4 I& E
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    1 N' v3 o( j; K& @1 Q  W
  179.   }
    , H3 ?; d4 q1 j
  180.   else. L5 f+ w- G, g- F$ g5 \3 P
  181.   {. E; @5 C( D! [3 J
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);& @/ z  @! ^/ y& e) F
  183.   }7 p& r" `- f4 {

  184. , [5 q1 c* c$ O9 e6 t
  185.   /* 设置FDCAN帧格式 */; z, y) k. d5 o6 N+ c2 a" p
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    8 u7 y" k3 z& _1 f  M, i- A/ j

  187. ; c+ @0 f, Z: h: b1 {$ w- J' j" ^* Q
  188.   /* 复位FDCAN操作模式 */
    8 R' ~8 x1 n5 d( |% o9 L5 k# d
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));" i! f) E% `( z' C, N
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);- T) w" p7 t/ v" C! k" x& T
  191. 2 D9 y( b. R. [4 y0 G7 |+ c
  192.   /* 设置FDCAN操作模式:1 @) }" \* U' a/ N3 d
  193.                | Normal | Restricted |    Bus     | Internal | External" M  M+ r: f5 T4 V6 u
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack
    , Z9 Q2 B; F5 i4 D: A
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    1
    1 w' T% k2 j0 a6 t
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    0" f. A) y2 n# p# ~2 m
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    1
    3 q' t' G" d/ a8 U' f2 W
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0
    - \7 F( P3 W) e
  199.   */- k* g7 s- F. F- z. O* W: ~
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)/ G$ Y4 ?7 i6 H# J
  201.   {1 J  X/ P+ j5 U2 [4 B" {
  202.     /* 使能限制操作模式 */
    5 e4 }$ {$ x# g' V0 O
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
    8 H, Y  C' V! j, |! h4 h" w
  204.   }. s8 `. v: z- l3 d1 H2 U3 F
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
    9 b. u0 W" d( U1 F  B6 S
  206.   {' y  ?; u4 u3 _/ V% T/ d5 H3 L
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    5 z$ P4 n& [- H7 g
  208.     {3 R/ H7 c, r7 ~5 K/ y7 f! R- n% H
  209.       /* TEST寄存器写访问使能 */
    8 \% g* z' x2 L+ L; @
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
    + }. x3 J1 ]+ T: Y5 s' ^5 i

  211. * w, R( ?# Q; ^: L7 c) ^+ U
  212.       /* 使能回环模式 */
    4 p/ V8 N4 O2 X) |/ Y  y
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);5 c8 r# K/ i3 u5 C" @% L5 s

  214. 5 n  @2 P( G2 u: H
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
    + K0 y* ~9 ?. M. i7 j
  216.       {
    5 [" R9 `7 t; I* ?
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);( _3 d/ [% s+ ?" ]; Z9 F
  218.       }
    3 B9 I2 [: T6 g+ o* i. F" S
  219.     }
    : Q; E1 F0 }; }
  220.     else9 ^+ l. u% _$ Q/ a# o9 O
  221.     {
    ) Y5 W& q. |4 i' h9 e+ s
  222.       /* 使能检测模式 *// ?" t) v8 ?3 V% o3 U
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
    * y& A# @$ d+ r# \  @
  224.     }, x. Q- X' p. `: A7 t* A
  225.   }
    & ^5 @9 g* O6 ]8 Z) X
  226.   else; u6 S+ t* O" ~
  227.   {
    9 B; {" y. c+ F% F% [
  228.     /* Nothing to do: normal mode */
    # \+ k" l* O4 B2 N. _6 q6 G# \
  229.   }( g5 e- p" T. y6 l2 Q

  230. 9 i+ w, z. N: M. R: _' J
  231.   /* 设置nominal bit timing 寄存器 */
    ( I7 @6 P3 e4 B# e
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
    0 @& h4 I# n% f# W  g- }
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
    8 H5 X# [/ I& _6 S- `( y! W
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
    0 I, a" L8 i6 b! Q8 |- ~7 w9 e
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));. ^) h. A5 q' g# y: ]

  236. 5 n' w- c7 \) S0 R: y) B
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/
    ) X& O  @9 _. B5 l0 H
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    ! V6 V- c5 F! ]4 ]# n+ E( B
  239.   {) u6 u1 f& T8 T6 I% ~4 s) i+ J
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
    5 S3 c( E! K$ D5 ?9 P
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
    1 ]; ?, s' ?9 T- }6 z7 _/ a8 Z4 p
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \; W- |% P( L' k  i5 x+ A9 \" E
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));! L( y) R3 F+ G
  244.   }$ g5 K6 @1 y: u% j5 L) a. n* L
  245. . L: @9 @+ F  k: s0 M
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)0 X3 P9 _9 y# c& `
  247.   {
    & S5 R5 ~6 }9 U) d+ l
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
    4 I9 q$ k1 ]' h  h! s2 V( N0 {
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
    3 x( |, P, {$ f8 c1 S* {
  250.   }( ]- p- \$ ~4 d: J* V' Y8 X
  251. 6 q: l6 f; _. c. S5 b  H$ p
  252.   /* 配置Tx element 大小 */
    " x1 c6 h2 P5 i) \( x9 [
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)% z' G9 ~4 B. a7 W. l
  254.   {3 J5 J# F- ~1 S
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);* E  M: ^. g4 i( ~/ E! Q4 O; v
  256.   }
    . z  w6 x7 \. k
  257. 3 c! X" ^2 {. X' }3 c3 j0 {# H+ G$ H
  258.   /* 配置Rx FIFO 0 大小 */
    & \% {. E8 {/ }
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U). t, U* [2 \" ]' Q! u
  260.   {
      s: q4 T$ F! U" j! B. t
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));5 C; U. l0 N6 V( E
  262.   }8 m+ b& h7 w+ J

  263. ! Q1 G, n8 o1 G3 d% n2 d
  264.   /* 配置Rx FIFO 1大小 */
    . h* e& x2 a" N
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
    ) \: y1 Z" s* W( P6 U6 c5 ]1 f
  266.   {, ?; d2 U/ B- c* ?& Q* f4 T; [
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));
    5 ^3 ^$ b+ U2 W& c3 P; r. E
  268.   }
    + a& C% O: B! t' R! u! s  ]( Z, `
  269. / H: t0 Q: [5 j( k9 e) n
  270.   /* 配置 Rx buffer element 大小 */
    ' N8 i0 |' I' J: Y' C/ q, G
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)
    5 o0 R, U" M* S- |" s
  272.   {
    ! q) L  J+ J) O1 U0 J
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));/ a. X; E. z% L& h
  274.   }
    % R# J7 C, P5 R7 w* V
  275. 6 R7 \  b0 l; D
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
    . W! w5 o* Z2 u; t2 U% ?
  277. 后调用HAL_FDCAN_TT_ConfigOperation */
    . D9 ^" f0 h/ q# G( H" g
  278.   if (hfdcan->Instance == FDCAN1)" C! d: n( |+ ^; H5 R
  279.   {
    7 ~( ?! h( e7 N6 x# n9 ^
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);3 o& M+ `2 c  c9 q3 }) V
  281.   }
    4 S8 D( l: d. f+ }

  282. ' B1 t$ L! k$ a, F
  283.   /* 初始化Tx FIFO/Queue */1 y7 ?; |4 M+ T- a7 u* @
  284.   hfdcan->LatestTxFifoQRequest = 0U;5 s/ ~/ i( L+ J. o0 b" j$ g
  285. ( X. T; O: V" V
  286.   /* 初始化错误码 */
    $ B; |& H  E, P2 j) B. H
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    0 \, n0 x1 y: K. z. x6 Q6 K

  288. 5 Z, b# u( I" R" d: [0 n
  289.   /* 初始化FDCAN状态 */
    + x' E, @7 Q; a8 t8 y) \
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;
    - R( ~  g+ J2 t& e, e3 q0 k, z8 A

  291. ! U3 H. v0 P, ?1 K1 x& _, s
  292.   /* 计算每个RAM块地址 */
    , D0 ?9 G2 [- y
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
    , I3 F) Q( f8 V" |4 f# \$ g
  294. % R2 F. T2 p+ k7 Y
  295.   /* 返回函数状态 */! m: F7 ?3 A( K+ s$ V( ~
  296.   return status;- a. Y% J& j) [, p& D
  297. }
复制代码

( u8 \3 g. e/ V5 ?函数描述:
9 t/ O  w, [6 ?) S' S- K" ?* J8 j) S* x8 u
此函数用于初始化FDCAN。5 `! q1 y5 N" C. ]& Q& ^6 j
2 r2 @4 n, m# o; V- Q* E
函数参数:% h5 b# p( g" J5 y0 v5 I& i
% V+ X9 M  T! h* n' m. _  F
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。3 J* D1 H5 Q7 n( d( [
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
# U% Y% b4 V$ O0 X+ D注意事项:
' G$ W/ P4 y4 u  g; \9 y2 T) k# i- V/ ]
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
3 `. S7 R: f, Y4 c如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
, B5 U( F# Z% _  L: _3 I对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。' t5 u7 d5 I- I1 _. U, s. ^" {8 ~4 R

% F2 p8 c: ^. U6 y解决办法有三' [) v( B( C) G; F* W: C' {. X; a$ A
# a( A8 z2 u5 }# O4 \
方法1:用户自己初始化FDCAN和涉及到的GPIO等。
9 `* _- q! E! F- M/ X; d  c( `& Q0 V. P2 I* R! q, }
方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。$ e- i( h- k  H+ j

! s$ L: F3 Z# P9 V- z. b方法3:下面的方法) }/ U$ C- t# a. i' O

1 c! k, N- X; X2 C! f/ _# L/ |
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)
    % T# F: }2 r2 |* J
  2. {0 A7 D2 m- R+ ]2 N
  3.     Error_Handler();$ u, R0 _& }+ m
  4. }  ' z- Y4 U8 t1 J  H( {
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)
    & h' h5 r8 @: E
  6. {0 h: Q& m& W4 h$ D; n9 j/ H( e
  7.     Error_Handler();
    " Z- A/ c0 C- N; S9 s
  8. }
复制代码
+ S; l! Q( e, B. l3 F3 b
使用举例:
7 M2 z4 I0 o7 u3 J% X
: w' [) d2 x2 e
  1. FDCAN_HandleTypeDef hfdcan1;
    ( ^# T0 m: ^5 G5 l4 g: b

  2. 5 o; X4 N* I. h% N. _! ?
  3. /*5 S: D# |, z3 d0 K
  4. *********************************************************************************************************' K4 N2 b7 u; X, B4 n7 B7 g% P
  5. *        函 数 名: bsp_InitCan12 @' r; F5 H: ]- f" c3 @8 A3 C/ N7 C5 `8 [
  6. *        功能说明: 初始CAN1/ I8 R4 u* J+ v7 ]2 K
  7. *        形    参: 无  d4 ~! i4 q) K
  8. *        返 回 值: 无% A, K' ^" p' w7 r0 D
  9. *********************************************************************************************************8 s# ]- Z% T$ Y' u; U1 `! u: ~/ J* h2 u
  10. */  A- y  z% K# v
  11. void bsp_InitCan1(void)
    : w3 s$ j3 {% `6 N' x
  12. {         
    . e% f5 x6 g# z. X
  13.         /*                    位时间特性配置
    ' n3 \9 F. K- Z) G6 f
  14.                 Bit time parameter         | Nominal      |  Data
    9 H1 O2 @+ g' U& t& s" E
  15.                 ---------------------------|--------------|----------------1 b# S* c+ n+ N4 d
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz( I6 }' I& L$ p
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns% T0 o& h3 D* T6 e7 a! F+ G" g
  18.                 Synchronization_segment    | 1 tq         | 1 tq7 z7 ~, e! D. v  ^
  19.                 Propagation_segment        | 23 tq        | 1 tq/ f9 ~3 B7 c! z, @6 w, c7 y. p
  20.                 Phase_segment_1            | 8 tq         | 4 tq. M0 l  Y% c% N: ~4 L0 T* ]
  21.                 Phase_segment_2            | 8 tq         | 4 tq& ~6 V4 H1 V" ^( j# ^2 w2 Q8 x+ K
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq$ e5 [* I1 \4 N$ j- Q
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us& Y6 J+ k1 j, @2 n+ |
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s' ?- A' r7 i' E* y, M
  25.         */" }; K& t, Q7 A% h1 D  K1 R
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */             # H$ A. p, {6 p- X) I( U+ ^/ f
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  - Y+ p3 H7 [8 D( j# T: ]2 J
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */ ; f/ R' y0 Y. M+ Y  }; |' B8 n6 T. X
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */ ) l0 ~2 I4 k- U1 l
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */
    8 |* x, o+ v, V$ L4 P5 W
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */- ]- ]8 J1 n0 |; ?$ T. K6 c2 U7 P9 \7 f
  32.         : `9 }; M/ v; ~$ S
  33.         /* + f; _1 J/ u: z) @
  34.                 配置仲裁阶段波特率 & T! q1 Q( h2 \  o" r8 C+ F- X
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是. h- I$ ?0 h( v& }& o$ I4 ?
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps          q9 W, \/ i7 w: D) C- o
  37.                
    ' a, i3 W/ {* q7 j- q* F2 c4 D( d
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2* E: Z, O% l3 y& Y9 J0 y! p5 ~/ [1 ^
  39.         */6 M; G* e9 B6 Q" T9 B
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    2 b) x9 C  d% @- S/ E
  41.         hfdcan1.Init.NominalPrescaler = 0x01;
    / J3 s- \% h5 V0 J

  42. - u: n% W$ M  o
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */* {/ i4 t2 c5 P9 J9 n: U
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08;
    $ {9 K6 {- J& p, C; Q
  45. % h9 _0 d2 h% L* t2 k0 G! X, F
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */" _* J4 |8 u' ~3 R! l7 ^. y( \5 r
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;          . W: {4 O' ^, K( f: G9 a/ f: r8 }2 L
  48. # I5 |0 O, A) A) e! `1 V
  49. /* 对应位时间特性图的 Phase_Seg2 */
    ! j; S( O1 v- e4 D) ^
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     
    : T/ d- F9 d5 f0 y) A- F
  51. $ P5 U( Z  o/ i4 ~8 Z& Y0 C9 Y. F

  52. ' L* d5 x7 ?! h+ @% Z6 i: W$ T
  53.         /*
    - W1 O- M5 U; e; Z
  54.                 配置数据阶段波特率 ) J  u; c7 t$ B4 ]. `$ j
  55.                 CAN时钟20MHz时,数据阶段的波特率就是
    - D/ x$ v8 f. T, ?9 `* ?
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
    * Z% p- y' U# D7 I1 ]6 ^
  57.                 & t) G! b2 W8 f5 V. a3 [% e
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2% L0 A; n5 B* P& h6 [) K" h( V
  59.         */
    6 I( p3 b8 x' p+ L3 P5 d1 u
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),+ ?. u# j4 L. n7 T6 v- S) ^# R/ X+ i
  61. 范围1-32 *// q8 D7 Z% A, Y7 A6 l$ q% b
  62.         hfdcan1.Init.DataPrescaler = 0x01;
    0 @$ q: K5 Z' t8 e5 p) Q: z

  63. $ w5 k) t) C# h: s, D5 W
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
    ! n# z7 C/ u' v% p- G
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  
    6 l( x5 a- ^+ h5 [+ I( ?8 r5 T9 R& D

  66. & h( g$ C/ @- q" u
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
    : _/ h6 f  n' }8 e7 Q7 R
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05;
    * E+ g% E9 u% o$ q+ p
  69. # C/ {- M5 e" N% s% d7 }8 v
  70. /* 对应位时间特性图的 Phase_Seg2 */                & \/ f: J% \5 J6 U, v7 }1 z
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           
    % R! q! O0 B6 q2 P5 o
  72.         . N/ j: g4 r9 i; w! H
  73.         
    0 s% D5 _8 o; `! h" E+ t( F
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */: E' M. C6 h1 d5 m
  75.         
    $ r1 h3 p, C# E) [- Z$ o
  76.         * @# {: A1 f& f6 u2 V7 Z
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */       5 _7 {* H5 ~1 f
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   
    $ Q! w' ^& k/ u" D' X" }
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  
    5 a, L; z: Q: T8 H8 V, M3 N9 s
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
    ; e0 H9 A4 v' y# p) Y( x: r9 G2 @
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
    * {7 d4 ^4 _" L! d$ r* F: a
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */" X& g# J: L) \, m

  83. ( a/ O6 w* W, w- @
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        
    4 _% _: s, Q0 \) S) [' d9 I
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; 1 N% `. U, s8 D8 `/ }
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */0 B$ C% q# b1 X5 R
  87.         
    ' v) D& o/ |$ l  h8 f
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */) D- [8 j  ?# t
  89. hfdcan1.Init.RxBufferSize = 0;                             
    " F1 @( X, u4 A+ ?/ b. o
  90. : c7 L( G. x! {+ W! z, d% y
  91. " S( c; [! a2 j, h
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        $ D. h* d" T. V
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
    / O3 k& o! O: o2 r
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */
    , d: G2 A9 e- Q$ c
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    / K" s$ G, J2 J9 h7 X# {% r9 C

  96. , b% L8 U; I8 r' o( ]
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */; A" L* [. W2 q- r( }3 Z; Q
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;         
    + m7 x4 `$ j3 Y; [% {4 |0 q1 \
  99.         HAL_FDCAN_Init(&hfdcan1);
    $ G4 s9 e; r* R6 F6 T. _' Z: ^# i

  100. - f# P6 [. B% H  O+ l

  101. : K( L( O5 N+ @5 B% K  |
  102.         //省略未写
    & \, V/ G, Y3 v) |9 @- R( W3 Z
  103. " H3 e  B$ k, d& N
  104. }
复制代码

+ e; v3 H& A& d* \. z; Q91.4.2 函数HAL_FDCAN_DeInit
! l! c! E0 s# J. z5 l! l% }函数原型:4 {0 O/ l+ E1 l7 i, {5 n7 B: b+ A

0 E/ A; A, R! O& K' F$ n7 K! i
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)$ K& z; `' N/ f5 _2 ~
  2. {
    / f4 m3 Y6 g) w& O2 S
  3.   /* 检测句柄 */
    " q& D  Y/ y! C. j$ N, Q/ y- K5 G& p
  4.   if (hfdcan == NULL). D5 O. w8 }7 w. F7 c; `( h$ [
  5.   {
    6 _0 W. }5 M! B) I% u
  6.     return HAL_ERROR;
    % o2 l9 @! }! V9 u6 R
  7.   }# P- O, a: M% X) }

  8. & j5 d4 d9 T7 p, d1 i2 }$ a
  9.   /* 检查函数形参 */6 n+ E5 Y. m- l! B9 K- d- c
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));# A0 K. ~) e" {# f# V( j. I
  11. 9 H/ a/ X% q, v6 O5 U7 A
  12.   /* 停止FDCAN */
      D, u1 s8 x! q! T& V& F
  13.   (void)HAL_FDCAN_Stop(hfdcan);
    5 v. o0 L1 u5 Y5 ?8 ]

  14. - ^% V0 }$ u1 b5 _3 p0 g
  15.   /* 禁止中断 */
    " Q5 q7 k7 L, d7 }' H- }6 F. P
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    + ^! Q, P6 q5 g2 T

  17. & m" a- C: b% B9 B- R; i: ]; q
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    ) F4 e* A0 V; E, i
  19.   if (hfdcan->MspDeInitCallback == NULL)
    ' x3 G/ I9 u+ Y# j. [
  20.   {# z% E4 F' e- U+ ]/ E& V! H
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
    9 K! A. g. L+ G4 `1 Z: |2 D- G5 L
  22.   }1 R1 p' l- h! ?2 z9 H- D

  23. 6 C7 y, R5 l8 W: y4 c% s3 Z* {3 P
  24.   /* 复位底层硬件,如时钟,NVIC等 */
    - r2 }$ u0 w8 b# J9 T
  25.   hfdcan->MspDeInitCallback(hfdcan);
    % f, g; c, k. W+ k. W2 |
  26. #else8 W# Y1 O) M+ ^7 _
  27. /* 复位底层硬件,如时钟,NVIC等 */
    ) y, I6 s7 c# \. Q! o# N- f- X
  28.   HAL_FDCAN_MspDeInit(hfdcan);4 b# \+ C) y. \& V2 z
  29. #endif
    % A0 _, J& J* e. a

  30. 1 t! x$ `$ c- X0 q# T
  31.   /* 复位错误码 */
    7 S- y3 P. x+ W: B$ [
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    - \! h  G! q+ P
  33. $ Z( X" u: W. v2 |) N/ b
  34.   /* 设置FDCAN状态 */" ?# C  @# R: ^# \3 \7 s
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;
    7 U( }5 _  f/ c6 t( j7 x5 ]; u4 o

  36. # u4 q  X- u2 B) `' Q
  37.   /* 返回HAL_OK */8 Y; \8 \: s/ k! H
  38.   return HAL_OK;, _# a5 s: U- `. f, v: m* i. K( w
  39. }
复制代码

3 N- c" O! X" o0 j4 k' l# z函数描述:+ {* l( Y% E# X' E+ V3 H2 m) ]: g

: Y5 Z( E# e0 v% L* [用于复位FDCAN。
# l* b; o& l2 W
( s7 Q1 P/ x! u" E" ]函数参数:  s9 s' H& q* }( `; c8 L1 q
) v+ d& n( A( t9 d. k
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。# p1 q/ B% K- E8 f
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
2 P  Q# o( u9 d3 T' E, L91.4.3 函数HAL_FDCAN_ConfigFilter) o, r; [! A1 j- r  s/ W- h! l: k1 M
函数原型:
  A9 Z2 O9 c6 d( b5 x
, e6 E0 x* v6 j8 O4 u
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
    $ j6 l  ]7 a8 k! z7 P2 V7 j& _
  2. {' W% X# _6 k" s/ d7 a3 p
  3.   uint32_t FilterElementW1;
    . s8 G8 O1 }3 u( D+ @2 v( M
  4.   uint32_t FilterElementW2;0 ]; ?# U1 u( f4 x; ~' D2 ]
  5.   uint32_t *FilterAddress;
    6 g1 k9 l$ U  O$ `  v, d& A# V
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    ! q# |8 R0 N9 B6 U+ }) h/ k

  7. 4 _8 k/ b8 j( e% R2 u& U9 F
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY)). c: E2 v& |7 I% N; `5 b2 \/ P: J
  9.   {
    $ _! F* O: X' ]& W- S2 Q
  10.     /* 检测函数参数 */
    - T% t+ V& J" }$ A1 C
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));8 S/ D/ n% r) E0 a
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));( N  v: C- b( R9 N6 v# X4 a
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    6 ^' I0 l8 o3 i, V% ]
  14.     {
    ; ~7 J* K* K5 v4 z. N/ q
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
    ; x* m& x- l$ |# j" U( b1 G" T1 r
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
    9 o5 l( W7 D' m* s* n! q$ y
  17.     }8 C; E$ L, H2 |  @" @, j7 t7 H
  18. ; J; T6 I: L6 _  v4 W, l
  19.     /* 标准ID */
    / [+ t( k4 F9 m$ ^
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)  `* u6 y+ }( t9 s
  21.     {
    7 c9 N6 U# t( G( U
  22.       /* 检测函数形参 */2 C' |. ^5 T/ x% t" z  O
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
    ; R1 g' E6 o4 ?' s9 i) T8 T  N
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
    8 c4 S& c- d8 y7 v# e2 I4 f! L8 F0 D
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)! q- U& _/ @) B: p' U6 D' S# `, ~
  26.       {
    - R, l+ |; P0 g
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
    ! q! c8 {. }7 l1 e# p4 s
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
    / }) }. F/ `' }# d8 c* i
  29.       }8 u  s! J* |+ m/ b
  30. / T4 w7 E# C$ h2 y( `$ J
  31.       /* 构建过滤元素 */6 h/ h: g! c! X
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)7 ~# q9 P( P7 d( I, A# i  I
  33.       {
    9 c# W4 P, \* E9 e
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
    4 N! ^& J  L1 g! c! E
  35.                            (sFilterConfig->FilterID1 << 16U)       |, r( O# F# s/ i; s% G' ~
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |
    % u- }8 a5 I+ K! \; X. [# t
  37.                            sFilterConfig->RxBufferIndex);
    " c( {3 l! A; K0 d% I5 Y: [# l
  38.       }/ n' l/ D0 f: G) c; N: I3 _' Z
  39.       else
    ; c5 ~* L5 k* D( H) j! o' D
  40.       {$ r: [* u& S2 X3 D( j$ c
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |* I& e' X" z1 T7 O1 \
  42.                            (sFilterConfig->FilterConfig << 27U) |
    & x" Y9 w! D7 d
  43.                            (sFilterConfig->FilterID1 << 16U)    |& a( x0 }1 S7 c. M! E" J5 Q4 D
  44.                            sFilterConfig->FilterID2);
    & L3 G9 T% ~% J( R
  45.       }: y+ \! Y& L8 G

  46. 5 `) s" ]" R5 G; Q
  47.       /* 计算过滤地址 */
    ) Z. S- f! z3 o$ E, l
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));+ G4 j" L5 x+ D* G- C8 E* u

  49. / Q8 u! ]8 f/ ~( e
  50.       /* 将过滤元素写到消息RAM中 */
    # V: u  j8 v; o# @% t
  51.       *FilterAddress = FilterElementW1;
    0 X+ g5 w7 d! a4 {$ K" s
  52. }9 \0 P; b; [; d
  53. /* 扩展ID */, v, V5 S  L7 q. X& d& Y
  54.     else
    . \: y3 q2 i8 e; `) C9 m
  55.     {
    + e: l+ c- p+ @' Y( ]$ S# o3 F9 @
  56.       /* 检测函数参数 */
    * O/ K7 H3 r2 {9 J
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));0 `% C9 B7 Q4 V8 e) O, ]
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));; V. s7 i: o( s8 a$ Y
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)! a# X- z; B2 N$ L* q* m  ^
  60.       {) e7 e2 {6 L5 j# j/ G
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
    ! N1 n2 q6 H. l/ D" X, \, Q
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));- q7 R  a& K, [3 H& R  V) Z- F
  63.       }/ ~4 G0 Q) S  E" \

  64. $ d& p) Q: Q1 ?* |' P, T) X
  65.       /* 构建第1个word的过滤元素 */7 r! b5 }7 C% b9 U3 `# M
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);. u; W6 u  {$ }- b
  67. / m2 b( T+ y: U) }
  68.       /* 构建第2个word的过滤元素 */
    ' e% }; ]& ]/ G' Q& a5 U
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    ) Q% g! ?0 \! N) b
  70.       {0 `6 s, z! }8 m8 g6 G% l
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;; i8 E( \9 G* E4 ?& q7 t9 \
  72.       }
    ! D/ J+ m! g3 U& Z) h6 m
  73.       else: s6 c# C# Z. O/ y5 k
  74.       {! y3 k  Y) o; n" O- [# V( e! h1 R! b
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
    ; a3 g, g/ V8 j2 f
  76.       }
    ' M1 E3 \4 T: U$ c4 [

  77. ) J# [& d$ ?" H
  78.       /* 计算过滤地址 */
    ) p7 W) |. P5 j1 j
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));( M  t% O. G4 G! }4 |8 M
  80. 1 f" `5 J: l+ H1 b! a# Z, r5 N  S( q; l
  81.       /* 写过滤元素到消息RAM */
    7 c6 K+ D5 u/ e( t7 K% _% Q
  82.       *FilterAddress = FilterElementW1;
    8 e) S1 A& n  h
  83.       FilterAddress++;+ D& l1 p# W9 x6 I) o
  84.       *FilterAddress = FilterElementW2;4 j' }/ v* H- p# `
  85.     }( g/ ]1 ~+ v; G7 D7 v2 d5 W
  86. ( |! [. v1 c' C5 i
  87.     return HAL_OK;
    4 B2 K9 Z  W( q+ J: v8 Q
  88.   }
    % c% E& u3 {+ }" x8 J0 @
  89.   else( Y% f6 R2 m: d  \
  90.   {
    / L6 @0 w0 ~7 T# H
  91.     /* 更新错误码e */
    0 z; d* K' n7 [: W( G. r1 [) E
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;! B; @5 S: U( L* _2 {0 s

  93. 5 H, _* [" M! u& D# j7 Z* _  H
  94.     return HAL_ERROR;3 N  `9 K4 M* n' n& X6 b+ i, ^1 J
  95.   }
    0 ~9 d; ?2 Z/ g
  96. }
复制代码
% g0 A) b7 W! m& d% G2 s
函数描述:
  E" ?- T/ S8 s. B. V. M& f: B, Y. S( Z; m
此函数主要用于设置FDCAN过滤。
4 g$ s4 W. U" V* S0 f" X* R. M/ U* n' \9 L
函数参数:
7 ~/ M. \' J1 X6 z* ^6 p2 h
0 F* R, E: M# y. q& X8 i2 r, }" s  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。/ U& g( V' I, C
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。3 k$ |; Z3 O$ M& u- @- w. |( p2 I8 L
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。8 u3 P9 g, v* [0 j6 A
使用举例:
1 ~) h( l' e: i
6 b% z8 l/ ?3 B# o! ^: Q
  1. FDCAN_HandleTypeDef hfdcan1;
    ; S8 m8 N0 U* [7 ?! i- r: l
  2. 3 q# G2 P2 @3 o* w) g, o. e  u; [
  3. /*5 _. n4 \8 x: T* D
  4. *********************************************************************************************************
    + H+ r. o) _( j5 p
  5. *        函 数 名: bsp_InitCan1
    + W9 n% X/ I$ U, Z' h
  6. *        功能说明: 初始CAN1# N1 `  o( H# z
  7. *        形    参: 无
    9 Q+ I5 A  H8 q$ Z7 I
  8. *        返 回 值: 无
    * z; e6 M5 t- H( i( W4 X
  9. *********************************************************************************************************3 t+ G( }. b! _0 q: R0 t- T5 K  e3 ^
  10. */; q4 ]% B1 r7 m
  11. void bsp_InitCan1(void)8 T  @- S! C; r  z/ |: [  }1 V
  12. {         
    : O; f3 x1 `. W2 b. \+ Q
  13.         7 I5 }! T6 u/ l0 r$ t$ u# @' E
  14.         /* 4 S, C6 R1 a: T7 A
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。: Z" {. v1 K- H  W4 O3 q
  16.                 FilterID1 = filter1 n- x# b& x! z0 t  T* f
  17.                 FilterID2 = mask
    # S3 B& Q  [: N( i" h* ^' X
  18.                
    " M9 q6 T  y5 T1 t7 x4 D' N3 G
  19.                 FilterID2的mask每个bit含义
    " N  f$ s) h/ m8 D0 A
  20.                 0: 不关心,该位不用于比较;
    ; ^4 o& V6 |  e% M# S2 {, R) j. b: _
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。
    3 }# q; q3 X9 M% B- l) {! Y3 s! p
  22.                 " k- O  Y! r5 s5 J1 ]- |- Z5 j: }. H
  23.                 举例说明:2 ~. _3 y9 z& A+ Z1 J& ]7 M& F
  24.                 FilterID1 = 0x111
    4 {; _% J- E% O; R
  25.                 FilterID2 = 0x7FF ! M8 a6 H& R+ h/ K. e8 c9 V" x4 w9 ]
  26.                 表示仅接收ID为0x111的FDCAN帧。
    4 I2 G( }2 ^0 a6 [5 _+ u- O; E
  27.                 ) W& D/ p9 Z3 Q
  28.         */" {: {/ d, M" Y5 e
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */: {5 S6 r5 m. V) h
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */1 |8 U) Z8 U! W: r0 [
  31. sFilterConfig1.FilterIndex = 0;                                                   
    8 |+ m* I! s! r9 S9 Q6 q: c) {: J6 M- l
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 *// m- W) G1 I# D" H
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 *// H7 d& x: }  r  u% [
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */+ R& a7 {/ A1 }1 ]( A  C- ]$ d5 ^
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
    1 L& H4 z: U# ^1 b
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    ( {* Z% c  u/ S5 F$ K3 Z
  37. ; H# ?$ ~) a8 k* i
  38. }
复制代码
9 m9 @2 @- }6 _: ^3 L! B6 L! ?) P
91.4.4 函数HAL_FDCAN_ConfigFifoWatermark
) H2 E; A. N8 S! f1 q函数原型:
% b- Y' S0 o+ N% Q& t1 a  h% g8 P4 _
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
    " ^% y: E8 i* R% n, q
  2. {
    " Q" ^4 L8 U! o; G
  3.   /* 检测参数 */
    ) n" P( M2 Y4 S
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
    & I7 d( ^# N3 Z$ l  C
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)$ C9 p0 B* ^: q; m/ K
  6.   {
    ; V/ X8 J; {4 P
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));( l% `" U$ E; K+ B. \. A
  8.   }
    8 S2 U: n+ q2 z2 m/ x
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */, s# Q: ~; U. w" X8 U
  10.   {
    " k2 }* Q) _2 T/ I
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
    5 `$ h0 n  r$ D2 w
  12.   }
    & [+ l& p" S1 p$ e- S- B( R6 g) S& `

  13. ' k" m. k2 W' k! E" R
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)" ?! I- |# X5 Q# [  j9 |2 P* F# R  \
  15.   {1 \) h* ~2 d2 ~1 Y9 N6 y
  16.     /* 设置发送事件FIFO */
    ( S# I( r" Y: g9 J0 B" _+ f8 l$ ]
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)/ K/ \5 o4 S5 w; t1 ~$ j3 H4 @
  18.     {- H$ f4 v: R. ]8 |) Z$ \
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));. h, W/ o# N' M$ ^: c- l
  20. }
    , i  e. B1 ^0 y* x, y& n) c. Q" D
  21. /* 设置接收FIFO0 */
    " }9 D6 t# }3 Q9 P) J- G& E' S' t
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)) w0 Y4 B5 O% K) x" p
  23.     {
    $ P$ q1 u4 y! m" y$ ^
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));
    1 E  y+ ~3 U2 T5 R
  25. }% _' A7 Q: u6 d+ j( x" P
  26. /* 设置接收FIFO1 */+ U8 f# O+ ]* y5 ^1 R" H
  27.     else
    " v/ |0 @3 Y1 f; H" z: c: @( [& I  |
  28.     {
    $ o, p4 b* R* {# R( A% P, Z
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
    0 d9 j# [) J3 l
  30.     }$ y7 x6 M0 c* S& A, ?$ a0 C/ @
  31. ' `+ ~' g; R, L/ ~- I, r% y
  32.     /* 返回状态 */
    ' d0 w( d. b" G# n3 C( F
  33.     return HAL_OK;
    & j9 h9 G6 I2 e8 Z  K  e
  34.   }# I6 H, z+ F% m9 J) \. l. {
  35.   else
    7 I/ S# y) H) D1 y1 s
  36.   {) `5 a) z0 s  S8 T
  37.     /* 更新错误码 */; l+ e  H) Y& N# E
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;0 x7 O1 ]( N2 D% V: |6 [) {# {
  39. : R# d  N8 L4 u5 h! Q" O8 B4 m
  40.     return HAL_ERROR;% l  u" f- U0 F* W& x
  41.   }, {0 H& e; F4 I+ B1 F
  42. }
复制代码

) @+ I# p3 F9 q函数描述:' r9 w. }% F! G- W
) t5 z( [' Z9 E- G
此函数主要用于配置FIFO Watermark$ E# a! @8 s7 s: w

# [; s# X( ?& x" _7 T函数参数:5 E% l$ i$ \. T' V( M, V$ ]

1 a. q  {8 h3 N1 u6 X" l  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
( c8 R. X* r  M$ C5 c  w3 A  第2个参数是FDCAN FIFO Watermark3 A# [* E9 i# T: [) }" x/ w$ R) F" |
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */, D; d# A; {) s" b* F( l$ `5 k/ ?
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */5 D( j4 t3 T/ m& }4 B
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码

) b1 ^- u1 W& R3 s  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。$ c; N! Y3 k* ?$ @9 q
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。3 z% b# i- G  U- o
使用举例:
2 a1 R3 e0 u8 I' i! b' P
! k; o, h2 T8 @1 ?  m( t( F9 l( L
  1. FDCAN_HandleTypeDef hfdcan1;% `' s# M% @9 E) ?: |
  2. 8 U/ v) |' r4 Q* N
  3. /* 设置Rx FIFO0的wartermark为1 */: f7 B& O- j2 ~7 N( U' g
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
" b6 J+ e. d3 x
91.4.5 函数HAL_FDCAN_ActivateNotification3 ]# w  Y- O7 l% L# r" m) w5 Z
函数原型:& ?5 @2 U3 X- K, G. }7 x. ?- r3 q

# K/ h. [8 F. ^- V1 Y8 L
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes); p" t! l7 U% w2 Z/ S' o
  2. {- V+ H. G0 [: f9 k" e
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;3 d5 O8 ^& }. O# e. g6 z' `
  4. , x& v0 f- u2 s# z3 u( i
  5.   /* 检测函数形参 */8 X5 v' d8 _5 n# H
  6.   assert_param(IS_FDCAN_IT(ActiveITs));8 J. S7 m8 T# C( Z! P, W

  7. . M6 A  ]: O0 {
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    2 v8 f# T. i# E# t+ {: l. P5 s
  9.   {* C$ g! K* t* y/ |4 }4 \$ ~4 Z
  10.     /* 使能中断行 */  ]* D, d2 G1 o* l3 U
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
    * B+ V) a6 L. t* k! R
  12.     {
    ' D/ Q* Q( \" H8 v. x& W
  13.       /* 使能中断行0 */4 f* z! ^7 @; H
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
    2 x6 S7 z+ h6 r8 m
  15.     }
    + |4 w' n! f  \. n0 t$ X3 f
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
    ; |+ [$ \6 a/ u/ ^% P5 c
  17.     {& {0 Q& L  g# c" f9 A: G0 H
  18.       /* 使能中断行1 */$ ~& p, i) L& d% v2 O6 ~
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);2 q( ~1 j$ J" E1 Z
  20.     }% z. ^1 b- a; a0 `0 r3 N" [, A
  21.     else& @) ^% U6 n5 c7 p2 Y
  22.     {2 E/ Z3 g5 W  i: Z
  23.       /* 使能中断行0和中断行1 */
    / {* d) b) m' _
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);3 z, M& [) l7 B7 ]; R
  25.     }
    & s( R$ j' O3 F; x3 }. _$ U
  26. , f4 t- }. e" @# K5 _( P
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)3 h+ R1 L# A% J" ?$ [
  28.     {/ Z0 x2 i' U7 @' q3 I- j
  29.       /* 使能Tx Buffer Transmission 中断 */
    - S) y8 B( ?5 m) Q/ e
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
    4 m; C3 Y/ E1 D) A& j  `6 c5 R1 ?
  31.     }9 Y- f2 H. C4 i# V7 i" K2 {, g
  32. - ]% a4 A) z  ?6 ?% J
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)! T3 g% r3 x, A7 \6 D7 @
  34.     {$ U' d6 r( F: k. ?0 N* d1 w
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */
    " b: i3 Q+ o2 U6 o! g; V9 w( C
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);6 m5 R2 }& t1 [9 m
  37.     }2 ?  `. D, h2 H- N
  38. & d6 u& f( B4 }" R
  39.     /* 使能选择的中断 */
    ' S- L) \+ F6 G' T$ [; ]7 \
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);8 G" `* R: n- z2 G, h: R: ~! z6 W

  41. % d0 c* E6 J* Z) N9 a7 U9 p
  42.     /* 返回函数状态 */8 ~0 i9 o. \4 t( F" N: h# K$ I. S, l0 Z
  43.     return HAL_OK;3 B& c, m; B1 `2 ^( e" ^, s
  44.   }3 h; m" @& z  A5 O- y
  45.   else) {% I9 z5 E  x/ w7 W9 F) G5 Y
  46.   {
    % ^( U* r6 [: T" c- X
  47.     /* 更新错误码 */
    - A8 k# S4 L  [
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;  K' `; m) \+ Z) G, p) C; J, s, \

  49. 5 ]* b- Z, M# F; g7 {. }! M3 Q
  50.     return HAL_ERROR;
    4 ?1 L0 T% E5 ]# t: c  j5 z
  51.   }
    ) `: D0 V+ f5 B# |
  52. }
复制代码

5 E4 n! M4 e1 L: n函数描述:1 E6 e3 f4 t& F( E$ `' U# n
5 h, b4 C- U1 Q: J
此函数主要用于使能中断。
4 K1 i4 k/ m7 _9 B& U6 d2 T( w. G
函数参数:
4 K  H2 L* V( Y
, Z2 H# q5 M! d5 ^- B  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
1 ~  T4 H) p+ Q& ]' i$ o1 _3 k  第2个参数用于设置要使能的中断,支持的参数如下:) H/ y. l2 e2 r5 }, k+ g! f
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  + Z- D0 \: H, `* h5 P
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
    " A3 ^7 D5 D8 }: p8 q0 a* i$ L
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         . Z2 |( q3 M0 I* j* ^' x
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */1 g$ I  _1 Q" C# Y( X
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer 3 l; h3 d" g# F5 t
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
    6 ?7 j* D1 g! p, }- Y: `* K6 r
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */0 ]' E  Q8 U, e- ^) {" V
  8. ; a$ F5 z3 Q( n3 H$ l5 t
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
    7 w, L3 q+ A: h9 k8 \( l- v- J7 y
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred ! H3 r& c# A9 L/ p" D- ]& W
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */+ F( _" ]5 P0 e+ M" \% z
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */& s2 u1 c9 m' z! J$ O
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */) G' i. [+ w# o$ z
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */6 x. S* y8 M$ x) _; K

  15. % L% Q' p: r  s& y% V
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */6 s3 z# I% a5 V! x6 o) Q
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */6 {3 f0 l! M4 ~& v, X3 n* R
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark *// t8 z5 `! d  Q$ D; x2 ^7 D' F
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */, X2 v) b' z! ]! w

  20. 5 W* l, }+ \9 o2 }6 u& _
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
    . R2 Q+ d6 T( A. Z  n
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */! w. D8 h) `/ b7 k! F
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
    5 n6 I7 @* A+ n. \: I$ [* I
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */
    4 G( R1 o6 N( Y9 l: u& F! c% S& U
  25. 8 p  _4 l" T( q$ h6 K
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              2 |% d! |7 a8 u+ E
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
    - V% [3 v2 y% R$ D" h
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
    ) P* b5 |! J9 U  g* Y+ ?! ]
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     
    # d  x+ a  a) n: R+ d
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            
    1 t1 Q& N- z- w7 m9 S% U" u
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              
    & |$ B, ]5 ]- k
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
    # w8 N+ ?* Z/ o1 C
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */2 W0 D' p' N3 S
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码

: v5 m: m1 Z2 m( z. U6 E! J  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:
# x8 c) ^) ^/ D+ G, t+ M# ^
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
    . V( V8 ~: R' _: S1 h! ]
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */
    , S/ b+ Y% c9 r# Y
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */; J+ G1 a9 [2 m* ^
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
    8 s5 o2 C* O2 E4 [
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */, `2 n) z5 E: W" t. C, N% j
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */0 z, F# b% h3 G8 n' n4 q+ v) ?
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */6 R. M; j: v8 f& _  E* j2 B
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
    # u. _7 |  l9 `, P3 i. W
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */
    , [! v  F1 }; p, r  b6 e$ g/ B1 O+ f$ S
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */" V  a. _/ P8 f8 ^
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */
    - j9 [& Z4 s. N) {. `7 n
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
    / B7 I+ I  p. B; {
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
    - x% \, s$ @5 Y# u* N
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
    " ]3 [; `% g5 c; l3 r
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
    5 k% f" |8 V- b) N. Y
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
    + Y" s- M3 P1 v
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    9 U& l& U8 @4 H8 j1 W4 D" ]$ w
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
    2 ^. ^6 C+ I6 ?1 z6 n2 k
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
    ( X9 p+ h. B0 V" Q, ?8 Z
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 *// x, a- W  p7 P$ C3 j9 `
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    3 v3 [1 H8 b5 e( x: n$ |
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */
    . R# G% W; ^4 l9 H4 n5 |
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */
    6 h; c6 Z6 v2 A
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
    # Y" B/ ?% r# m- ]
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
    ! ]! O# i3 q5 Z! y' U& K9 I
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */
    ' Z, R# r% N" n  o/ I
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */& Z# j& t. n3 h  s7 X9 n5 b4 ~
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 *// f; U2 X( B' n5 ]3 r/ \2 ^' u' ?
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
    , r( T  B3 V. A9 f% U$ s) r) S
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */& I/ q2 l9 E' ^8 A3 s
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */3 s0 U7 Y* K7 O7 h
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码
# q; U5 n% L' j0 |
如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。, @. @0 R  t  {5 V) }

2 b" H" v: |) r6 E7 D7 A  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
  ]! i* [1 J) ~* i/ W8 H使用举例:
( t, N! i' N* N. r9 M+ H$ G; m6 k5 a3 G& |/ e8 e3 Y
FDCAN_HandleTypeDef hfdcan1;) q( U+ e1 y5 U4 y1 ^% v
8 p% A/ @9 @9 ]: w
/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/  N7 N& W, H. B+ P6 C
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
1 T2 D; v+ F; q6 l  A$ \: ?, ~91.4.6 函数HAL_FDCAN_Start: U  t; V% Z" o' B& r  W- P. y
函数原型:. x- K/ c9 M5 X' L9 d

; Q9 N3 R9 b. U* g, A
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)3 f. R$ V0 a/ A  w5 l2 k+ [. N! x
  2. {8 \  E. G% _0 U1 T( Y; H0 \. X7 P, M
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)& k$ {, L2 p0 l. r0 Z
  4.   {
    # `& G! C7 [: C( X1 j
  5.     /* 设置FDCAN外设状态 */3 j, }- g4 F: l# x6 Z: Q4 q4 t
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;
    " p2 C9 s% A. ]5 s" R! ?% k1 L
  7. ) M" |5 t  X0 c9 [5 }8 W& Y/ G
  8.     /* 请求离开初始化状态 */" u: Y, V& c5 q; J+ E8 y
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);4 C9 D+ q3 U/ l2 l

  10. # |' c  v: g' t& ~, _$ q
  11.     /* 设置错误码 */
    $ \" ]3 @* C2 ~4 @9 T5 u
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;4 C5 b+ @7 u, Z

  13. . z& K& m- G0 l$ |$ T. r
  14.     return HAL_OK;
    7 k& P3 o6 D3 c. o
  15.   }" j( l# s- v/ q; e7 K* D
  16.   else, W4 t( e8 J) W6 p& I; _& x% ]
  17.   {+ h& n/ y) X) s# ]
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;7 m2 k* g% [% i- ]( q, l
  19. & ^* y2 Q; C8 e! t, [( e
  20.     return HAL_ERROR;* m5 ?9 J: X7 [- H  U
  21.   }7 b( K/ W" k& y5 _$ m+ r1 y
  22. }
复制代码
. a  O" c0 \: E7 y: `
函数描述:
- ~6 f* F4 i( h# X3 a* W! D5 x2 `: u
此函数主要用于启动FDCAN。0 {2 Z0 b5 v3 u: A

( w, |, ?& I) h' F6 u/ H  [函数参数:4 }5 A& K( m3 o2 d7 |

) U, B. Y% O  s" R+ ^  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。8 P9 J( g/ f5 N  o  m5 n
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。* H* ]+ k0 v  r# q+ Z( {
使用举例:
, R$ V% p. h$ [; ~8 p" a. q1 ^$ U5 V) a$ w
  1. /**, E* \3 L" f- i& ?2 a5 L1 M
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
    4 O# c7 U" {, L: E& p; [* e( F
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    % v; E' q7 z& f0 z# Y0 ]7 F) d
  4. * @param  WriteAddr: Address from where data is to be written
    4 h& I5 I* |6 o+ m. W' g( ]6 v
  5. * @param  NumOfBlocks: Number of SD blocks to write
    % ?  [3 c3 R, O7 M1 ?8 c5 }' F
  6. * @retval SD status
    ; `& g( i1 V) n
  7. */
    ' Q: v1 ]$ c- i0 Z0 Z, s# S
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    * l' \0 T; H4 P6 j  H9 }
  9. {$ D: e+ \6 a* w

  10. % G: r6 C1 k7 C. @- |$ O
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    . ^2 n( f! N# S8 X. r
  12.   {9 {) Q5 W' S3 F2 l$ G8 y
  13.     return MSD_OK;  H, _7 h/ [3 C# t
  14.   }  Q  M9 d  p& W1 h/ z
  15.   else! ?/ m0 Y2 O7 T1 v9 W
  16.   {1 e5 A) C3 Q4 I3 W( U
  17.     return MSD_ERROR;5 v0 o; \" K4 o! j/ t7 M
  18.   }
    0 S4 U* j# L+ y6 W; T
  19. }
复制代码

5 k4 I( f" P" [9 I91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ2 e+ o% d+ h: I6 Q
函数原型:
% P  B* t/ @0 w& T8 L
8 ~1 M% \$ U) Z
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
    ; U% b; i7 _- ^0 T
  2. {
    - {. F4 |- I% v7 H% _' h! f/ N
  3.   uint32_t PutIndex;
    + k' `) O' i! h. j$ q9 K
  4. 8 H6 a# t/ m' D; L/ K. J6 q
  5.   /* 检查函数形参 */
    - @! P# o  N1 Z+ _* K$ D' G" c
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));% H3 y4 y" F! j% p, k
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)5 a# \4 u- z& v6 k, i  }
  8.   {
    ' Z  ^1 c# s# G' F1 _
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));
    + v5 z- [* H. W% q+ c
  10.   }" T. s# f# ]! c# V- G3 g
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */
      h1 i! P/ U/ w5 m, f( s. N
  12.   {8 g1 C5 o  w# A  R% l# _7 {  J
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
    + O% B$ q/ K/ Y
  14.   }5 ^; l) @0 h, ?3 ^- F* g; _( ?
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));" r  q0 h3 v. _6 E
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
    , w$ H4 V( t- x% B7 K  ?- w
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
    9 t. H- m0 i1 g& M
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
    ' }% T1 {  [$ S% d
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));7 q% c8 v7 t; I% A
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));( ^% j+ i0 V4 `" M/ ]
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));
      }/ o5 a) `" Z' L! E3 D

  22. & c8 n) M; y8 Z
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)7 ]' R8 l2 L+ J+ N4 l" b  P' L# f
  24.   {
    6 {! @! m/ T# X+ g  _6 J
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */& K( C$ M2 G9 f& t
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    ' Q/ r+ _) l: }' m/ z& }" p
  27.     {; m: C3 L4 ~0 V4 O8 v& b  k
  28.       /* 更新错误码 */, r5 Z% b3 V7 s3 \
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;4 S4 f1 g5 Y7 a  Y% M5 s" t
  30. ' f9 N$ F- v* _
  31.       return HAL_ERROR;  j; |9 _- U3 A+ s9 l* q& H/ y
  32.     }
    ) Z$ x% W" e, s$ t; ?
  33. * z$ X6 n9 L3 K' [
  34.     /* 检查Tx FIFO/Queue 是否满 */  c# O1 v, ?; x
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
    6 G* U6 G  O5 T
  36.     {
    & _$ i2 t+ V! X6 S+ F+ N+ D
  37.        /* 更新错误码 */
    + u; K! A# f. U; A5 @$ Y+ V
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;& k3 T  ^0 S/ W+ ~" n
  39. 2 t# h& o: w$ E3 o
  40.       return HAL_ERROR;! b# s0 x2 _  H! j
  41.     }
    7 ~% t6 h! H+ e3 Q! z) B# ]' A
  42.     else. v' f  d. Y2 N$ I  Q" C
  43.     {
    : D0 C0 Z! V/ {3 ~6 x- B! N
  44.       /* 获取Tx FIFO PutIndex */
    , x; I: ~: k# S8 y; [  y
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);% H5 B& i" |: C% p, X' l
  46.   _" q" B. Y+ }. m3 ?& e7 S
  47.       /* 添加消息到Tx FIFO/Queue */
    + m* h! s: m5 O- `
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);
    9 i4 O. {/ L& h" d1 h- R

  49. 1 n" t8 u2 ^# d! d
  50.       /* 激活相应的传输请求 */% ^' G" f# ^. G$ b5 a! w- ^8 j
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);9 Y# ?  u! ]* }# g& h5 E

  52. 4 E* y- ~: |  M" a6 k
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */
    5 ^/ ?( T3 M- I% q% m' p( A, n
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);  n6 q; C& D" h1 l0 c* T
  55.     }
    9 m4 Z5 \* M2 W7 I1 F9 q

  56. % m& g' {% B1 i( B+ c/ F
  57.     /* 返回错误状态 */% a! \- W, y3 X. Y! W7 F2 a+ |
  58.     return HAL_OK;2 x  K: k% y- z7 ]; S0 `$ i4 u' b
  59.   }
    ( [7 v& }0 ?; ?+ I0 k6 {- Z
  60.   else
    " k. A# N5 u( j0 e! e/ Z5 n% \
  61.   {3 y7 {4 L' c! ?! o& T
  62.      /* 更新错误码 */) K3 n' q, V- y3 s+ Z
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    ( c, @* F4 o- t4 o

  64. 6 q4 A% m; d3 z3 C8 H9 M
  65.     return HAL_ERROR;4 Z5 R) a$ l$ x3 O
  66.   }6 |* H. Q& [  }6 p. n9 Q, d
  67. }
复制代码
  k2 T5 B; i6 f: U8 r
函数描述:
) ~/ O0 \* J5 f* d. x
4 J( [$ S0 Z2 E9 ]2 E此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。1 O; T. \6 F. i6 e( ]7 H9 @* G, _

/ s. d% Z, M$ r$ G9 u函数参数:( P( P5 W, `0 z, g4 I
% e' M- F: D9 a+ a& a4 q+ b
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。5 P- l) [$ x( f% l/ W* R5 j6 m# G( p
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
8 Q) X# n: }. G: _8 w! A  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
) J4 A% a% ~( L, _/ A. T  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。9 W0 G/ \1 h) w% A1 B
使用举例:
7 j; Q1 L% e  @; |5 T. B$ v$ w) k' h4 o5 F3 U- m$ E( _8 P) w
  1. /*( g) c; b1 _# u- _" v7 b% N
  2. *********************************************************************************************************
    ' v( A  c8 m- n' F2 ?
  3. *        函 数 名: can1_SendPacket; Z5 ]7 O0 E4 j; W$ M# m
  4. *        功能说明: 发送一包数据$ X) l/ Y8 D7 K7 _5 ~
  5. *        形    参:_DataBuf 数据缓冲区
    & ~8 c* ]& N4 w, b
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节
    - l4 i* [% t1 P' ]4 q$ J$ h
  7. *        返 回 值: 无5 ^/ ?% k2 @4 j' i( K
  8. *********************************************************************************************************( x) ?( H; D) f* p
  9. */
    - U0 o9 V" x% o/ d  _4 W+ C
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)! |* G  h- |" \+ d. t
  11. {                9 g3 t8 h2 I$ }4 f( J- ]
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};  H, }0 B' ]3 n+ S% F" R! L
  13.         ) t3 Q, h, K9 b. b9 _1 v% R! i
  14.         /* 配置发送参数 */
    5 o+ O! o  j! F
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
    2 v) G/ S; \% z
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
    " h! Z7 m: Z1 s0 H
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
    6 p& K0 d  h! ^5 z) R: @$ [
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */
    ) X$ O3 s! r& C; K1 S5 [
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */* q! i* p- U& [) ^7 g; `
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */
    2 r3 |4 y7 W+ m- H- r
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */
    & ~* i+ t: K# \7 |7 b  @" Z$ K7 `
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */
    4 s) \6 P- r4 K" r+ [
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF *// D# f; u7 ]2 F3 e* Z
  24.           O$ {. X- b) Q2 c' b# m
  25.     /* 添加数据到TX FIFO */
    / c/ V0 Z! o. d% F* r/ u
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);& ?  t: g6 R' m' r' O2 f' R' z5 Q
  27. }
复制代码
/ V6 R) g' c! ]9 W8 S0 w$ i
91.4.8 函数HAL_FDCAN_GetRxMessage- ]4 {2 D* I" y3 e% ^! m7 @
函数原型:( a# x/ v) ?; x  V+ B# T  l

+ A( F, v+ f) t7 B- U- B
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)& [8 _! w- Z- E0 J: A
  2. {2 G) ?9 ]  S# B/ c1 m: P( X% ^
  3.   uint32_t *RxAddress;8 P# n" t" ]( Z7 ^
  4.   uint8_t  *pData;( Y% U; [$ R2 G8 P+ _
  5.   uint32_t ByteCounter;
    % C: c4 @7 q1 n; I  A' U0 c2 Y: t
  6.   uint32_t GetIndex = 0;' h& _% ^8 B, v- e
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    : t7 g) f6 Z: v9 r, c9 o, J

  8. / n5 o" U, p, F8 Y
  9.   if (state == HAL_FDCAN_STATE_BUSY)- D  A, G" @6 Q! a4 }% M' L6 |
  10.   {
    + a$ X. p+ n# Q# w5 E
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    3 g& M! p1 B" t6 U) }
  12.     {. r+ O9 E& {4 l  m- F5 s
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    6 N9 M0 K. S0 s$ _% |
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
    7 R+ a- M2 W% ^6 i8 D4 j
  15.       {( p* l5 D. \, D0 c
  16.         /* 更新错误码*/
    8 k5 i# s2 |7 Y. j- f: g6 H; W8 Q. O
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;  d9 Y; Y4 _3 J  m# g  W6 R" b2 p: s
  18.   L2 X# D1 ~. d0 r7 B& `
  19.         return HAL_ERROR;
    8 F/ |. R/ E% c
  20.       }2 B0 F$ C  G! F# p$ C" \- \" H

  21. - `6 ]* @  N. q9 }* C- w* `* t, B
  22.       /* 检查Rx FIFO 0 非空 */; i/ n2 c" A0 P! B
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)7 x, Y4 E! D- c" b
  24.       {) ]% v( e9 V7 a& r. O& V1 O7 J+ e
  25.         /* 更新错误码*/
    3 E* A7 u! u7 Z! a8 ~, F' k# H  m3 ~
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;  ?+ R/ z3 h, K
  27. 4 h. i# i6 q* t1 z
  28.         return HAL_ERROR;0 R) n: F) ]( M' t- L, l
  29.       }2 L$ ~' R& y5 Q5 |1 U  T, R
  30.       else7 s, C0 G0 w9 q( o3 N
  31.       {
    2 ~; e% C- w( S% H+ C( c+ a
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */7 p, ^6 Y3 s5 y" q* {
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
    0 g$ U* _) y. r/ l5 s9 f7 m
  34.         {) J1 W8 ?% j8 q- S# j5 @! |, X
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)/ l3 O- `" r2 q  X0 _, x) l
  36.           {
    / G' t( Y  I/ H
  37.             /* 开启了覆盖模式,丢弃第1个数据 */& E# N- t( a8 k: [, D
  38.             GetIndex = 1U;. C3 |1 t3 q# z5 F# T
  39.           }
    6 m! b1 o2 d- t6 G; x( m6 C8 c
  40.         }. b* @- s% `0 ]
  41. 3 g1 ?1 W! Q) |9 X6 I
  42.         /* 计算Rx FIFO 0 element 索引 */7 G$ K6 E& l, l+ P) b  y' f
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);6 {, e+ W7 f; `" x
  44.   V3 W% j8 _* e+ I8 G/ A
  45.         /* 计算 Rx FIFO 0 element 地址  */2 ^6 ], _3 N& _  b" v, d: p
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));8 ]5 t1 E8 Z, y$ T# y
  47.       }1 H- t1 W5 m( n( ?. k; E
  48.     }
    4 d! m, V# K' I) T# a$ S
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    : S1 Q: p+ c5 t7 Y- z
  50.     {
    4 m! q0 |, t% R6 g2 E; Q. r# c3 ~
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */9 H$ r" V7 d$ q% J
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
    * j$ k% b* r1 t* c) A! ^
  53.       {
    ' H* W4 G9 N3 _2 Y( M) w* v
  54.         /* 更新错误码 */$ O+ r! z8 J8 D  i4 s( I8 g& ^
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    , S, ?5 Z& T+ L+ K+ q) U1 g
  56. 5 I8 \/ e4 c1 S3 [! H
  57.         return HAL_ERROR;
    0 r0 U: `  L6 S( ~( ^' E* ^
  58.       }
    ' K( W0 Z1 m. C0 t7 j0 x6 B

  59. 2 S/ G9 E8 C* X5 s4 l$ N6 ~
  60.       /* 检查 Rx FIFO 0 非空 */  D) V: C# A, [1 V) I( B2 T
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
    + @; V# f5 \, t  J4 O  g
  62.       {: `' f" u- F& p
  63.        /* 更新错误码 */
    " |- H; }* c; T* {) c2 f* d0 i# i7 o$ ~
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
    8 d* G5 J% R' {2 T

  65. ! R* e* ?( J* H8 w( k
  66.         return HAL_ERROR;
    ' N! N( V/ ~( R8 j% d; K9 {* i
  67.       }( G2 h9 I# m7 {- n  m: c
  68.       else
    : L" ^9 `8 F- K9 |! i! t
  69.       {
    0 A) T) C3 T& N
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    " f. V+ e4 m0 w2 P
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)7 V9 m& P. H2 F& W
  72.         {
    - M( S5 \  m1 f7 A0 s* W
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)9 L# V% z0 [% H0 z8 K
  74.           {: R; [6 z2 {) g* v! H  S/ W: ~6 w0 u6 d4 @
  75.             /* 开启了覆盖模式,丢弃第1个数据 */) |2 q1 t) n# c/ `+ j6 p
  76.             GetIndex = 1U;
    ( g) O% A# o' J6 v+ u
  77.           }$ b% }, G! x+ x! X1 n
  78.         }! D1 z' h$ b9 P* S( M
  79. 1 Z6 }! V. w& f" ^  p/ R
  80.         /* 计算  Rx FIFO 1 element 索引 */5 O/ ?5 Z2 l2 w3 X* M& \. y) G" b% X
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);
    9 o- K& M6 o3 q$ A. V

  82. ; z+ B! B# W, W" B
  83.         /* 计算 Rx FIFO 1 element 地址 */
    ' X, S5 m% ^! m/ ?$ f) _' c' p; }
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
    " S+ P! S' ~/ n, ]4 Z3 `
  85.       }; Z8 D5 u  G2 |3 x3 J* J
  86.     }& _: W# Q. n6 h  h8 a1 S$ O% i
  87.     else /* Rx element 分配了专用 Rx buffer */, X6 W: z, l) n8 G, v1 H
  88.     {% t3 V, {) P" b( Y: i( K7 L
  89.       /* 检查选择的buffer分配了RAM空间 */$ ^4 k# Z! ]% f% a3 M" J( }
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
    ! j; ~& X9 K/ ?# U( e& I0 q" `
  91.       {
    ) |$ I8 X0 H5 [5 C$ u, @" y
  92.         /* 更新错误码 */
    ' b! ^( Q) v6 a3 U8 ~+ s
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
      A$ W( o+ {# _  N

  94. " l, g- y4 a' ~# C' n7 S
  95.         return HAL_ERROR;  ?2 c. O) t# X! n
  96.       }
    # U' D/ y' Q* B5 m! d* g  t
  97.       else/ _. O) W3 j' c* I# g9 L
  98.       {
    + a0 {2 d% N' e+ d9 Y6 q
  99.         /* 计算Rx buffer 地址 *// P- C, o( x8 m4 k3 v
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));
    , q; S1 F. s) {1 A) t, o
  101.       }5 }6 K9 ^. B) L& _  a
  102.     }2 Q! k- d  n6 Y$ p8 N# \
  103. 0 ~2 b3 Z" s: S$ d
  104.     /* 接收IdType */; }5 y& k1 `- y% J  l
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;$ J7 x0 D$ X1 w, Q

  106. 0 q6 X. H% ]/ _" y: @- F
  107.     /* 接收Identifier */" |0 V) {! `) C6 I' z8 ~
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */4 K" a2 I$ V5 T# x2 `- ]) ~* e3 J
  109.     {
    3 A" I% Q1 }4 T9 r1 @0 v
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);  i" S% [+ K  z$ f1 |
  111.     }
      p1 X5 b% x8 c% [4 J7 _# L
  112.     else /* Extended ID element */5 h/ T) @6 Q1 ]% y6 }
  113.     {
    5 U7 U* X. R2 Q8 n% a: j
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    7 R. N2 Y! B5 k: y
  115.     }
    7 \: m1 h4 s5 K6 p* s* T$ U7 f' \2 u
  116. ( p. c1 H. R: H
  117.     /* 接收RxFrameType */! N, |5 w/ a4 E, E/ G
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);2 R$ z  v# l7 m% J: N$ b' P

  119. * k3 _; a5 u) A5 A8 i5 [
  120.     /* 接收ErrorStateIndicator */
    + y# W; v1 G4 q+ s/ ~/ a& p
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);
    $ @2 s5 R5 H9 K" i! |+ R
  122. 5 [/ ?3 D% d7 w3 O* D6 `+ j5 c3 Z& A
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */
    / o/ M# L/ k& j0 a
  124.     RxAddress++;3 ?8 O* w4 Y8 k) |4 b0 _

  125. # B6 n4 r" ~, r: r" B4 T7 {
  126.     /* 接收RxTimestamp */
    1 m- Z" }, c9 Y
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);
    + S. q" `5 E& l, u6 D. _1 j# P# A! K" ~3 |
  128. / k8 ]$ Z; T- k* D6 o4 T) u
  129.     /* 接收DataLength */
    : m' v0 j- c/ @' g
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
    5 R" U# V; T, {- m! ?3 v1 x* E

  131. ' U3 @# n* s3 I- g  {) R
  132.     /* 接收BitRateSwitch */9 d3 s8 T0 s' g
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);5 d8 {, [% s6 C1 X+ q. C% b
  134. - t2 J7 ~8 W3 P- w- t
  135.     /* 接收FDFormat */. K0 ]: x$ y6 y) Q* M' X7 R; h
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);
    5 B, B1 @9 f7 V7 q6 H8 ]5 W- ^' H

  137. ; c3 U+ t3 _6 Y4 y. L7 g
  138.     /* 接收FilterIndex */
    4 Y7 Z" f3 l  A$ N% u7 X. ^
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);
    1 c% Z$ p. e4 _) S$ [# c/ [

  140. / _6 U/ l! G) W- B$ O
  141.     /* 接收NonMatchingFrame */
    ! e" T, E$ x) z9 L/ n* [; S7 E
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);5 D6 U* G1 \6 z/ A
  143. $ y4 I5 l$ H- @; L) a
  144.     /* 增加地址,指向Rx FIFO element的payload */
    0 @5 m: w' ?( g
  145.     RxAddress++;+ V( N4 [, [7 {9 @( X2 w9 w
  146. 4 _- e) {0 A3 v- O8 ?& w5 k
  147.     /* 接收 Rx payload */
    + D" }3 i" t# o& Y- u' ^
  148.     pData = (uint8_t *)RxAddress;
    . J9 S& i% v- S1 [) r8 f9 Z
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)* d  p; `3 x8 y0 L) R' g
  150.     {- t+ C6 l  y& |# O
  151.       pRxData[ByteCounter] = pData[ByteCounter];
    0 s: T( A5 Z+ @) x' a
  152.     }  z8 @* F/ M+ X

  153. & C6 x: j* P2 Q' \4 Q
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */( x% s* D' f, p9 x( ~8 [
  155.     {
    ) U4 o* S7 L6 R, U2 Y* I! q3 _
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */$ A' i, N- \$ |
  157.       hfdcan->Instance->RXF0A = GetIndex;
    ' x7 Q+ S% l/ ^
  158.     }+ w& b. t% G9 r
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    9 C% c9 s- E5 S! H- A1 E, W1 n: Y
  160.     {8 R7 v5 u1 R# I5 U$ X: s* c" r
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */$ k0 p/ G* B. |' S* U4 o9 S
  162.       hfdcan->Instance->RXF1A = GetIndex;
    + K8 S& D3 E$ h  J2 r
  163.     }
      ?7 W+ Y+ p) `+ @
  164.     else /* Rx element is assigned to a dedicated Rx buffer */
    ' g/ c& y! s8 u9 C
  165.     {
    8 t" N2 a. J" k- U, E0 b
  166.       /* 清除当前Rx buffer的新数据标志 */
    4 |1 H+ J' ^( D& M/ Z0 j. @6 Y
  167.       if (RxLocation < FDCAN_RX_BUFFER32)4 F3 l4 I+ i+ `* D
  168.       {5 I, B0 p: q5 d+ D& B2 j9 P8 x
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
    - I0 s9 H1 k6 ~6 P& O% _' m, q
  170.       }
    7 v, E+ L1 U  M, _1 S! Q
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */7 U/ I/ a3 M+ q6 D8 \
  172.       {
    " U7 z& E) F5 f  [1 Y% \1 ?) f
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));$ A* b( c7 V. ^" E8 c8 R/ C
  174.       }
      d5 X0 F) @0 E6 K
  175.     }7 f( D3 u2 c, X4 [4 r* y

  176. 6 u. o0 ^! }7 P0 z' B
  177.     /* 返回状态 */3 ^) |& @3 t% o- N
  178.     return HAL_OK;1 S2 ]+ s" M8 H; B( d2 a! y; R
  179.   }0 Z& A* V5 Z8 ^5 m
  180.   else% N0 W) d; l; F' c
  181.   {
    + n% e. [! r' @) ~. u9 o* _1 r
  182.     /* 更新错误码 */
    8 B/ N1 g+ I/ D- f- U
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    - A* j+ C$ I0 I* R5 q% ~

  184. 8 U. t' E# k( C* [
  185.     return HAL_ERROR;
    $ L2 }; A  M( J7 D1 _; y& k$ u
  186.   }
    ! T) |0 b1 U3 @. G& p
  187. }
复制代码

8 |& G$ `# ?1 |2 a/ ]函数描述:1 n# ^# \) r- ~$ q$ \  U
  Z( w7 p2 n- `6 A( T5 T% V. r- v
此函数主要用于获取接收到的数据。$ b# W' n; ~9 ?$ q& W, B7 L. H

! C" e5 t7 ], E, C  H函数参数:( ]/ G  N) z! v* ^9 h: F1 |! X
& A/ [/ R# G9 I$ o
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。3 v* Q0 c0 V/ n+ S  W, ?3 j$ G
  第2个参数是读取位置,支持如下几种参数:3 Q6 h) C7 B8 e# r9 r, ]. j
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
    % z* a: k1 c7 c, l
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */: ^) H8 ~/ g4 ^) v. L" a
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
    $ r$ T3 I# E1 O4 ^
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  *// [8 K6 j, j/ V0 u5 t# g3 o
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */( s1 I; |; [. ^7 `. P+ c
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */
    / r5 K* k1 Z1 \' J, m
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
    4 R+ k( J5 `1 J4 ~. I9 I4 b9 c
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */% m- Y  p/ d! m3 a6 |# V7 x* c: n
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */, Q( N7 _# u+ F) S3 W& B) Q! s
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    9 W* V2 e9 E2 c% E. e
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
    # @0 K) e! k$ }. Y# ]
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */! r# O; ?( H& [# D) j' ^
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */0 O1 I8 ]# y2 C5 Z8 G+ e2 y1 H: I7 s/ ?
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */% f1 |$ W  C- E. W# s. v! F
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */8 U, j( x/ ^; D
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */9 l+ m) [9 r. q4 `
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */; T4 f+ k' _2 ^& P$ C
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */$ }  k' }. w  A* d; t) O2 E: o
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */9 M5 A- \5 }. T/ `
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */0 e' U! K0 G# v* f/ z
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */3 f# X) w2 V' K+ h. ]1 p$ P
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */
    7 t0 C8 z' X/ D( v
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */
    " `# t3 C, k* a
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
    9 \" P2 _1 |6 Y" o+ q
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */- g4 e" a& s: c/ @
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */; A" D% @( B0 E- G% v
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */
    $ O. z+ @$ \* Z2 w; T) @+ w
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */
    " F% O1 v3 L# V* b
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
    , k  C/ d# Z) t) Q  i
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 *// H' X- S9 E1 ?5 w" }) d. d4 r
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
    . T# N3 o5 O8 ~" Y8 J5 s1 O9 W
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */
    , ~- J$ D' V* n/ R' o
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
    $ M  i. y- Z5 E7 E; m' a" J
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */0 N$ W" o0 [' P# n7 Q
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */+ x% }& l: [4 X8 [9 P
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */4 {) }/ ~  f8 W0 y% I) j8 w
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */: d$ @$ A1 ?+ i$ ?1 u) ^
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
    7 r$ `* {7 U- n8 |! n$ S- R9 P
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */: H2 I6 z$ H, y- h/ }
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    " ]* l+ Q1 ~( x1 f
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */1 j' M: T* ]/ J1 M* e  ~" v
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
    ' D8 l1 C6 ?4 g  i5 t
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */
    ! a" ]2 W8 Q/ t- H, f0 L% D+ K
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
    5 @' P+ V6 e5 o2 W- P8 r
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */
    ) [  v- m. }! j
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    - ]9 J" r5 n: x
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */6 Y. J: N- Y* u* N* R
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
    7 ^3 {! i  {; t2 s+ b
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
    ' B, u+ Q& B$ [, I
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */, w  ^7 L' e! X0 M7 l) r/ l6 f
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */$ n+ i0 d5 R% w9 @5 ]9 k
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */& ~7 }* q9 Q& K
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */
    5 _8 c2 r/ w( W1 T0 s6 l
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    % q. D; S% W( t3 t& D4 ?% X$ u4 s
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */% ]. r2 [$ T9 ?  L  R
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */
    * b1 C" Y$ [) w1 e1 E$ t# `
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */4 [: [2 t% O; A: m! n% y" [
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */3 F1 u1 ~2 A' G
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */
      J( n' S+ R" H- a% d
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */
    0 T( a# G2 C* X0 x+ x
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */, L% M+ {, k. a6 h
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
    # L: O) s$ \" ]3 |" I3 b
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
    / f: W& u" l' |7 d* s7 U
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */! Z! f/ h9 T$ Q$ S0 Q) Q$ {* R; u7 N
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */
    8 n! ^8 X# h, k0 s  C& Z' z7 F
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码
5 n) X4 ?! [6 g* @  _' Q
  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。
5 c, q% B6 k2 Q5 x9 ~, @# s  第4个参数是数据接收缓冲地址。
8 p4 |/ _; K% Z( ]4 p  Z  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 E4 E- Q3 N3 U. q" V6 W  ~% ~
使用举例:/ e3 K0 K3 y5 {5 @, x0 b# b' U% @

+ Q! X# x- r, q1 z
  1. /*) @9 @! }7 O1 b1 Y
  2. *********************************************************************************************************4 k, ]" n2 U/ _0 k
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback& y2 `; q( H$ ]9 M' t3 k" Y' c
  4. *        功能说明: CAN中断服务程序-回调函数
    2 ^8 I* c" ~  S2 p' b
  5. *        形    参: hfdcan4 `7 M( N& y+ k/ [
  6. *        返 回 值: 无
    * e9 _( [- C" Q( e% R
  7. *********************************************************************************************************
    ( y% J6 W: f* G; |0 m  H# g" V! C
  8. */% I5 _. ^& Y6 y8 o1 [
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    # K4 Q2 B( v/ m0 M9 J" j4 B
  10. {+ E4 A  u; o# \7 G. H9 a8 V- E
  11.         if (hfdcan == &hfdcan1)
    9 \  r1 [& w6 j+ @) Y
  12.         {, @9 }/ v- L  h/ t7 }
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    ! q$ {' r; v6 H& e
  14.                 {7 W* p  Q# |! J& A' E7 [- |
  15.                         /* 从RX FIFO0读取数据 */
    0 I$ [+ t) y3 y1 {
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    - Y0 a6 l3 z  I
  17. ; Y: C  v- B3 k+ Y
  18.                         /* 激活Rx FIFO0 watermark notification */# w8 u; X3 n7 ]0 E8 D% U
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
    5 ?/ n) X: S8 o
  20.                         
    * ]' i$ e+ y2 G/ [
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
    1 W5 |' u1 a& D* t3 g) N
  22.                         {
    $ }5 K" h# O: ~2 D& {
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */
    2 W0 y' q* r! j9 H
  24.                         }
    " A) q0 `1 _" {* t6 [0 K! b
  25.                 }2 M- Z$ n" z9 _0 b9 x4 s
  26.         }
    2 _( Q) l/ Q9 g! _' t% K
  27. }
复制代码

- M' _7 G! W9 T6 D91.5 总结
# V$ G: T6 z  N# F1 \本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。
. r  s; E, ~; O& m6 {  |4 O; c: J# D, \

6 T3 ^5 Q: @5 d7 q4 @" @* J7 b
赞 收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版