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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示
8 |3 f6 d2 U4 n8 T  FDCAN基础知识点可以看第90章,已经进行了详细说明6 {/ x" U8 s5 W* J' Q" z6 Q
  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接
0 s1 U# c% L; e8 y91.2 FDCAN基础知识8 d# R, c1 K1 K4 B, d
FDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。
+ }3 D; P7 ^" E: q( i7 U  B/ f. B: U* z& @' p4 t
91.2.1 CAN FD协议介绍. _# @9 P6 P5 c, n5 P8 q2 E  j
STM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:
, h) |/ R, L6 _! P3 _' P2 b
; M8 t  f: d) f. Q% g; _(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
" k$ g( ?$ s4 c5 J7 T# r. w  ^( j9 z3 l, [+ h. u/ ]: o; L
(2)可访问的10 KB RAM内存,最多可分配2560个字。/ K0 I6 O. z3 V* G) u# I' v
% U1 l) G* ]  a" j+ b, n/ S
(3)改进了接收过滤。
/ W! B0 x; T9 y1 E( Y! ^6 {" ^+ E- B! f: a/ F/ d, h+ I  o$ x% S
(4)两个可配置的接收FIFO。5 @" l6 V0 y4 o" F. D+ X

$ _% y5 x5 e" }, N(5)多达64个专用接收缓冲区。0 V, _9 w: N1 E( x; [. t

9 K! u- Y& v7 P(6)接收高优先级消息时的单独信令。* f' ?! C! N) F; G1 [* [
3 @! m+ T( `* F# H" v
(7)多达32个专用发送缓冲区。
0 v2 H, k' i) J4 ?3 l: x( f9 c" g* ^
(8)可配置的发送FIFO和发送队列。
3 b* L6 t! I4 n0 e- e5 e# F3 j% ]6 N# i7 v% |
(9)可配置的发送事件FIFO。
! O5 ]1 b2 W( e! ~( R
! [2 p( D0 x0 r& c(10)时钟校准单元。
. s- b2 y! u* {$ y# X$ W7 Y/ O7 G. L: t( J* j3 ?- Y% R! U
(11)收发器延迟补偿。' U- y2 p7 M1 P6 Y
6 k7 D3 C6 q& A& o3 S
下图说明了FDCAN框图。
0 i; e! g0 D$ J! H+ o3 I, }! p+ h; o( B8 J3 n* B! y" G" K
+ n$ q9 J: P) s% i" t1 `
f4f1d5cd872648458911e8be8ddfffe0.png

- I4 x5 R' Q5 N) h* ~) a: @! q" j$ \7 S3 m6 g( j: R4 Z" R$ x1 p' |7 O

; d( `" F, j3 o8 k& T通过这个框图要了解到以下信息:
6 e0 O2 B% Y; o5 B' U1 Y4 d2 a3 F  ]4 V, O0 y4 R3 R
(1)CANFD1和CANFD2共用一个RAM空间。; _. f0 S  K' ~( W  _/ w. `8 A$ ~
5 y: p( Y" E( x2 r0 X0 U
(2)每个CANFD都有自己的内核。) E( T& s5 f- K, Q! |8 V. V
4 H+ i- y8 B" e* S! M  F
(3)CAN内核实现协议控制和收发移位寄存器。3 x( H/ L& ]2 N2 _0 {

  L( z8 b% Z8 G: K( l(4)Tx handler控制消息从CAN消息RAM到CAN内核。% Y/ Q( D; P( a3 k4 `+ a$ Q
7 S% N0 O% _9 O: A
(5)Rx handler控制CAN内核到CAN消息RAM。) M" ~+ W2 w' _0 w8 C8 x

; _2 U( U& a; Q, w6 S/ X/ a# z91.2.2 CAN FD特性# \$ `5 l8 i3 e
(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。& |% ~: {% l8 {. W( X& S
5 {  k" F5 g0 w8 f* M& ^' B0 q
(2)提升错误检测,支持高达CRC 21位的校验和。
, m& B) t4 b& v3 ~' d
: r" ^# _7 y/ [! Z$ D" W(3)消息优先级。
% m) t9 [0 G& c" R
# J$ I8 v% K. H8 W(4)保证延迟时间。
4 O" U* Q# o9 j& N
) i; a+ C- |3 m9 T1 [(5)配置灵活性。: T0 t, E! _  z/ v" L0 @$ m

6 U, Y9 U: X* R" q4 ~(6)具有时间同步的组播接收。# J; e) |0 q) Q6 W' r* A4 i4 z
: }4 R6 A. A! V; m/ F+ q
(7)系统范围内的数据一致性,每条消息最多64个字节。
% \& J; p1 _2 _
/ z/ |! l* ~2 M2 l- f' l1 z(8)多主机。4 |0 m0 i: m* K
5 ?- S! R9 G3 X) W: f; X6 O
(9)错误检测和信号。6 i6 {' Z/ u" b; k/ y

) {, R, S( p4 D2 |' z(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。
, x, x2 _. z( R3 V; o. Q
* l& z7 H2 ^9 `7 d1 @4 G91.2.3 CAN FD格式& Z3 d  q! Y" f: C1 Z

/ @. s$ p, T: ^( d; H3 }
c692adda5a1149b0a6e3d8a30745fd62.png
$ w! F7 D2 ^. G+ H1 E

; R0 z) e% F3 {! N
$ q0 N1 L8 @2 p2 x1 [. V第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:
1 R- E6 R% C$ w3 R& K% M( g: H5 a; r! t% E7 b' T4 O% _% ]
(1)帧开始(SOF)。7 Z* t$ o' [. R( D
$ T( e6 F+ B+ t. s$ [3 Q
(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。
5 q# d/ h* r1 I+ c( ]
* z3 a  B7 q: N0 S) F数据传输阶段(The data transmission phase)包括:
! e$ w* t9 t7 X& r; L9 v) h8 B7 N
(1)数据长度代码(DLC),指示消息包含多少数据字节。: ]) S% `3 Q* ?- s) c! K! `* u
' c4 L2 F. c* ~: ]' r& ?
(2)用户希望发送的数据。
. g1 Y2 e( S9 G# Q
9 b- T. Q. q' q1 ^; R- Y(3)检查循环冗余序列(CRC)。; S. N9 R% X( F% j

  e( K4 h4 Y* j(4)显性位。* c4 b* z* H% [" {+ {" D# k3 r

! O' J1 |( Q% A1 W. U5 n第二个仲裁阶段(The second arbitration phase)包含:
" o+ e% l& }. p
0 I6 E: {7 h# L/ @(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)( ]% j/ ^  j# w' T+ |# j' R
3 E. u* k5 D, ]* Z$ `4 l
(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。
' l  e$ L) Q3 ?8 [
5 x5 C7 ^" R, _# @1 z注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。3 y7 [  _7 O" Z# L8 h
7 D" B3 ]5 U3 o7 i
91.2.4 CAN FD相比CAN2.0的提升6 \$ c  {4 e9 H* Q9 k4 G
CAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:
7 x. I) G5 o& v/ P; N% |) @& Y3 g& {: }
(1)17级多项式对最大16字节的有效载荷进行CRC。
6 a8 X5 D6 o& `/ j
! C' D1 }8 }3 N+ p(2)21级多项式对16到64字节之间的有效载荷进行校验。: o) i: h4 i# I) u
; Q3 m) d' @' S9 k
标准帧和CAN FD的区别:
; L  l# B9 s: `3 v5 ]/ W8 G, f* A/ ^, U, e2 d6 ?

8 ]. R+ ]1 w% H& e4 Y% l
050433e4b8fe4f4d91de7eb85d5e6bdd.png
. u! _0 q- l' n$ I! T+ [

, _  \4 P; I$ O, }: s/ |4 ]9 {: z
标识符后,CAN 2.0和CAN-FD具有不同的作用:; G8 E+ R; T  B! b+ Y
% W( m) h4 ?/ C3 |: \
(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
1 V# Q. B2 L; [& ~( g; h
+ R6 I. j+ |2 D3 P( ]7 A(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。- O4 |1 O( i. S( ]4 y

& H6 w3 a1 @9 I, e/ n: \IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。6 c) B' o6 G; g, C( ?7 ^7 j0 G9 }

% b4 j) i# E; N$ b0 T( [与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:
, {% {! ]& }+ x/ t8 H- ?& V0 V0 }. @, H, ~2 p4 t- ?
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。5 v0 L* d0 K' r; \: G

- ^8 g( z6 g7 n1 D(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。& p) H* C1 @# Y' c4 u& N

0 j1 I& x& ?3 X1 M(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。0 k7 T! Z/ ~& r6 W4 d0 i% f( o5 p

" F0 P( }# x8 T7 T& k$ B6 v6 a5 y, f控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。6 W! K. A7 j( B5 A) u0 G: Z

; }# z  {2 s5 K. w6 }- M9 p8 w6 k/ N) a7 U2 t
c4fbc9fa3f184422a77784de5280382d.png
2 N& H" u% j& W- p7 E% ]

" Q# d3 \. R2 F6 ?: I4 n
0 l4 A3 L7 F% f; P1 |! P! o通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
" U- P  Z2 x. K1 Z, C" t" x, a6 K$ u2 A* W; Q
(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。* i4 u5 S( ^  r8 ?- e" S

5 e/ P( L) p) G% n5 _0 C0 \(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。
2 k. ~* C) x0 Z2 o) e, I% J7 D" |1 Q# u/ P; \
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。+ z  x, v; Y  |/ J: D% A/ v% z
3 \. Y% c/ G9 R% T4 o' ?- I, F

9 ~: u. I% q! r, y* _$ G/ B
a00dca8056bf40dc860b52366afa5197.png
! W! F! y2 s$ M  z; r

: P$ o3 ]  u0 e: z1 s  X9 f8 p2 j3 N$ A: s+ Y' O
91.3 FDCAN总线的HAL库用法7 S& l! q! s8 q0 Q' R5 q4 V
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef  w! n0 V% M) g# l8 _/ x" _: s
FD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:8 [! W' C0 X5 |* O* q& _! W
$ w" F- ^" w" R  P( x, V4 n+ ]0 \
  1. typedef struct
    $ d# h# u- ?' [9 k- K$ U3 g
  2. {
    + R6 _% j5 k0 k. ^# g+ i% v2 Q% j
  3.   __IO uint32_t CREL;   7 g5 ^8 _( ]" `$ s# i7 x
  4.   __IO uint32_t ENDN;        
    ' G& {" f. p0 l4 v! }* G+ x
  5.   __IO uint32_t RESERVED1;   
    + W0 Y% H3 v3 T2 d, ~) O) u; [
  6.   __IO uint32_t DBTP;        ' G3 H5 L% l9 j$ I9 i
  7.   __IO uint32_t TEST;        7 u  n+ j$ g" {" l1 x2 f$ U
  8.   __IO uint32_t RWD;         0 ^5 M9 _5 S4 ?/ Q0 i+ p8 U( @8 l
  9.   __IO uint32_t CCCR;         ! W' L6 e4 i% V/ a# X1 n
  10.   __IO uint32_t NBTP;         4 C0 N8 k+ @7 J5 ^; t. l# a
  11.   __IO uint32_t TSCC;         
    * e4 F- |) s/ p. j- L
  12.   __IO uint32_t TSCV;         * H* p* E9 _# P. \/ M6 c
  13.   __IO uint32_t TOCC;         / k1 z% i8 ]' a7 B
  14.   __IO uint32_t TOCV;         
    ) P2 T+ Y" u  L& h5 z
  15.   __IO uint32_t RESERVED2[4];
    * K! \  W' V  G: g, Z0 }$ F, {
  16.   __IO uint32_t ECR;         
    ; Q  r+ D2 k& E0 }- c
  17.   __IO uint32_t PSR;         
    8 g( L+ y7 X: {9 W
  18.   __IO uint32_t TDCR;         
    : @' d) |$ R" F
  19.   __IO uint32_t RESERVED3;   
    4 R7 l- _! v% i
  20.   __IO uint32_t IR;           
    6 Y8 h0 t2 n* O5 j
  21.   __IO uint32_t IE;           
    , V6 ]# `+ v( l$ }6 W
  22.   __IO uint32_t ILS;         . c8 C+ U5 T/ T; [0 S# Z6 V
  23.   __IO uint32_t ILE;         
    % V& Z3 u( _; E7 E1 g+ X; {- D
  24.   __IO uint32_t RESERVED4[8];! K/ O3 J7 O3 f0 j" q3 o) u
  25.   __IO uint32_t GFC;         
    & R7 ~+ I( w, p% x
  26.   __IO uint32_t SIDFC;       7 M& ~8 Y# f, V+ I% m
  27.   __IO uint32_t XIDFC;      
    , e! m* S" }, b& t9 X
  28.   __IO uint32_t RESERVED5;   
      _7 R+ `, u- ?/ [1 I
  29.   __IO uint32_t XIDAM;      
    2 K& I; m. {. V% o- [
  30.   __IO uint32_t HPMS;        
    3 O3 M4 x0 V, W- H6 H5 E
  31.   __IO uint32_t NDAT1;       % k* J" d2 a2 O3 q* I. J+ K
  32.   __IO uint32_t NDAT2;       + Y* B8 D8 K" z/ l$ X
  33.   __IO uint32_t RXF0C;        
    ) Y3 @' |& \" k( `1 C& z- Y
  34.   __IO uint32_t RXF0S;      
    8 p2 W  ~5 w. Y
  35.   __IO uint32_t RXF0A;       7 [$ C4 ?  L$ Q
  36.   __IO uint32_t RXBC;      
    / Q  K  B; ~  p6 K6 e
  37.   __IO uint32_t RXF1C;       6 j( m" R' Y; w( Q. }
  38.   __IO uint32_t RXF1S;       & S3 U; S$ L: X7 a& t' U! |2 t2 s
  39.   __IO uint32_t RXF1A;       % T4 c- X. L. m. G6 g: w( p1 k
  40.   __IO uint32_t RXESC;        
    5 c5 M: B) j8 }8 n7 z) V$ V8 [
  41.   __IO uint32_t TXBC;         
    0 N) k( l/ S+ Y0 p9 J* F& Y4 S) A
  42.   __IO uint32_t TXFQS;        
    - y5 H0 u/ z( S# Z2 K) u; _
  43.   __IO uint32_t TXESC;        
    3 p1 S( i# M$ D" L4 M7 x- {
  44.   __IO uint32_t TXBRP;        5 n) l' l* K2 F2 R
  45.   __IO uint32_t TXBAR;       5 h0 t+ H" J9 Z  H
  46.   __IO uint32_t TXBCR;        3 H+ H4 H; h9 X; h) M" W! H9 _
  47.   __IO uint32_t TXBTO;        ' |5 i/ u( Y3 h% D6 n
  48.   __IO uint32_t TXBCF;      
    + l7 O, Q4 [; g4 A7 e
  49.   __IO uint32_t TXBTIE;      
    - m$ \: M+ v; G$ J) `! e9 g
  50.   __IO uint32_t TXBCIE;      
    : M- t8 N! m! z$ t
  51.   __IO uint32_t RESERVED6[2]; . v+ R! ]- y: D+ O$ ~, i; {
  52.   __IO uint32_t TXEFC;        
    9 m0 p8 C5 F+ e0 [: d
  53.   __IO uint32_t TXEFS;        
    , c$ ?- P- Y6 B, l& p( o( M
  54.   __IO uint32_t TXEFA;        2 M1 l" \/ C  G% f2 \
  55.   __IO uint32_t RESERVED7;   + H# D3 O: o$ W6 N" W% _2 t
  56. } FDCAN_GlobalTypeDef;
复制代码

" b( s9 k! h. G& M4 R. a这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。0 [1 e, f/ w) t8 O2 [
6 K4 {; @( F5 S$ O' j3 A
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:4 v+ k- S, h4 H" k2 R$ T
3 ^5 P2 G" E, W3 z/ ^3 j% Y3 ~
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
      z0 J& e& p: b  p; k
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
4 s# Y! T/ v& V4 |0 e
下面我们看下FDCAN的定义,在stm32h743xx.h文件。
+ X5 ]; S9 Q. F
  Y5 U/ z9 M  N
  1. #define PERIPH_BASE           (0x40000000UL) 9 n2 D( Q% T( r) n! k
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE
    + m7 S) X( A6 t* G& X  b
  3. ' [+ K3 Q8 d9 o
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL), C: F5 L" ]6 [8 E5 s) {
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)+ M; R9 }" y, X7 U1 }8 a1 D2 ?$ ^
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)6 M7 m1 j1 b) X! s4 F. H3 ^
  7. # E- p& A; `4 u% q2 x: b$ K
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000% w6 s  a$ |# B
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)) n2 Y$ ]5 o6 u  z8 g1 j8 k  o. F1 G5 [
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码
& L  O, c- F0 h0 `( K* m
我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。) K; n' n9 i0 a

: @5 c! i9 T& ^( Z& z  s0 ~  B91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef
+ Z" R. _! d# b& C3 L  ^7 S9 SFDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
3 s. J8 j( X) W5 X. A+ h$ H
6 {. s+ ]/ Y+ n- m" @( ~1 U  e
  1. typedef struct
    . I* ?" y' T2 e& ?- \
  2. {* F+ I7 n8 ?. U) h8 N/ j" u% `$ [
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */) @8 O/ A& x7 E8 |1 G' s
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */! V# N& Y# `6 T- u6 O3 E! a; A$ @) V
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */  n( Z+ e) P! W9 T/ `2 ~" n+ H  @
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */
    3 L) D1 g" \5 F* W( O, x' g
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */2 o( F1 }1 O+ z5 |* x3 ^7 \3 O' Z
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */! m! j6 q% [5 O  B' E( L9 m
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */( ~5 r+ y* q* B8 G- X
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */
    $ m# E7 v7 v7 d& p# L/ c' w
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
    , S! k: U$ Z- X; O
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    , j  j( I9 U2 J0 A% Q% @: E/ C
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */
    : z" E0 m% _/ }+ L; }
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
    " u5 o4 ^2 \2 k: w6 P! R1 ~  F
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
    6 y* x4 }2 k$ L
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */) `/ c' [8 `- d# O% F" \3 g% N9 D
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
    - V6 Z* F" l9 a/ p7 i' Q
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    : Q8 e1 x6 y2 ~. g3 [: f& H4 s/ V
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */2 I, L9 }: s, V: c
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
    # I: M" E- d; L' j, o  y# g. s4 \
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */- r8 a" ?; {( _" V" h$ C6 C. Y. I) Q
  22. } TTCAN_TypeDef;
复制代码

3 x5 r& L* G* P4 k0 G7 j3 _" _91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef) b' R( F' t5 Y) L' A( s
下面是FDCAN总线的初始化结构体:
% r* W3 r' \' N6 B6 O$ _( W" w) u( ]) e9 p# H! h
  1. typedef struct
    # j* Z. e. {! _# R/ x8 L! G
  2. {: w% w8 i$ Z  D
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.
    ) H) }! e+ w* R9 i( b" v
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     *// U4 W/ F$ V/ ^. }
  5. & {0 f+ t8 l: ^: D. ^% X
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.9 \& R# `5 n3 n2 k
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */
    7 ~1 A3 c4 m8 v% u$ Q' m0 `
  8. 8 `# k7 j' @/ f2 J2 j4 l! k' t
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.! a7 Q. ~% p& ~* R
  10.                                               This parameter can be set to ENABLE or DISABLE               */
    & l' ~, |4 k  k# s$ f

  11. ) M2 O# K! z) a
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.
    1 y# w& }# H0 S: m
  13.                                               This parameter can be set to ENABLE or DISABLE               */3 v* G% G1 {3 J9 v7 ]! U' R
  14. ' @- D6 h6 h8 I# \: F# y5 o
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.
    - H6 e6 A. L+ ]! @: n# e$ N
  16.                                               This parameter can be set to ENABLE or DISABLE               */
    * V- a- B- W$ v9 y' z
  17. : Z- c% l! k: F! c% w+ V
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is( J$ `: A1 _8 Y1 T. n1 _
  19.                                               divided for generating the nominal bit time quanta.
      B2 \6 E; N1 ^
  20.                                               This parameter must be a number between 1 and 512            */
    " `8 i; [; `4 N$ G2 A: n& u

  21. 2 g: ]. b1 g# ~
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    ; f% T, \8 p# _" m9 l& T3 C
  23.                                               hardware is allowed to lengthen or shorten a bit to perform) G) k+ L( @. f
  24.                                               resynchronization.7 z3 ]/ @/ T. m2 t# h: e4 Q
  25.                                               This parameter must be a number between 1 and 128            */
    5 C3 e% k' A+ i+ s/ |4 }
  26. ( H7 z; d: s" K- Z! G2 d+ ~" B
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
      U: \/ L# J8 R/ M; V
  28.                                               This parameter must be a number between 2 and 256            */0 H; Z2 q8 x; E* f, Y1 ^
  29. % q- k% o/ B# Q  l: }& {
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.% u3 C3 v, f0 O1 b7 h1 @  Z
  31.                                               This parameter must be a number between 2 and 128            */
    * b& M5 A/ F. }  [1 k

  32. 1 ]2 u- k* P) D4 Z
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is7 A7 S" m4 L+ h1 {2 l
  34.                                               divided for generating the data bit time quanta.
    6 |. @( v$ {' }. Q
  35.                                               This parameter must be a number between 1 and 32             */: u5 Y5 j8 r% e, r

  36. $ F# C; J$ B& |  M9 [2 t
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN
    6 ?  C5 s) H6 Q
  38.                                               hardware is allowed to lengthen or shorten a data bit to& \2 x" x6 D# k' q7 ~
  39.                                               perform resynchronization.
    ; `, e9 Q: }8 R% o) w
  40.                                               This parameter must be a number between 1 and 16             */
    % v8 n) q; k& L6 Y
  41. 6 d+ S! }+ s' I: j: [% m; U
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.7 B7 j" P8 ~/ v' p# Y* I
  43.                                               This parameter must be a number between 1 and 32             */
    8 E2 b- o6 }5 y8 Z& ~& R8 e
  44. ! D3 R0 c  F# L/ i  _% g
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.8 d$ E7 C+ _( ?$ E+ d3 Q- c7 J1 k
  46.                                               This parameter must be a number between 1 and 16             */6 u9 ?6 z* K" ]" H& \  X- n

  47. 5 o0 K- Y) |9 k/ o) p
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.' _# ^1 S$ T5 z* v0 c+ e% p
  49.                                               This parameter must be a number between 0 and 2560           */) g$ ~& s( j5 H" x/ K. z# }8 o$ f

  50. $ O" w3 d5 o' m/ D4 ?: y& R7 S
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.
      N% K; y: r; O7 G
  52.                                               This parameter must be a number between 0 and 128            */
    2 Z" z% v' X" ~9 d0 E
  53. 0 C- h3 j7 h3 ~/ g
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.; v0 v" Z* D. y6 B+ h5 x- G
  55.                                               This parameter must be a number between 0 and 64             */
    8 S) P# ~! r% P5 U
  56. : N  B4 `) A% ~8 K& {5 H: i& `
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
    5 ?1 L/ J0 E2 h/ t2 d
  58.                                               This parameter must be a number between 0 and 64             */; f+ ~0 |" P# k

  59. " w1 h5 @9 x4 R6 x" c" m/ @/ [5 {2 u
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.: u4 W, f  G  r+ N( T) Z
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    . ?  Q' j, |$ N; J
  62. 7 E, {% ]8 o1 B+ Q6 ~  T- F$ z" p' {
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.
    % _7 u4 B2 _) s" y$ `$ f
  64.                                               This parameter must be a number between 0 and 64             */
    0 }* ^  Q! v; c3 A+ u- [/ K$ d7 u

  65. 1 P& Y& H# f7 w
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.% G; U9 T, B) C. }* A( j& a( i
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */) @& E5 C7 y. R
  68. : {8 f! m2 L7 H9 r2 J- J
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.
    1 c& _$ _* T. Y& ?' b, |; `4 g* U
  70.                                               This parameter must be a number between 0 and 64             */
    $ I3 I0 ~2 l. l8 E% v  e- E8 c7 f

  71. 9 [+ X* ]9 j! X7 y
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element./ K, h0 v: C" N8 v- Z  d
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    4 ^; u1 V" |% M: ?" F9 V
  74. 3 s# E5 o7 r* N; H4 U, r& t1 g
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.9 b8 M( u! v/ ?8 {# o4 `1 z
  76.                                               This parameter must be a number between 0 and 32             */6 E* h; a) ~$ I1 H

  77. 2 L1 R  Z$ L' @% o+ w  t9 L0 j
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.
    6 P' c/ e, j9 N% N% W
  79.                                               This parameter must be a number between 0 and 32             */1 f6 ]: e3 G9 V0 G6 T

  80. ' C, ~( c, X4 E- U
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.$ `- W8 N% Q$ U  R
  82.                                               This parameter must be a number between 0 and 32             */4 Y6 @5 m4 v- `
  83.   U4 g! b1 q6 Q4 q
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.; [! u6 v' \) ?  ]7 g$ V5 q' j$ _
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */: ]+ i, n/ U$ G% b; S
  86. % W7 y9 N1 }# G# B) Z! p( g# e8 m
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.  s" n0 m( ]+ V" D; {1 J0 O" b
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */( {5 `% [6 \3 J  \$ [4 C: g

  89. " n5 j% v9 s2 G- d
  90. } FDCAN_InitTypeDef;
复制代码

+ E- C% \+ V2 L下面将结构体成员逐一做个说明:6 \! }4 X3 y2 c! t
$ l8 n6 K! o' C% @5 G3 b
  FrameFormat' ?; ~& c2 e2 H! p& V+ I
用于设置CAN帧格式。/ Y$ ]/ R  m& k  O
/ Z) W  m& U- i$ p5 ^: p% h
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
    + C* J! {3 E: l% |6 Q! ]
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */! H  k8 D6 I7 \& E2 ?/ A
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

  x) Q- l/ F& K' U& K  Mode
6 ~5 v5 B5 `) G3 ]* w& h# h用于设置CAN操作模式。
& a! B2 O4 o# T6 T* E0 {! ]) D, Z3 B- n' P: q6 ]5 {/ @5 I# v
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */
    , E- K; T/ |4 W
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */
    % \  J& o* v6 r) g5 [/ O2 D5 O# S  `
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    + k# _5 h7 j& i( w9 o7 Z; M
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */" ~3 {# X; r/ y. l
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码
4 c& ?9 f) t" A; l
  AutoRetransmission: }) R/ a; `5 U" d
使能自动重传模式。# ^- i1 {9 F" o( z0 c& W6 M

* n  j/ r$ L3 A/ {# Q使能ENABLE或者禁止DISABLE。/ }4 a2 ]6 `: E  C- y1 C  F. c$ {

7 @* z5 Z3 T0 E& W: B& c  TransmitPause
) p" Q+ X8 p: h1 z4 ~使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。4 r8 Q8 ?) \+ V& ^, L; o

5 Z- F  n3 y6 Y3 g) x- v6 _  ProtocolException
1 ^4 y* Q& x/ l% J) S7 }6 K; Z* n使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
) K0 M8 D/ E) U3 u1 p& }+ o" O7 m, X( s/ Z0 D
  NominalPrescaler& I( Z9 {* e; D6 d6 B% k+ J
用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。
$ R, u4 G; _) b) X- i; ?( w3 n: B. G1 I- O# n# S2 `2 w
  NominalSyncJumpWidth0 e; U0 K+ U- @' B) Y, n7 x  `! L
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。) W# o+ |7 I5 M7 w+ N9 M' M4 M
# V" J. i- J# k& X8 _) j
  NominalTimeSeg1: J- p, g: {: a3 M' ?8 h
设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。% `% |& {- y2 q3 P

( A+ {; r7 s( c" K$ s  L* O  NominalTimeSeg2
$ u* F. b: F9 O/ o设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。, D4 t' I% x2 ~
1 M' L1 Y  p5 e/ c* S# [
  DataPrescaler
0 [8 p7 C5 i& X: X4 X7 w- W# c6 J用于CAN FD数据阶段分频设置,范围1-32。
$ Y# U; i' @2 P) O
0 s3 s: h% X2 ^* X  DataSyncJumpWidth
. s$ B/ j& g) g# F% q设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。
& P0 E$ W# _/ c; C4 s8 k; K/ W7 M- z# o! G5 H
  DataTimeSeg1
. T; V! h; A' ]. G( \' Q8 C设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。
4 w: Q% u, B5 i" I) G# C( Y/ w* n+ a1 V; T5 ~% h+ J2 @
  DataTimeSeg2
: S! s2 y: p- s& v1 }/ }# e设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。0 |( p% U. E4 a8 p. M. w; J

+ D% K8 N% |9 }  `: `5 V  MessageRAMOffset# v2 Q; U- k9 E! y" R4 t# {
设置消息RAM起始地址,范围0到2560。
: c4 d; j* k/ p" \% C8 c8 q' e
0 D$ i- w' E0 d0 k8 r# E) n8 y% e  StdFiltersNbr9 J  o- A* o  q6 Q4 p3 k
标准ID过滤个数,范围0到128。  t0 }: o0 {) H

7 C% P  g  ]5 ~+ `# V* G  ExtFiltersNbr
7 c0 P: P! A  n扩展ID过滤个数,范围0到64。6 Q* k2 g5 D7 W. \( D2 D" W
8 [( u. T2 T) z. M' ?$ S
  RxFifo0ElmtsNbr* [# Q* U% G) n
RX FIFO0元素个数,范围0到64。9 S: Z8 T/ v4 E# r( C0 ~
) P7 `$ P  E' ?. Z& Z
  RxFifo0ElmtSize
, Y. b, S7 A8 O- ^3 O5 {RX FIFO0每个元素中数据大小,支持参数如下:$ G$ a: ]' a3 q0 P) n

( l4 r( s# z1 U+ ^' K0 h3 ~
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    * P6 p; y5 y7 X4 ^1 Y6 }
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */0 z) G/ y! s7 s$ d: d
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */' z. _8 U* _2 s" V8 U: V( ]* S1 Z
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */) l( _; D5 b  m! m$ t* k5 v" \* t
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    ) [7 |' t$ ^7 O9 I1 q' l2 v
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */; B5 ^& c4 N8 A$ J- `. E
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */8 F+ H( z; \. c' c2 C5 i0 Y
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
7 z2 w& e6 {+ t. M+ G6 ?& e
  RxFifo1ElmtsNbr; W) D' x$ ^5 p  l5 A
RX FIFO1个数,范围0到64。
8 {' s. I3 _5 W+ m
( G# a9 o- j! G+ A7 T/ ?  RxFifo1ElmtSize
0 w0 ]* u& A/ u; |; Q9 o" ZRX FIFO1每个元素中数据大小,支持参数如下:
( g8 e0 U9 l3 _' _, J3 |; l+ @) q* _7 x( F3 }
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */. o* S3 L; b! z9 M: D  v8 \( e; `
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */' l- ?, H6 X7 S  g
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */7 ~9 U$ e! ^0 R! e6 O& g
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    $ o3 S* j5 ~0 f. x! l
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */7 G6 a4 b; U; _0 r
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    9 J0 A5 l! D: b, a' O
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    + s% y% K8 Q- D/ D, G3 l- F
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
; @" s3 Y* N9 b$ s: D" b
  RxBuffersNbr
( U+ C. @5 v; p( A设置Rx Buffer元素个数,范围0 - 64:
5 N( k6 d0 m. j4 V$ P: ?9 X2 v  B+ J9 z! t7 A
  RxBuffersSize* \7 p, P5 |/ k. }" h3 U6 ^# ?; N4 K
设置Rx Buffer元素中每个数据大小,范围0 - 64:
% d, w8 ^, v8 t( l; U9 M( i% h6 H
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */" q' W( t' n1 `4 d; D
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    % _% f2 B2 Z8 ~$ O3 y
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    3 z& q- d( |1 W
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */' `8 ~; P& `- S
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */7 \) O9 q$ d  `# O, g3 `
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */" j4 z, w7 m7 C; w# |. \
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
      r# i% w  K  a* T& p! {9 n, _& U
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

4 E  H1 {$ F7 e9 @6 r  TxEventsNbr
4 T2 x/ i) U. K: YTx Event FIFO元素个数,范围0到32。
" A  u4 `$ v( p% c2 @9 z" Q/ K, E+ ]; R4 u& f, h
  TxBuffersNbr: M' Y! Q2 M( n! m; s+ D2 c
设置专用的Tx Buffer元素个数,范围0到32。- N) G- g; i! @
- v. z  t2 a# y  T9 _1 B" n
  TxFifoQueueElmtsNbr1 _4 @2 x! Q; f3 j
设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。
: `+ t: _" Z" q* Q1 b3 m; l+ D( x
7 k6 o! U# z  ~! t- E4 T( m$ ^  TxFifoQueueMode3 n" r! Z, u+ r
设置FIFO模式或者QUEUE队列模式。$ L: F; A9 f, [: B5 x5 Q
' Y2 u- {* y. C1 |
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */. T5 B6 B5 g) O0 V+ p; B3 \+ [
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
# L; X- G/ q' i* B( o! F
  TxElmtSize2 g8 C" p; y7 [& [& q- f/ J4 R
设置Tx Element中的数据域大小。支持参数如下:
5 \8 k7 _0 C' t% w( p4 O, Z, y
2 D- |+ i+ v- W. g
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    4 s2 w8 K; N: w: S  O2 G
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    9 }5 g, X1 q) A; v! h& x
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */* n) r9 L6 o" T/ a
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */1 @# m! i  e; v' S1 n- r0 ?7 G
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */9 Q% k8 l3 z. u
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    8 N4 l9 j1 h  d( T0 g" \. t  m
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    1 B9 q. o: T* K: w& f. R
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
1 ~7 J" A5 |. M8 k1 A# j* V8 G2 M* ]
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
/ n1 ^& V3 X# P; Y; ]下面是消息RAM结构体:+ x* _7 ^  v) y4 i

  1. ; M% ^3 i0 s2 Y: j* t' U
  2. typedef struct
    ; k( F/ V5 j0 e
  3. {
    ) m! z1 Z9 y! ]9 \" d
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
    7 }9 A1 F2 N8 C. v2 _3 g, V
  5.                                   This parameter must be a 32-bit word address      */
    ) t( c4 J" D7 B/ C; j; O

  6. $ U- j) W! w' S, h! R9 T
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.6 t% i; y* v2 X8 c, b& ^
  8.                                   This parameter must be a 32-bit word address      */. X# i8 R$ V5 s, H6 T$ T8 d

  9. / r: x$ Y* ^) m# a
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.0 v. H& x7 Y2 v7 Y8 D7 G
  11.                                   This parameter must be a 32-bit word address      */: @8 Z  Y3 I' n3 w0 v+ O
  12. 6 z4 ~. A$ F1 h2 _# H4 E: u
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.$ {; v2 I5 Z8 [, k
  14.                                   This parameter must be a 32-bit word address      */4 [/ @* v+ P! d4 T  b1 N" \

  15. 9 Z, `' B5 U2 @7 b, N
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.( n2 _7 A' W" x) z! s: Y6 v- j+ n( k
  17.                                   This parameter must be a 32-bit word address      */
    5 g, a! W2 J* L/ K) W
  18. ! j) h* r5 [$ r. p4 a* _
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.$ g$ @, S" k! }5 A: X* ^$ R6 x* ^) k
  20.                                   This parameter must be a 32-bit word address      */+ P) h* b! e; @- o% U% @6 k) `
  21. 8 z/ x2 p% j" \2 z9 Z* A* j
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.
    / p8 `9 X+ y. a+ j: p) E( I' r
  23.                                   This parameter must be a 32-bit word address      */0 A1 w( |5 a: y- v4 y/ E

  24. ; m0 T$ |9 z  w, N1 S$ U! A! r
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.
    / t$ N* F% G5 z4 y( }& \! z
  26.                                   This parameter must be a 32-bit word address      */% m3 q# c; |+ _! @& W* y
  27. 9 g" f2 m9 n  {% s
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address., M* I0 _' q2 [4 N1 C
  29.                                   This parameter must be a 32-bit word address      */
    . {8 A1 H' C* v& ?
  30. ; i& K- f$ ]6 r+ p0 @( E# V
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.; i/ E' D' C: e7 N; D  g
  32.                                   This parameter must be a 32-bit word address      */* z2 w" Y) J% r1 g7 R3 n: z/ b, {

  33. - m* s8 n' s( R. c+ b( l
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码

; o/ K) m, D; ~/ X下面将结构体成员逐一做个说明:
( B% A6 A; d6 L4 o/ w- @4 g$ C1 J; V9 c5 _  U+ y0 o
  StandardFilterSA
% C* K! D6 p: |) r) @' n设置标准过滤器起始地址,必须是32bit地址。
3 d9 W7 T& p# ^6 D+ T' v
6 _/ ^" H1 l7 {) ]! P  ExtendedFilterSA
% {+ V8 ]  l; ~' |; k设置扩展过滤器起始地址,必须是32bit地址。
5 P4 H, i+ Z, }" N0 I; T4 \7 w2 C; U6 c! Y
  RxFIFO0SA
- U/ _: L8 f6 Y( R9 b设置RX FIFO 0起始地址,必须是32bit地址。* c5 R/ M/ e( ]' Y' M. I, r

6 x4 V8 O( r) A- C! f& C7 c  RxFIFO1SA
0 r. A2 y) l% q! ?设置RX FIFO 1起始地址,必须是32bit地址。+ v5 \1 U: K1 T7 H' w( D$ E6 x

3 l$ v3 V. g/ b; l  ?# ~9 M0 S( F  RxBufferSA% v/ Q3 |) p6 d: X5 D7 M4 _( m
设置RX Buffer起始地址,必须是32bit地址。
& j0 m( g1 L% @5 F# G3 i
( C$ J! e: o! P  TxEventFIFOSA
; G2 f3 Y9 ^" Q8 W, d( c+ R设置Tx Event FIFO起始地址,必须是32bit地址。7 [8 V3 z3 |0 ~# p" ]5 Y% a3 _

" @/ X( h8 u  i, ^, a) ]+ @( y  TTMemorySA. [4 h8 D4 w# f, f2 b; B
设置触发内存起始地址,必须是32bit地址。- n# t& P7 v1 p. s# j4 b
9 w. f/ v+ U9 Q5 A; g/ h
  EndAddress. c- P% v; j0 }# X  c
设置申请RAM空间的结束地址,必须是32bit地址。
; i7 O6 K% _, {: ~1 C) Q3 l; I+ O  X6 y4 u3 ?% D" [  R
91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef
' l0 v9 [8 }7 [' I; v2 g下面是过滤结构体:  X% u. I5 u( h; o- u$ q7 M

5 I  N% |# v$ o6 D9 _
  1. typedef struct
      a! i3 h1 Z% R! o* ]- r# P: k% g
  2. {
    & ~# u- H6 q3 |9 l+ M! x
  3.   uint32_t IdType;           /*!< Specifies the identifier type.- }  V  e# J9 n
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */
    4 m& D% J. X+ C

  5. % J0 q4 D" k) d% |, g8 x, e
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.3 K# l7 i" B* v: p5 s0 P1 ~
  7.                                   This parameter must be a number between:
    / a4 @" B4 A; K# Q- X4 Z  l
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID9 o/ ]* w% r' F4 |
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */4 m9 H; c5 n2 X; K' d: L
  10. / b* u( g( O7 C- {$ J  E
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
    + f5 n4 y0 U# o1 r
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.9 ^* Y0 c+ p, u1 R% y# e! ~
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted
    " ]- w4 f6 K* k" b3 \, Z4 p
  14.                                   only when IdType is FDCAN_EXTENDED_ID.5 S" c* n, I- O0 p" n
  15.                                   This parameter is ignored if FilterConfig is set to
    7 G" D* g2 H/ A' y
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */
    * z9 o& i7 ?/ q7 f( R
  17. 9 o2 Y+ q6 t2 _; q3 t+ |' b
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.- _1 A6 D! o- P
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */, Q! D5 |3 r* z2 v
  20. ) I9 |, t  E1 H/ @. b. d  u
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.
    + u) L/ v, w  ~! U" H6 a
  22.                                   This parameter must be a number between:$ p) l( @3 v$ A. {( T0 m
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    2 _# G5 o- d& k' A( U2 r: ^
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       *// G0 I/ K) L# c7 Q0 u3 ^
  25.   U" j& @# g! |, J/ a5 J
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.3 F1 i- [7 Q" x3 R
  27.                                   This parameter is ignored if FilterConfig is set to
    2 `( M8 _5 M1 k) D; N
  28.                                   FDCAN_FILTER_TO_RXBUFFER.  {! b9 y  y3 \; K3 W
  29.                                   This parameter must be a number between:
    / @/ z/ K9 X6 x" G
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    1 a% s% O! l0 A7 a2 o& A
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    * G7 T6 @, O; o; b' O
  32. ' f0 C9 _) @) a
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
    . L9 K$ D) @; P
  34.                                   matching message will be stored.
    1 l: c7 X- `5 Q2 i
  35.                                   This parameter must be a number between 0 and 63.
    , w9 t0 m. [0 s1 ?  {
  36.                                   This parameter is ignored if FilterConfig is different
    ( G6 C  Z' F9 c" i6 X
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */6 s1 V( \; a8 d& R3 ?- A+ U  J& x8 ^- T
  38. ; m6 E7 V4 v2 D
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for# P- o0 w  R# H/ ~( r/ V
  40.                                   calibration messages.
    2 n; L* W) g; ?" x, D' M+ _9 J
  41.                                   This parameter is ignored if FilterConfig is different/ U2 f  z" }9 }
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.
    + r" Q. m6 W% C
  43.                                   This parameter can be:+ ?% e, R2 \6 o
  44.                                    - 0 : ordinary message* p( g4 \! M4 g8 s; i) o# y+ K
  45.                                    - 1 : calibration message                                */2 P9 \% ?6 n) a- l' m7 k% Z; ~/ j
  46. , r4 Y1 t8 P7 m6 K! Y2 s
  47. } FDCAN_FilterTypeDef;
复制代码
7 T0 B- }& U' J7 ~2 @8 `
  IdType
; K  W, J! Z  p+ c用于设置标准ID和扩展ID。
. b% m: U( ^0 `( O! V+ z9 {( ?$ M6 g* Q3 E# U
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */' B# y6 T; u% X& k
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
! L# L& g, V3 r9 O9 }8 V
  FilterIndex
% \; \3 n, u5 o9 h( `/ n# r9 \用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。
6 |& R8 _3 z! Q- l& {7 t# s# s* x! I# U; g8 t' s
  FilterType
1 b* }5 D% Y, f* A用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
  t. `7 h2 o, j( F4 J! {; ]3 J! }: ?! E+ `* n' n1 V+ _
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */
    8 }2 A  b/ i( J8 [5 M( h: I1 O1 z- v
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */
    % F$ M/ s+ z2 @% S& {7 ~

  3. * x1 ~4 @! d& b, E
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */: Q+ Z% s2 D$ g3 i+ {- B' N
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)
    " L0 ~3 X# ~9 y$ u

  6. ( z: a% d8 F/ d( ~- K
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */
    & |# H2 L- c, u& }/ @* S$ X/ Q
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

6 z7 X3 H4 Q: x" r) i+ N; q) i  Q- G3 L  FilterConfig- @) y! b  C0 g; p. Z8 ?
用于设置过滤类型。
) c% T0 O1 g/ f3 T; S- n/ f
8 m6 R! [+ [( }' d' o7 |
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤
    % A6 `9 b' T4 F  N2 Y
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0) x  K- U3 V" O0 z* {" B5 A
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1
    ) o: q) S, v) `/ h# t. U" ~- [. e
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID
    % T7 }/ Y" s( U2 A  h2 w4 N" f
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
    7 B8 }5 |* O! Y" `. \0 V
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
    9 P7 J, L9 R& w- d: B' J
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 15 ]0 R/ p1 l' ~
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码

  E; v' X- w- h" y7 s# E% G4 x1 }配置
" M; ~/ ?" B6 g- G7 G0 j2 v8 N, K& V) e  FilterID1( l7 M7 u; {8 f% e
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。% O  V& j7 q+ b$ D, Y" B  R( t

% A1 X/ |4 M. w3 W  FilterID2
& m: r7 z3 h! q7 L4 j  }" N用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。
/ v' C1 P: w; H$ u. L6 |' ~
$ ]' j2 E- N: M4 N- I3 [  RxBufferIndex
" V/ r% N" P9 @' m1 P, Z: G$ j8 _匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
5 G8 N$ v2 x+ ^) m. d  o! ^, ~9 f5 h$ ]0 t4 ?; L* E  P
  IsCalibrationMsg
9 K1 u9 R; Z* J8 D3 |6 n# ?, T用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
! H2 D- \: g3 p4 M) L
5 K$ N/ }% a1 M0 : 表示正常消息。
! {$ ]% D$ t' S2 _) U. ^& X. b8 P; o" b/ I7 r1 D
1 : 标志校准消息。
+ r0 F' y0 B8 Q+ Q
  U5 n# N1 i" [$ f# `  O  x91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
- P* v: N0 x; y  i: r1 F下面是CAN FD发送消息结构体:" a% G& F6 n0 L  P
$ n, W  u. V% G: r- _/ o% ]
  1. typedef struct
    6 r" g$ o) _. K$ N
  2. {
    ; V; C+ Z- C# ]1 @
  3.   uint32_t Identifier;          /*!< Specifies the identifier.
    5 @! C3 E+ V$ Q2 b. o7 R
  4.                                      This parameter must be a number between:
    8 C5 W# Z( ]- [
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    3 `: ]! B) g" _  q6 ~1 i
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */% D. E; t; {3 }

  7. ( J8 M; l+ o8 _* m
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be
    / [( N  @0 ~  F$ m* _3 k6 c
  9.                                      transmitted.
    $ a: Y3 d( d: ~7 N8 J4 S4 G
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */( ?1 Q6 K& l* c# e0 T4 Z6 o$ z; x+ J* ~
  11. 6 V  G6 ^1 b4 b8 y5 C8 _1 E, k
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.
    5 F4 g, ?3 ~! b# n' O! Y
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
    $ `0 J/ c# p* c1 r9 R* b' `

  14. * ], [  r1 [5 X4 z; k
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
    3 U" R7 V% i1 B6 _
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */- e( Z& q3 H* Q' c
  17. 9 o7 `0 T. S4 j, j, k, b
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.
    / S1 k8 h1 b7 h6 C$ G! s& z6 j
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */
      t1 m4 ?2 G, }) g3 L

  20. $ i3 g3 a* P7 X1 O0 @
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without: h$ N( W/ M/ f/ M( h4 J
  22.                                      bit rate switching.
    9 S6 h5 ^7 U. R! v6 a# F2 k& T
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    " P- q6 n/ g; c
  24. % e/ |% \* a( I1 Z6 `! d
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or
    : \) W/ K9 o& C# H
  26.                                      FD format.
    / g5 _3 S  F6 S# t/ ]( B$ Q# n# r: t) _* E
  27.                                      This parameter can be a value of @ref FDCAN_format                */6 P( B; \) r  ^- P" v
  28. ( f% ?) z$ L- d% w' D5 n0 f( T
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.3 j: d+ U& F  Q0 @. }
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */+ j4 z# v/ l% P5 [2 H. j
  31. ; {. \) t1 w3 c8 s& I7 u! P
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO# q5 {% F6 E' Z
  33.                                      element for identification of Tx message status.
    # P3 R! g2 Y, X' h/ F
  34.                                      This parameter must be a number between 0 and 0xFF                */
    ; Z/ L' g0 I  ?8 y# S

  35. . z7 q. q, B" S6 G% s; F0 ?7 a( |
  36. } FDCAN_TxHeaderTypeDef;
复制代码
' ?1 B" e( `8 r$ N) q
  Identifier' `1 j/ w+ C3 M7 m# F, |7 `6 u
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。. [$ |1 n1 ~$ M7 v: z! ~
: `, W% p8 p' f
  IdType0 O% s/ R, o( s) G+ h9 W, L+ `
用于设置标准ID或者扩展ID。
) c+ u$ V# b) c& O2 T9 C2 h# H( G* V: r  `7 S
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */6 M- R# V: q' E" ]4 O+ A+ i
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

, Z3 Z# k' Y  _5 o2 @/ q# @* t2 A  TxFrameType
0 b- d2 W) E* C( H% B; L# b4 v/ ]7 e用于设置帧类型,数据帧或遥控帧。
/ B8 C, i7 Z; d8 a3 |/ z3 }" |
% A8 {* l% q: }) }' `/ R
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    ' d- D2 U3 d+ [5 F" D
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

/ H4 L1 T8 {0 l; i6 X6 }! {, \  DataLength& T" V. n4 t, x; s
用于设置数据长度。! r5 Y$ N# J; G' M6 \

6 E. m1 T8 m! z: ~  c% w
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */4 ~' X  \0 o9 F5 r
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
      b6 N& D8 N0 s, `) Z
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    & s# [+ w/ O9 B  ?% r7 J! z+ u
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    , E) L+ F$ h7 }
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */* }$ ~) R( R5 a
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */* ]  `" G$ l5 E6 D
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    5 H# G: I  w$ m0 [
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */, D3 G; `  V2 ]2 _* G: m5 h* ?! o
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */  _. Y9 r9 }. v- x1 t; e
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    1 u! w+ L8 {# S
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */7 @; M4 ~0 o+ B% u
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
    ( E2 }# ?( n4 f4 V
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    - }8 |& y) g' S: |& c3 R; b
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    , G# K. P. h0 I9 C$ ?. |
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */
    $ c# ?2 ^& U) @) m- u0 [- y
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码

% ]. }6 ?3 I( [; ]. m6 H5 E  ErrorStateIndicator7 K- s  m* K) m; f; L
用于设置错误状态指示:% a9 ~, x5 `: b& P7 y
% B# n3 i1 O6 a1 q0 i
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */( O- s% d! T4 M0 d) z
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

. L% ?6 ?* O1 K) v0 W5 r7 Q1 f  BitRateSwitch5 O6 G% v1 s. V
用于设置发送是否波特率可变。' @% A/ M9 U5 h. J& M# w
6 c: i1 B  `0 Y8 w. W
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
    1 a; T) u9 \+ A& X" V4 `
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码
: m: g9 Q$ A% i, U3 U2 @
  FDFormat
' @" u: L3 F2 R- L& O" g用于设置发送帧是经典格式还是CANFD格式。9 D% x9 K- u$ ~' H; N

  1. 6 m1 c5 l( l! O! |
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */4 J, s; [6 a5 T; ?
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码
7 e  O* _7 u' b: J  K4 S, v/ z# ~
  TxEventFifoControl! z' N/ x1 s7 u3 L, s; C1 {
用于设置发送事件FIFO控制。' _2 F$ k/ z! f

- c+ o( s4 a% f( T
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */. N8 @2 ^8 a; C1 g
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码
' g# B5 p. c5 |
  MessageMarker
$ k" c* d3 [0 p: ~# ~8 L用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。
8 B9 m- v* x" o" T: I
0 }6 X. o& }$ |91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef
8 o& ^  b2 _8 }4 ~" e2 Z下面是CAN FD接收消息结构体:
9 V- o* @$ k9 @5 y. ?, v7 ]
0 J' q8 t) z$ `0 {' k
  1. typedef struct
    % w& Q/ l0 V- C- o) x0 p
  2. {% w8 ]' v7 K, l" I) I
  3.   uint32_t Identifier;            /*!< Specifies the identifier.
    ' z$ W" k' D  Y
  4.                                        This parameter must be a number between:  A3 s/ J2 s& i0 d9 M2 S0 ^
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID# W1 w) O6 [% Y
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    : s& g# E- }& w

  7. & b" ~- y4 u( @* U9 Q. q
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.; d" Z1 P4 O3 v8 S( i+ T
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */
    7 I% C! S# N( n& J
  10. 1 P, d. }1 j" }+ b. z  N$ Q! j
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
    5 l/ a* B4 I/ `
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */
    ! H9 X  a4 d8 ~( Y7 z, a2 P

  13. - K2 ^' o) V9 |9 B8 P& P
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.
    4 i/ _% q8 Z( \) n4 d+ d+ z) Q  U
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     *// C6 j' k  F5 d, i+ G9 _
  16. ( k( h/ A2 O$ h. B0 }3 @9 ^
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.6 w: c. D, g' s( h% E* k/ d
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */) k1 v0 O3 {( Z# W+ \# n8 R
  19. $ i( F# |. R5 @, B! S4 L
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit
    # Q) I: ?/ a+ w2 z
  21.                                        rate switching.
    ) T, V3 J) n. z5 g
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */1 D/ X& Q& M" @: k8 d
  23.   g% q9 J+ |$ `7 \8 d
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD$ L" a4 d- s1 }* P; e# H
  25.                                        format.
    ! d* F- T  Z! ^7 d: L
  26.                                        This parameter can be a value of @ref FDCAN_format                */+ x( Q6 q0 U. v- X& W
  27. 1 K5 O4 }. C9 F( a% T9 n( v# `9 S
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame
    8 G, c9 r. e; K/ z6 d- w
  29.                                        reception.
    $ s* u! Q  _: p& O) |# d) ?: ^
  30.                                        This parameter must be a number between 0 and 0xFFFF              */
    ' F. W7 ~. o1 U0 C

  31. ( v8 a0 T6 o6 f% D. z
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.5 f# T8 N( g8 }2 Z( H/ B  o
  33.                                        This parameter must be a number between:6 d0 G3 U- b: G4 g2 C( s. p/ p
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID
    8 t5 |  O* d6 A9 E& y+ z
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */
    + r- O$ \8 e  t( U2 q
  36. ' z7 F: U0 O- G# D, F
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    ; A- c3 F6 w2 j# x* G8 ]' |0 H
  38.                                          Acceptance of non-matching frames may be enabled via* c: Q! S* s: B3 G, I$ f6 c
  39.                                          HAL_FDCAN_ConfigGlobalFilter().5 N, o! B9 E5 F6 v' `2 F: ]' e0 _
  40.                                          This parameter can be 0 or 1                                    */( r2 v' r3 ^, t* h

  41. * f" _5 S3 L; ]& X8 B
  42. } FDCAN_RxHeaderTypeDef;
复制代码

/ i7 O1 }9 m9 S- Y  Identifier$ I( _  q# a& r
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
- W: Q& X! Q& c/ g( W& F* G
1 b% w# g3 z0 u5 K+ e2 B  IdType
$ X# t9 K+ x2 @1 K用于设置标志ID或者扩展ID。2 z* o, ?3 A% i- y+ g4 g
9 p4 M: y* I& ~( z0 c' F" F
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    ' |9 Z- z3 M. H' O' ?9 r
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

/ a2 w: B5 g) p7 A* Y- O7 i  RxFrameType
$ Q7 f1 R$ y$ B用于设置接收帧类型,数据帧或遥控帧& ]4 |+ \' J1 u3 S' y  u. `: j/ `! _" i
3 W- B) J% k3 h8 w* ]
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    * f6 I1 C; C" X. d
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

; q" K% o# y" z: r/ p& n% L  }0 Y  DataLength3 n$ o" j2 S+ A* v9 s
用于设置数据长度。! T* o( `$ w5 x' i: _% _8 |

4 i& s( D0 G& y' J. {- d
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */, _9 v& v+ `9 O6 D( ?8 B
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */7 T5 X9 P6 o$ g$ @' j0 G3 s
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    ; @5 ^) T" S, w4 r) ^
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    " o, a5 P% U5 }: P/ e& Y
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    . g% P  j- q6 I) E. l
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */3 Y% |- X/ }; z: E
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    3 w/ p) f' j# s$ R. Y# _
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    0 A- J4 f" I3 @/ H5 u4 i7 s
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */+ w1 m3 k& c2 P& u- S
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    * T2 c) W$ e6 S
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */* k& H$ s% N, p& a  D( H
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */- K% k# O% W, d, y! E( \- y
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    ) r6 ]' T$ M/ N& u9 V: `
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */! l/ u6 f& x6 y- m+ l6 Z
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */7 m$ z9 n! }+ A( e: F4 s9 V
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
    3 H$ T. v( t! }7 C7 a- ~+ N
  17.   ErrorStateIndicator
复制代码
! }* H( ?/ q( z! L' v
用于设置错误状态指示:0 Z; \# q6 n2 ?; x: o/ d: v

6 J( e( Z# p5 r' x$ Y7 n( v, S
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */' I3 Q6 s8 `' T4 J; y0 i0 p5 n* O
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
- ]6 q8 N2 R. ^
  BitRateSwitch
% S1 E8 z  E% f6 O# o用于设置接收是否带波特率切换
" R1 F0 N3 g( t6 Z' s( g8 \& W2 S- d
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
    " K8 G7 E8 {, [8 R
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

2 Z/ f0 U- F! ]' @0 I  FDFormat
8 z0 U& o+ k$ J( [5 ?& F用于设置接收帧是经典格式还是CANFD格式% [9 U  a  F/ M0 z  ?

* z- L8 ~, G3 f" w
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
    ! s' x2 n& t. q" {
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码

! [$ A5 P1 X. y9 Y) J: d  RxTimestamp5 W8 V. E: I0 j& f
用于设置帧接收时间戳,范围0到0xFFFF。   0 D3 x3 f! F, {+ S2 i
$ s' I5 p( m4 H& L; d7 m
  FilterIndex
. m+ }- s9 D/ I9 u% x) p- w用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。 1 ?: a: f/ a8 d( e! ?. g* f  D
* L% D, I" M# `" R: Z9 n7 e
  IsFilterMatchingFrame& U% `. Q! l4 v- X2 M
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。$ ?& v6 W/ X( u. w* K! t( H, W0 D8 R
. |$ U5 u8 R; f; R1 _% d2 y
0:表示不接受。) x: |; q: u0 j$ R4 ~

% N5 ~6 Q+ n9 I7 m# R: }: D1:表示接收。
1 C2 w0 b5 E- q% R( _& L$ e! d* o/ i6 m9 i/ w
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef0 p& K) a+ ^) T8 i
下面是CANFD句柄结构体:$ v9 K6 m" q4 ]  i" c2 @  h& X
. q  ]& h& |8 _" ^9 K% O
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 11 m0 \; w) c9 n
  2. typedef struct __FDCAN_HandleTypeDef, [( c+ Z; t. `) w% G
  3. #else
    2 d/ e' Q. N4 B& v$ e
  4. typedef struct! E- O3 l% r/ ^- P
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS *// |+ _2 v) h/ {$ M3 @+ W
  6. {
    0 M7 C, P2 [2 I- R9 L8 u
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */
    ! G3 w' B) O/ M' D
  8. . ~- s' E/ W( g$ z
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */4 @6 r; ~4 e2 m6 N2 W

  10. 3 K6 J+ W; ]( o/ G8 c4 N
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */
    5 l7 G* Z0 d$ Q4 e8 _# q0 c
  12. 0 [- \) B- V. A8 g( o8 R
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */; w% L  N# H7 u. I

  14. # _8 }) q0 ^" w4 Z6 C6 _2 k: l
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index3 Y3 {: Z  D  S+ j# P2 K" b8 u( A
  16.                                                of latest Tx FIFO/Queue request */
    ; \6 h) i7 a3 |0 T; P
  17. ! b1 @5 Z+ ?! i. A
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */1 ]" c: i- f: i6 D
  19. , V' p4 J3 T( q
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */, N) D6 v9 Z7 |6 \) |

  21. / l2 Z' m9 A, k  L8 D3 e4 t/ ]
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */1 V& ]& E( H! G+ k( N6 a
  23. ; ^5 E& i  Y7 V5 n: h4 Y% W
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    # @, Q0 `- R) D3 ]
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */3 u* M' Q: w6 ^0 l" e/ W
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */. a) L7 k- J: M* @% C: U
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */
    * G: _2 w% J. y( T
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */
    2 g' L' }, G$ G7 x& f8 w% z
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */
    - ]4 M1 a; ?# N! z. |% k* u
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */
    . G$ q' k6 x1 L0 d: n
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */
    0 _/ e: W  M0 b# I$ E- a
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */  N0 r! P7 N; E1 P3 Y3 T
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */
      n0 u; C& ^3 I" j6 E
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
    0 G' z1 r& {* S' L( o0 @0 q: _
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */& E9 B  y. Y8 m
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */
      L' I6 L% {" F1 c$ H
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */
    ! _/ P) d% J0 ]. S0 L
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */; J) r0 P( _4 n# ~* _; n& b
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */; b2 G! t, j) W2 T5 r; O% B
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
    ! V& ^9 S7 u2 o; y5 j
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */, d! Y$ x+ U: k% Z
  42. 8 s1 I& T5 M$ I& J1 |" e
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */4 I3 K' q+ v3 C/ a0 W' ?
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */
      V4 [' p8 Z$ C, M0 H/ S& J
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */+ t! o$ x" V$ H% o6 }4 D) D
  46. 5 m3 T8 G- t: O! j% Q* y; |
  47. } FDCAN_HandleTypeDef;
复制代码

( Q' d' a: [1 A0 X) k( m注意事项:
/ x/ Y; f, T7 w$ F1 D
7 F1 g0 P8 I- `3 j条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:( N) p" Z# ^/ V, k7 J
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码

* I6 V7 s+ {, s, ^
9 |7 j" R* ]! J+ |函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。
% B9 M: l0 Z) ?% J  j, Y
& ]( Y0 o& W8 {这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。$ e+ D. [/ B" C2 h/ L- w- N

  G5 R+ e9 Q3 u  FDCAN_GlobalTypeDef         *Instance; h' t0 E- e! @9 ?
这个参数是寄存器的例化,方便操作寄存器。
& H# @8 U* l* W3 j& N( D( u" c9 q$ \6 S7 e1 ?' U
  TTCAN_TypeDef               *ttcan
& K( K: V/ g1 t3 R/ M9 j5 e# |TT CAN时间触发寄存器基地址。
- E" k9 l6 n' j* A$ l5 B5 R5 ?' u* n- \
  FDCAN_InitTypeDef           Init
+ h& v5 z- @! q2 OFDCAN相关的初始化参数。9 a( R1 L: t% U9 C* j
! \& t! u1 U5 Q6 y0 J
  FDCAN_MsgRamAddressTypeDef  msgRam
3 r3 n3 g9 q0 s, c) x" k消息RAM地址。
/ j, E7 W* N4 W8 B
; K: ]! V# O( {$ r- s  t  uint32_t    LatestTxFifoQRequest
. @1 `; k% ?% P( R# YTx buffer索引最后一个Tx FIFO/Queue参数。/ ]% H' B# _( V
( J/ u6 R9 q: K4 h( X5 ?
  __IO HAL_FDCAN_StateTypeDef State          ' V1 S. c2 B' e# q* |: ^+ e" \" W/ _
HAL_LockTypeDef             Lock          1 z* W# t. `& A$ ?1 j
& h8 H! T4 u0 f# y
__IO uint32_t               ErrorCode/ b8 o" X& C5 ^1 {/ |2 N6 ]
' G) \9 c5 a5 o7 S+ Y
程序内部使用的状态参数。5 M5 s; w$ X: t
$ e) z7 m$ D6 M+ A4 a% @
  剩下的都是回调函数/ {1 l2 }4 m( \" X
91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
; j( P* ~: C' a/ c' r此文件涉及到的函数较多,这里把几个常用的函数做个说明:! u9 W4 H( P, |. [* T# c
9 S7 k# g+ `9 s! K$ v
91.4.1 函数HAL_FDCAN_Init6 H0 t( s; {% X% l7 V  x$ P5 w
函数原型:
/ N% r1 v4 O. E3 q8 G0 P
5 x- q6 }* ?: R# H6 s! C7 M, r
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
    5 R8 l2 v, m* M
  2. {
    . q: I; P/ j. _# e# K* m
  3.   uint32_t tickstart;
    : f7 l4 D& f  U4 j
  4.   HAL_StatusTypeDef status;
    3 o* w6 c+ U- _" G6 W
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
      M6 ^2 A4 A" O6 G8 E- B

  6. 6 N8 \! f$ a1 F! G! f: l
  7.   /* 检测FDCAN句柄是否有效 */5 A4 F9 }- f3 U( i, U
  8.   if (hfdcan == NULL)$ Q. w% L6 O! I( H; p) `- S1 e
  9.   {
    # e/ o, J: g8 ?# G
  10.     return HAL_ERROR;5 D! @5 D5 F2 F7 ?& ?0 W/ e
  11.   }+ Y. \0 x4 J% S# X. h
  12. 2 i5 I1 E: [2 i' {- a
  13.   /* 检查FDCAN例化 */
    ! k& s5 g" A- _- J( ~7 |
  14.   if (hfdcan->Instance == FDCAN1)
    * F  D2 U' E' O8 Y- F0 {
  15.   {
    2 L& F8 B. z% w1 V
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);$ {# Z2 K1 Y' b, N9 n* y2 c( V
  17.   }% W- i# V* S% n7 q) o' x4 W6 R- Y
  18. + T9 A  v6 O# `3 d
  19.   /* 检查函数参数 */
    5 c/ m, ~( u7 `
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    5 [0 L5 [- f. A* q* X+ r
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
    0 `( j. Y  H, p4 {  W
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
    7 t3 L9 k# f5 \2 H2 x
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));
    # ^" B! n" s: `
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
    7 w3 B9 u" v- Y; q  |# R
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    4 _( |* K, x/ A' `2 f
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
    $ A) d0 _2 W3 e( n, N6 r- ~
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));, z* V4 W9 x  F7 i6 e
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
    4 F/ n# l+ o) A9 j5 M
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));4 d- F& e# m$ T" y) {) W
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)/ D' X6 n4 S. ~1 T0 F
  31.   {
    ' ]" X; `1 V1 L9 W5 ]' s
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));  l! ]0 X8 U! S- i
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));9 b4 V5 y6 J  W7 A( S5 L) |% `
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
    ' y6 v+ y: B, m7 ?/ {
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));  m$ f8 L1 A  b- L6 g) i
  36.   }3 }- V/ |% @+ o* s3 W
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));; D, l" V5 F- h) J: |% ~0 z
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
    2 x- ?. }" {" J% S: f# ?) I+ s7 m
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    8 x" J# b- K* l* A: B0 l4 D
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
    - {& o& j/ m) `0 u3 O. O1 D
  41.   {0 j( f5 l. X  Z! ]) X2 D% Z
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));8 z$ ?+ _( ]2 t2 n
  43.   }
    5 ^* {& z2 q' ~6 X) B$ H
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));( ^' Y- n$ J3 T' s
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U): l6 L6 x: Y; B  Y4 f7 R, f( H
  46.   {5 r: J; Z# d7 \! _" f
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));/ F; t' F4 t8 B" v; C
  48.   }" \- X% [. K7 |" {  d6 R; P, c  w  K. j
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
    0 Z5 K$ y7 g8 a$ E1 \) F( P
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    * ?% W9 a2 x! t+ j$ L
  51.   {. }3 v4 k( b* F; q  d  V
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));3 j  f- s1 u( U4 X, s" e& E! N% m7 c
  53.   }3 ]2 R0 F" J2 I, w9 ?
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
    % Z( a* n7 U4 A( X% t) J
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));: \( n0 ?4 j# M! `3 |) x7 K
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    * a: r% F" s: A, ]1 p- Z, g: w
  57.   {
    1 i! A* s8 u; Q8 j  x! c+ k
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
    - ?( L* m5 V( b7 [0 p% P1 u
  59.   }6 h# M& X* e$ w* t5 ^
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)5 d/ Q- y* U$ ~  _7 |
  61.   {
    % F8 s. w$ i; I9 |: h5 T
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));, j, o5 I& k9 N0 `& f: R
  63.   }% t: _# @" |  p+ a  t/ E2 D8 F, z8 n
  64. 6 ?* v6 x" Z( S4 Q
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    ( z' U# e+ S" E7 S, b
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    3 r- q7 Z" h( E& U. x
  67.   {
    1 @8 v/ G( ?- x4 W6 w
  68.     /* 解锁*/
    7 `' R* d3 X. m3 J  E, x& b
  69.     hfdcan->Lock = HAL_UNLOCKED;
      R: F0 V) o2 w* N* _

  70. 7 y& C. H( B# c3 D
  71.     /* 复位设置默认回调 */7 I4 ?  O1 f3 Z5 F! p3 }
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
    * ?' y3 i) J3 b# Q+ J. E  P
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */- z( H4 A) V& F6 V+ v6 O% b) E7 H, d
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    . D  O( G$ x( p- }$ r+ i
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */4 Y6 ?$ R' l( V8 `) K7 H0 t3 }9 l
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */: O5 T1 g* |3 U6 b( S$ b
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */
    * g( `+ ~9 D+ a( h- ?
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    & Q# b) P4 v  R) e4 a
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */
    $ x* K9 x* d, k" p. j1 e9 ]7 A
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
    : j% R: k* H5 B: C8 R3 Z) V
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
    % l7 L# W. l! L7 Y: Z
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */
    8 o+ |& W! E( E' J8 Z5 g
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
    . X  P5 ~/ W/ m. L/ K8 t
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */8 I$ X8 C: Z6 t* e
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */4 a# ]( c: e8 p6 |+ ]) i
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    ; Q. f0 b4 C$ G
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */2 A) C) ~# b1 U- R! L" ]
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    * E7 b+ N6 Y/ ~. l" h+ p
  89. * L' d3 U5 o0 g& ^* r( ?- A
  90.     if (hfdcan->MspInitCallback == NULL)- q/ s& o1 Q" g. s
  91.     {' W& i) M1 S1 W6 O' P
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */8 q) @5 k6 t& T+ o/ w1 H
  93.     }- X3 t( N) ]9 k$ E
  94. 9 k0 f5 e) h$ x4 p$ m- r
  95.     /* 初始化CLOCK和NVIC  */
    $ R4 T$ F3 `0 w8 ~: ?: Z5 |
  96.     hfdcan->MspInitCallback(hfdcan);
    " ?& Q5 F+ M; A$ j
  97.   }; w/ N8 C7 i: Y# ~
  98. #else
    ! ~* R, J% g" ^; k
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    1 C9 X) Y% D) q
  100.   {
    1 @7 }3 C( R; w4 `! b
  101.     /* 解锁 */# u+ p+ V, d7 s9 ^$ _
  102.     hfdcan->Lock = HAL_UNLOCKED;8 n; ]! X3 ~5 H  E
  103. - T* ~+ B5 Z! a- a
  104.     /* 初始化底层硬件 */
    % R  p; d1 B6 s' s2 m
  105.     HAL_FDCAN_MspInit(hfdcan);+ ]. P* w, }/ y, C8 V! v' g$ i
  106.   }; Q1 @6 U- B7 E7 B( s
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    & L' i- [5 i9 n) _
  108. ; Z) u5 P# a; M! t4 |
  109.   /* 退出Sleep  */
    8 L: ^7 V5 o! b1 H" L
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);" j) P1 ?! @1 c- N$ D, p! ~; h

  111. 9 }( \0 V/ O& q. M+ i8 `
  112.   /* 获取时钟 */
    ; t. Z' e5 I' X, |. k" o& z' L
  113.   tickstart = HAL_GetTick();
    ; h% |8 `7 O" i( ?0 P7 E# Q
  114. # d, o' f# \6 N+ O5 h
  115.   /* 等待Sleep模式确认 */
    " J1 k( T* |, b0 C* ?
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)6 p; C6 h5 p' F) H
  117.   {
    ! R; z( R. K/ H. H9 Y
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)$ b7 t' i+ M8 s
  119.     {
    9 N, x! u# O% Q2 ~3 D
  120.       /* 更新错误码 */& Y; ]4 @  ~, T% p7 p$ ]& x8 T
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    3 K7 n' ^4 B. C

  122. 5 A  u9 E3 u' Y- }0 r4 Z
  123.       /* 改变FDCAN状态 */- y/ h  ]& t5 ?$ A9 x. `
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;6 Y; l" O9 ^' _4 \- J
  125. - U( A& G% `7 w! y0 R
  126.       return HAL_ERROR;
    - t1 u& X- a8 N
  127.     }) G- X7 ]& F# X1 P; K
  128.   }  l4 S* F. K# F$ E( c, m
  129. ' g4 m) u9 n' s6 |5 B
  130.   /* 请求初始化 */* a# p& h$ V4 \' a
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    ( }! a' _7 |; V9 h( T
  132. ' s* P2 e3 C8 b( f4 z# C  r
  133.   /* 获取时钟 */
    / l4 t9 p. }0 Y7 ~
  134.   tickstart = HAL_GetTick();
    / [/ ~9 L9 L2 Q
  135. . `2 r3 H6 c* h- ]2 w; q0 ^" }
  136.   /* 等待CCCR寄存器的INIT位 */
    & G; q& H  n5 E# w; }: O3 X  a( u
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)
    9 Z- O. \+ B; z& x
  138.   {
    & {: D* ^# K! R
  139.     /* 检查溢出时间 */
    / L* @- ^1 v: |' G
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)2 @  J* f0 m% Y
  141.     {2 D8 `% \6 O# V7 W, l0 k* n3 h4 J
  142.       /* 更新错误码 */
    " M  H4 \5 Y- h! _5 S, K( z; _% g2 }
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    ( ^8 b; u$ v( K5 S4 ^- f  F" N, K
  144. . H; O7 E) L# W
  145.       /* 设置FDCAN状态 */
    / B# V  I! |3 J# P
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;
    1 m* p4 L# S7 D% U  T( i' X" D
  147. 8 j2 \7 B9 r- K) E4 X- b
  148.       return HAL_ERROR;
    1 t5 [8 `- ^* W5 W# r( |- D
  149.     }5 S9 V* y2 J+ S- ]& P* i' G! e% g- h# k
  150.   }+ \. S; P$ E6 B/ F( Y7 k
  151. : }! I  Q# H. F9 [$ k4 h0 v; U- k
  152.   /* 使能配置修改 */5 f  P& G( G! Y5 u# E: m
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);9 ?7 [! s9 k5 }7 P" G6 P) r
  154. 5 I- I% ^6 A- y3 C# b, w0 Y
  155.   /* 设置是否自动重传 */
    : T+ }6 `2 e. G3 w1 G
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    + w, t1 m+ m( }! m; U5 _
  157.   {8 W7 j. K! M1 Y8 L
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
      w- c& F: Z% m2 G6 w5 g
  159.   }
    & p: ]  f/ `6 M- m% v) P
  160.   else' H" N  Y# O6 Y, d+ }
  161.   {
    ) ^9 H' |( L' Y: j, y4 c- E
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    3 i5 I7 j$ [; n0 u) B$ c5 s/ q
  163.   }
    5 g; Q+ w6 x7 T0 m5 E

  164. 9 U2 a9 x) D( ]) s: r+ n+ e8 p
  165.   /* 设置传输暂停特性 */
    5 k. L4 r  d- X
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    7 A  @6 O& z3 u7 t
  167.   {
    " f1 g$ ^( Y4 ~$ u% d/ J
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    * T4 `% V$ u9 \3 d) b+ Z1 x
  169.   }
    % h, `1 s, C# p/ l9 D! r
  170.   else
    3 T" V: f, k$ n8 V
  171.   {
    + X6 ?) @5 O2 D. {) i/ x. C
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
    4 Q  l: j) G+ ^# }! C0 p3 A* w( |) W
  173.   }0 m  |6 i( b6 k4 O) e9 Z

  174. 9 E* p2 Z5 [; h2 d0 y7 R
  175.   /* 设置协议异常处理 */
    : h0 Y3 p% a+ H* V& `: N, t; k
  176.   if (hfdcan->Init.ProtocolException == ENABLE)8 P; Z; H- L) k  s
  177.   {
    . U3 e4 z  E+ C6 S& R) ]) p. `
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);" a7 J0 W3 ^) Y3 U
  179.   }& q* Y% v& q3 k( T7 q
  180.   else$ ~) g6 Y# U, Z" Z( ?
  181.   {
    - N+ t# \$ G; p$ W! q: e: P& D* r/ ^. W
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    5 q4 |# G; l& k3 Q8 x, X8 {
  183.   }
    1 ^  O! y( }8 t8 D

  184. 1 P2 G. @8 f# u4 W+ d
  185.   /* 设置FDCAN帧格式 */
    / {8 e* @  s0 Q- `% c
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);/ z+ [9 V/ H2 \* I

  187. , B8 ]% d: \. C& j  l  s
  188.   /* 复位FDCAN操作模式 *// C9 U' f& T+ d- |4 V
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));% F7 J6 ]" |: I8 G
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);/ J, p. ~" J. }2 m* }
  191. ( ^7 t) _0 ]6 @3 R! B7 X4 f7 P7 L, C  p, o
  192.   /* 设置FDCAN操作模式:$ Y/ a- t$ x. ?3 }& ~6 x, }% N! l; T
  193.                | Normal | Restricted |    Bus     | Internal | External, _5 S& u" y8 m9 L! y
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack( a; v4 M. [: E5 D2 U6 H$ u
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    11 E' V% S, @8 W* S6 @- y. Z6 |7 c! n
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    00 M0 h4 w7 Y2 t1 s
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    1
    0 c2 a$ ^/ u. W& A
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0' t+ L: ~$ }8 A8 I
  199.   */8 r  `' u) i1 H9 T# b1 g) \
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
    . f3 w! W8 c/ k" Q; G. E
  201.   {
    % U) C6 [0 @# L- C4 j: e" S
  202.     /* 使能限制操作模式 */
    7 l' G" S  K& M+ }
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);7 ^$ B* u! w' `- e7 j5 R3 Z/ Q
  204.   }
    # V' F, P6 \# l, j3 [& R+ O& A% a
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)9 F, |+ Q4 j0 V
  206.   {) D, A; m& G9 C% N4 a' u" |6 X2 G
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)4 B5 D" w2 a3 y. g" D2 c/ O  E* y
  208.     {
    * I! _9 L2 {9 H  q/ z) W% P
  209.       /* TEST寄存器写访问使能 */
    . h1 j+ b! x0 m5 `
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
    . ^8 y8 G& l3 \9 a4 ?

  211. 9 Z  g% j1 z# |
  212.       /* 使能回环模式 */
    9 s$ I: t. M/ y+ [" D
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);% y/ `5 u+ a- ~& p
  214.   y2 e; q! p7 J
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)0 B4 |% ^8 S$ p( y2 }! j4 B
  216.       {
    & S5 r( N: I, m( _# d' {
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);1 P% }" o$ M' m. Z
  218.       }
    # z! [% L; {, |2 v3 |5 E
  219.     }
    7 w' b& N2 m  a8 _& h& O6 M8 c( A( P
  220.     else
    2 |' f  `$ S4 O! a$ g
  221.     {! N% a- |. {( w* @: n$ R# [- T
  222.       /* 使能检测模式 */
    1 D0 v& m- K) p3 F- L
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);& {1 t' Y, }3 b  g" [0 O9 t/ L
  224.     }% v6 a; `8 F$ _2 f: U: w
  225.   }
    2 a! E# k0 B8 s
  226.   else/ a- n* y3 U/ K
  227.   {) s' F2 K' O% m. e# t: j) [% M8 D
  228.     /* Nothing to do: normal mode */
    0 ]# @* x/ X- Y+ Y" m4 q5 I( p
  229.   }) P. s) S& g! r) o& Y8 I. @

  230. ( }; m2 C) m% Y  a  A0 y0 @6 V3 \
  231.   /* 设置nominal bit timing 寄存器 */5 M/ h4 T& @/ L; X$ |
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
    4 |$ x7 v. j9 h. `1 N& Y7 N: {
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
    8 ~1 u2 t& b- y! f: }2 l
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \
    % j6 f' F3 d% J, z, S# Z
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));0 E3 U3 @8 u6 b3 U! s# a
  236. 8 J# a+ E  F, T
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*// g; ]% c! p4 h* J4 i4 K
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)6 n3 v# |/ T* I* E% P1 t
  239.   {, P, \2 W& @. y- h0 I
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \
    8 v8 h0 P6 s2 K& |% y4 [- A
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
    6 l, ?" G5 z, s. E; g+ p
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \1 T8 ^. |; v. f# J( H
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
    ( D9 h: S) {. l* Y8 W/ m
  244.   }
    + H- A4 N. k1 }5 V& G
  245. 7 D# B) Q$ j9 B- W1 |2 y" v& c
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U). J# s0 |! t$ }9 I5 Y
  247.   {
    # ^5 M1 h/ |3 E  n* F" ~2 X
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
    4 V8 [- N" f) i: |- |2 H$ T5 O- M3 ]
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
    : M4 g% d) O; T, y5 q
  250.   }
    8 S  K9 F5 e5 R+ q, c
  251. + w5 r- j7 a' S5 {: I- i8 d, a' D/ n
  252.   /* 配置Tx element 大小 */" b' o) h" W+ O( H
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)) ~0 F  W  f1 ?( ~( ?* y  B; h! p
  254.   {) \  _- r" r! a& \' K
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);8 O% o) N+ t# W
  256.   }4 `' y; I1 n! }( j# x

  257.   s% T' u3 h& q# B
  258.   /* 配置Rx FIFO 0 大小 */
    1 N$ {9 q0 |, T6 F0 g7 _( M
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)3 ]* F( L9 Y$ n* U  s
  260.   {
    + e" D1 f% |# H
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));
    . E) ~5 `4 F" Y
  262.   }3 b; d! L/ t+ o, a( q( b
  263. / B+ A  z8 O7 ^6 ]
  264.   /* 配置Rx FIFO 1大小 */+ t/ c/ ?  U8 d6 ]* s+ ?
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)& I0 w* P# p( k
  266.   {2 A4 v$ D- D0 g, H) R/ n2 R* }
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));$ B3 X) h8 X5 Q; x
  268.   }1 T5 ?, B. ^1 V# u' K
  269. 8 x0 `8 t$ I$ J$ P4 |; q( ^
  270.   /* 配置 Rx buffer element 大小 */
    9 b7 i  b1 p5 w
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)' E" K' D, \; u
  272.   {3 Z' Y# j2 J# |" ?
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));
    7 [2 C) _) t6 c4 _6 H" E
  274.   }6 y3 w6 O$ w  [6 j0 W2 N
  275. 4 i) @- o3 Z; R$ ?7 G/ Q" G4 i
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
    + J3 S8 l9 i+ J
  277. 后调用HAL_FDCAN_TT_ConfigOperation */5 @3 C7 b% i/ h6 W+ X" M
  278.   if (hfdcan->Instance == FDCAN1)8 ^. M7 A, M; J$ D8 c' }, q! b
  279.   {
    / l! N5 [1 O* U. R2 s0 ?9 p
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);/ U. n) t# ^- [& g; G
  281.   }4 Z2 A/ f+ r  C

  282. , P6 J, T9 s. k8 Z1 ?
  283.   /* 初始化Tx FIFO/Queue */
    , \/ `' U/ X- E& `& Z
  284.   hfdcan->LatestTxFifoQRequest = 0U;
    3 z! h0 F3 H# f; ?. C. `
  285. / N3 Y% A' ?( I' g$ Z
  286.   /* 初始化错误码 */! m8 u" {6 X" p" l1 k
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    6 l' e. F! @' s; F) P2 {
  288. : w: f, Q' a3 @# M0 J; L( Z
  289.   /* 初始化FDCAN状态 */
    , ~) G9 s0 x4 n3 T$ f- H' n
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;  k$ L/ h7 M. N6 S
  291. $ n" b- W/ P# h5 d2 a2 i
  292.   /* 计算每个RAM块地址 */5 @  t  B7 I; I3 v
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);' b" o* w/ G) O4 X; {5 D  o

  294. ; d  i* R7 K" t; \6 o' d$ k6 q- y
  295.   /* 返回函数状态 */9 M5 C/ r0 c) B# }- [8 B
  296.   return status;
    # K& g; V0 G0 p" ~
  297. }
复制代码

. E) O% ~: A/ x6 w1 Z2 B% x函数描述:
; h* ^/ h' h2 s" v$ P- ?+ Y, g# w8 U2 B$ Y5 I* v
此函数用于初始化FDCAN。, I! i" }3 N8 Y% q6 G; ]' D, r
' \9 W$ U1 r' Q+ [) Z9 q! _$ M: e
函数参数:2 V* B4 }$ w0 m4 A6 C7 M9 i
/ P3 s5 J4 x- p, s4 z% [
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。+ u/ L0 |& N; x( ]% g
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。( F) n. t. _9 X; k* x
注意事项:
2 p7 _2 [1 N0 [& {% E2 i1 Y; }% w3 R3 _* \+ E% d, z
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。( q% t$ B& p/ |. l$ C
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
1 ^  w4 r& G2 n" J# K对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。3 M2 A, ^6 k2 S4 D; H! t6 b
: i% d- j6 ]: g: G2 J  b2 B
解决办法有三4 f  S3 X( y- {- ]
* l7 e" u, w$ Y$ q! C* m1 @
方法1:用户自己初始化FDCAN和涉及到的GPIO等。7 H+ v& V1 B0 l' P: Q- `

: D* c* |- O1 e* L方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。7 z/ |* v& b7 U4 M

8 s6 O- u/ r( W  W方法3:下面的方法
1 o+ o" c% \. h0 R% K
+ k& @! i; v: J' T8 q
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)& ]2 G8 m& u# |: [& E/ n/ }
  2. {: }6 K1 `6 V% j( {
  3.     Error_Handler();
    " Z+ k+ |$ Y5 ]1 c: F* ?  D
  4. }  
    / f* |8 m: D2 n5 v- u
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)
    + Z' U& L+ e# m" z7 N% P; J. \
  6. {
    # h+ O7 W, o( i2 t
  7.     Error_Handler();
    ; e0 N$ ^: @, T* h# r
  8. }
复制代码
% o* t; g0 h/ j
使用举例:! `( i( [  U; j9 F  I1 o: V

2 _1 O' q; W; W4 P7 @
  1. FDCAN_HandleTypeDef hfdcan1;
    0 E4 x. h) \0 _, t4 M

  2. & n2 @3 w( V& N3 x
  3. /*5 f' k  X. a1 ^0 m
  4. *********************************************************************************************************
    7 K3 E, q$ Y) G/ F
  5. *        函 数 名: bsp_InitCan1
    ) v8 i8 k- G' x2 {$ f/ z
  6. *        功能说明: 初始CAN1; q$ ~3 j! M: p) k0 D& G
  7. *        形    参: 无
    0 G, G* q) E6 O9 Z
  8. *        返 回 值: 无
    : z7 n3 @- t3 I: U8 ^; Y
  9. *********************************************************************************************************
    8 d/ h" u: z0 [! c( I2 H
  10. */
    % J- z% g) J  b# ]. f
  11. void bsp_InitCan1(void): b( ]% y( G6 R# ~, n" s
  12. {         
    ( @& A3 r/ \# T8 y
  13.         /*                    位时间特性配置9 Q3 m3 l5 Z5 s% L# a+ X
  14.                 Bit time parameter         | Nominal      |  Data* _$ W7 h+ d5 X' k/ D( K0 m7 L
  15.                 ---------------------------|--------------|----------------
    % G, G8 j( D9 Z* |0 `$ B" B6 f: D& L
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz+ J: w& L0 Z( V3 u
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns+ b, J( r( I) L! |7 G
  18.                 Synchronization_segment    | 1 tq         | 1 tq
    $ t6 T$ c  O4 ]1 y+ n) @! ^
  19.                 Propagation_segment        | 23 tq        | 1 tq8 M' R0 D/ I4 l. F' |: O
  20.                 Phase_segment_1            | 8 tq         | 4 tq
    ! X9 y8 x$ s6 ]+ V* k) B
  21.                 Phase_segment_2            | 8 tq         | 4 tq* A$ y/ H. w8 f9 o7 C
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq
    7 x- U0 P. a) I6 v
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
    + V! X+ d8 |3 ~! |, F6 N* @4 [
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
    6 w' s0 \' E8 D. I9 L
  25.         */
    ) |: L! Z( P- Y  B
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */            
    # U- G, U3 ?6 O/ p0 m8 r  R$ ]8 p
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  
    6 g0 C( [4 W5 L; r- c  m/ P
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */ & E/ s; {+ d) j& H: e+ d
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */
    8 l8 C, ^: x% S
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */' c) ]. K) E1 C% {& h' e+ R
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */2 ~) t3 d5 a/ r* L) C# C
  32.         
    6 W/ {$ t  f' f) }3 K$ o9 S
  33.         /* 1 M- [% ]& f. D" M8 W* ^
  34.                 配置仲裁阶段波特率 , o8 n) W6 {8 g* j/ p7 ~: R
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是! d- e5 ]- R& |1 F0 S- y3 E- v4 ]
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        $ {4 ^7 q6 w+ _" i1 G
  37.                
    7 A) Q4 G" C0 l& |3 D0 x
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg29 Q0 C* q9 a1 L. S0 P' i
  39.         */5 Z3 _. _; E2 z: S8 R5 R4 ^' ]
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    ! A: d& I& E! ~+ A, h# t
  41.         hfdcan1.Init.NominalPrescaler = 0x01; - G4 L- D, U& \  f' D9 j6 y

  42. ' H$ \9 o0 f# J3 V6 F
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */: x- p; {- y5 ^$ Y) e" g
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08; & o5 `- v# o, @7 r) u

  45. & u" w) T& a5 |" ^7 t  w
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */( M, O. X$ e  p4 y8 r. ^& }
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;         
      q; V% \0 H2 o/ D
  48. 1 Z5 Z$ l9 w+ k9 v
  49. /* 对应位时间特性图的 Phase_Seg2 */& R% h" a0 i' N7 a) m) ^8 ?
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     % b7 r6 I8 a& Y

  51. * d/ g: Q4 |7 d5 p; K
  52. * S, z  v1 j7 h* H! l
  53.         /* ) l0 V. k2 J) S1 R& k" k  j
  54.                 配置数据阶段波特率
    & U. D% {. O+ [7 F5 U+ t- P
  55.                 CAN时钟20MHz时,数据阶段的波特率就是
    + o- S3 ^+ V6 |- C0 r) L- G
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
    ) j) N7 \1 \" k# i5 m$ n' |
  57.                 - Q0 x# ]! t$ \7 \1 G4 X) N+ p! c
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2/ t9 s) g( e% \  g+ U( E9 p
  59.         */; M& {9 a! {4 a. Q* u
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
    / K6 C  v% V( E/ s3 @
  61. 范围1-32 */6 s: r" j$ R7 t7 u. ^! ~
  62.         hfdcan1.Init.DataPrescaler = 0x01; 2 @3 X/ d, t' p2 x2 i+ g/ T

  63. ; k# {; P! A9 M3 d
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */+ i0 |8 p1 P( D8 L/ [0 n( l
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  : q: m' ?, g1 c8 `1 j7 K
  66. % ?, k4 O3 H' {) l5 [7 g0 E1 |
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
    * ~7 r2 A1 I) c' @
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05; 5 w* }0 V' o6 H, Y+ i0 n: y  w

  69. ) q! y; J! I, E
  70. /* 对应位时间特性图的 Phase_Seg2 */                9 K1 x) w/ u# y# C
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           
    + E9 L+ G; F; e" t6 d+ g! u2 r
  72.         3 Y2 D5 T. I# v3 j$ ]* _
  73.         ) y0 q1 S6 i+ H- U
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */# H& }( y! M2 V$ I+ g
  75.         & ~( H' D. |: ]& S% S7 U
  76.         
    8 }- b" M6 I: r$ G
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
    ! Q1 Y: |5 @! N+ ]. P- h
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   9 T/ X9 k8 w0 q1 V* C
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  ( i" i1 |* J2 D" r7 O, Y9 ?
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
    7 s; }" u: J  W6 t# @: G
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 1 d! j% K2 N7 J; r  m5 Q2 f1 G% g
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 *// T0 S8 c" f" F

  83. 4 P; h8 t/ \$ _6 t+ w
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        
    / ?( e$ g' ^- t7 s* T. a# F% X
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; 6 H; `# `! U6 j8 Y
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
    . a3 e7 {, }9 s: L6 x" ^
  87.         
    7 P# P, e6 _7 [* ^; t+ T; ~0 @
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */0 K) [, L- d1 \' t9 `
  89. hfdcan1.Init.RxBufferSize = 0;                             
    ' c% Q( Q! a2 p
  90. $ ?: m6 G- l/ W9 z! p7 X4 T6 Y

  91. 7 C' L& q! d8 C3 D6 h
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        
    ! e7 D, K- |, K: {7 l2 `
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
    2 m% \5 x$ {' L4 v
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */& A. S5 s0 ?, q/ |* O* q* R
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    ) c2 ^- o' d$ E, W' \
  96. 3 ~& ?1 ~3 ?3 d) Z
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */
    % @# s$ Z7 `8 S5 |7 A1 Y# X' h4 k
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;         
    7 c! x6 x/ Q, g
  99.         HAL_FDCAN_Init(&hfdcan1);) O6 ^+ f3 A# T' }: Y  f* M; Y+ a
  100. ( G, a! y5 s1 r! e* M, ]

  101. ( y% ^5 p$ Q0 z% S
  102.         //省略未写% q9 S5 A& ]# U! d5 a) E" ^
  103. % t, I9 ~! f* M+ t% \- a
  104. }
复制代码
: S, _, V# g; t2 _6 E
91.4.2 函数HAL_FDCAN_DeInit9 F3 M* s! N. Z% k, |7 O' c+ ?, Y
函数原型:
) R, I5 [" g7 C) m
# i3 v4 P# r# v5 w/ a
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)
    : F1 N. {0 L, j
  2. {
    : m+ X( K( j# h7 ]% n7 _
  3.   /* 检测句柄 */
    9 ]- {' l) B, z$ l
  4.   if (hfdcan == NULL)
    % S# V- C6 }  b) ^: T; Z
  5.   {; c; m0 D$ `* @6 F6 H. N
  6.     return HAL_ERROR;2 k4 y4 p6 z, I9 X6 l
  7.   }0 Y* H/ Q: R  o" T
  8. 0 o8 r0 ]1 x" b2 L  i6 z$ M
  9.   /* 检查函数形参 */% v5 d+ ?) Y1 H& }
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    & U4 h; c; S' C

  11. 5 d) a) T2 z3 v, m1 d+ U
  12.   /* 停止FDCAN */
    ; b7 _1 n+ x: c
  13.   (void)HAL_FDCAN_Stop(hfdcan);
    4 ]5 `' h) r( N, P1 j' Q- \
  14. 4 s" C9 }, k9 c, B; }( k1 n
  15.   /* 禁止中断 */
    ' T3 }) _0 i) F- R% f  _8 U# h
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    5 |* x6 E! s8 J" S9 L

  17. ( q2 Z0 `6 |6 a) I+ V8 b7 K3 t+ K% b# q0 m
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    4 F6 l% \' y: G% W1 ?3 b
  19.   if (hfdcan->MspDeInitCallback == NULL)
    , A) V' `. \% S
  20.   {
    ( V% ?- j+ l2 G1 T2 r
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
    - C8 }, T& c$ {# ?" V, i
  22.   }
    $ l* u  n) n* E% z$ ?
  23. $ I6 \3 @$ c' C# }  F" S
  24.   /* 复位底层硬件,如时钟,NVIC等 */
    # N+ e/ u1 t' I" u0 S
  25.   hfdcan->MspDeInitCallback(hfdcan);
    7 s6 ]) `% d, g5 l& K
  26. #else
    % f# F. Y# e/ ]+ v. F+ j" T
  27. /* 复位底层硬件,如时钟,NVIC等 */% {1 F, E6 i: i) m
  28.   HAL_FDCAN_MspDeInit(hfdcan);& ^/ J0 l. V6 a# X
  29. #endif ; D8 z% ~  T' o; |2 |" Q: r
  30.   V. ?2 r7 n. A9 O1 q# S) A( }. `
  31.   /* 复位错误码 */
    * l8 R9 q7 s+ d# U' ^+ x5 {
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    / z( m1 t- o# c2 s# N9 ~8 y

  33. 4 l9 ^6 B* E& z$ M# I$ G2 ~
  34.   /* 设置FDCAN状态 */( m0 e1 ?: \- h; i2 d
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;
    . a1 u& l6 _( _( n6 W  x+ @
  36. 0 W& n( {" Z) ]) a+ V0 f. A, ?7 ^
  37.   /* 返回HAL_OK */
    2 F; V/ K0 t: }* u; L
  38.   return HAL_OK;/ w/ L5 h/ `1 u1 p1 |
  39. }
复制代码
4 m: a% i5 P! V
函数描述:+ F' s" |) o* N' O& d
1 s2 Y" \& m1 x# p0 }' P
用于复位FDCAN。- b- x6 I9 T) I. z
; A  \1 D8 q% v! z9 y* O5 X
函数参数:
& u  U2 ^* i# \. q
% F: O' Y$ K/ ?/ T4 d& t8 Y, T  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
4 o3 B$ C2 n  j% q/ g& J. q  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。5 m8 a7 C1 e+ f+ ], ^3 S) X  V- C& B( i) h
91.4.3 函数HAL_FDCAN_ConfigFilter* P" p! n8 I; A/ B- |
函数原型:
$ Y+ |/ p+ @9 @. {2 O! Y* R7 V# f5 J" @
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
    / E7 i( F) ?) j5 e9 Q$ S6 S
  2. {
    / p( Y! ]' b' r# C
  3.   uint32_t FilterElementW1;
    " a: Q2 H) C' j6 w3 K. h0 j
  4.   uint32_t FilterElementW2;2 n4 J7 [' o" A, L; ^# G6 F; C
  5.   uint32_t *FilterAddress;" q6 g' h+ O- _4 i6 u
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;) B0 T5 l. W$ t. L8 r
  7. 5 E) h4 v8 p4 {
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))2 R2 P4 p1 Y* C$ V/ L4 }3 [
  9.   {7 h. S1 q# w- H7 `; b( g6 N; z
  10.     /* 检测函数参数 */
    7 j* [6 s/ P& {1 {4 {" I: A" R. C
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));0 U. L. T+ g3 T: I' p
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    3 p; B) E/ K  I! Q: p+ R9 k
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    * [1 u, V* U+ H# a! A7 O
  14.     {
    6 Q# M2 [2 {1 `$ W0 @( P
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
    . D+ q( o2 A# ^
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
    - H( z& k6 x5 H" Y  o6 S2 z
  17.     }
    ! d! r2 e4 b  G
  18. - i* h) `  N) L7 x0 U  F
  19.     /* 标准ID */0 J: A$ c8 ]" ?2 t5 }
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
    3 n& X" l+ z- K4 X5 s, g
  21.     {, C, ?( C# v  ~8 X! z& ]
  22.       /* 检测函数形参 */* M7 l& Y" t2 ^# a3 Y+ ?! T
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
    8 k/ c$ D: {4 e- a% ~. C, s) e3 R
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));' N: j8 {& v- I, E
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)% h1 }8 m4 ]# d! y5 F7 s
  26.       {4 {7 n" u. A. @
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));" D2 Y5 \0 n3 K8 q: l# g
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
    7 c6 B: `4 ?8 E5 q
  29.       }  _) _* F3 O: l7 O1 N
  30. & r! h( r+ U; {' Y* y+ N  j3 C
  31.       /* 构建过滤元素 */
    $ H  D- u9 _' t2 X; b
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    9 y# P7 H' `% u$ W9 Z! C& r  p9 |
  33.       {
    - l$ l1 Y8 E: U. J# \
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |5 ?1 ?7 f( q. }: ~! d
  35.                            (sFilterConfig->FilterID1 << 16U)       |# c& M: s( d5 F/ M8 K
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |" F5 K3 B: a( D4 k& X
  37.                            sFilterConfig->RxBufferIndex);, Y, \" O$ ?7 j! s# ^2 J( H7 G1 u
  38.       }# a! u- y: w" |; b* `
  39.       else
    ; l6 T7 ?+ p& W8 U8 x7 j
  40.       {( V. p' t* J* v, M4 @
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |
    : O3 ]/ p, b9 ]" y
  42.                            (sFilterConfig->FilterConfig << 27U) |
    . m; t) r; I0 a* {2 D; e
  43.                            (sFilterConfig->FilterID1 << 16U)    |) ^* S  e8 q7 y/ Q) G
  44.                            sFilterConfig->FilterID2);! O4 \$ v% y( l/ C
  45.       }! R1 S! j% y4 R$ s9 C6 B/ o" B

  46. . r# D- O; e* N7 o6 ?
  47.       /* 计算过滤地址 */
    ' x3 E" x4 i6 R8 t9 ]
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));3 e  z7 ^1 r# a, R' ^  r
  49. 7 M, w: H' P* r  Z* y4 F
  50.       /* 将过滤元素写到消息RAM中 */
    5 `7 l% Q8 t; a8 ?2 X: V) B
  51.       *FilterAddress = FilterElementW1;$ G3 w0 b" J3 V
  52. }" A- O8 X% G- k) S) X' E$ p. B, c3 t& ]/ L
  53. /* 扩展ID */
    + i6 s6 h2 q4 y' I6 k
  54.     else ; ]0 Q% R+ A7 q% q6 L$ Q
  55.     {
    9 W4 l6 B: q( G
  56.       /* 检测函数参数 */
    5 i) P5 ?" H0 r1 e
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
    $ S& v$ n( Q: i
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));
    . d7 |: O1 U6 f. k% {6 U
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER). X  h! Z3 g' m1 B$ ]- x
  60.       {! I2 Z- d" M$ R/ W) E
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));* o' P6 p; S( R- v( K# d- D
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));; W" c6 r  N$ ]3 H6 l6 I! b
  63.       }6 {" L5 R  ^. K  F' q

  64. 1 P+ q  Z' Q0 e: @7 ^
  65.       /* 构建第1个word的过滤元素 *// C0 A. c+ [; I. y. |
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);2 g8 R: T, o. R% b# ?  T! z1 G

  67. ' \. P9 l3 L* m& B+ z
  68.       /* 构建第2个word的过滤元素 */# P% p0 d% ~6 I8 @% E5 \
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)2 A# }5 J' W* t
  70.       {. S( J7 i7 T4 R& i; U' b) ?
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;
    5 N7 T& f- v3 S: m' u
  72.       }
    & p, ^' ~/ p6 q' \% e# j- {
  73.       else2 Y. X; N0 a+ s" ~
  74.       {" I" b6 O* U( J# c( h) s) q) S0 i; n2 m
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
    $ f* G+ @; J3 z7 q. N: K7 U
  76.       }+ h! e: A0 P2 I* o  Z
  77. 3 I& e  [) x* Y! B6 Z" X
  78.       /* 计算过滤地址 */
    1 {6 @. l' v6 r# _: r$ f
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));7 W- `/ j9 `5 u! T

  80. 0 H" C- q$ I* G/ C) y6 ^# |" r4 b
  81.       /* 写过滤元素到消息RAM */* ^" w9 L. t+ k1 d9 ^
  82.       *FilterAddress = FilterElementW1;
    . q+ ~" j. q/ B
  83.       FilterAddress++;
    9 w1 P8 p$ N+ U) @8 U
  84.       *FilterAddress = FilterElementW2;- u) e& w1 z8 i% F0 ^: |/ y
  85.     }
    # v" P4 `* L) V2 x7 j
  86. ) V! Y* b" Y7 {+ L0 t
  87.     return HAL_OK;8 Q! G1 Q) O9 O2 x
  88.   }
    ) e% c: }5 Q0 i" A( x
  89.   else! u! G* U3 m  x8 ~
  90.   {! j  L  Z( W7 l4 Q+ [8 ^
  91.     /* 更新错误码e */5 {3 v3 s$ b; X( p8 n6 U; {
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
    ! ~  j2 M8 J- @: `/ s8 l
  93. ! Y0 \4 i4 \3 {/ L
  94.     return HAL_ERROR;
    # a) t: W1 o, r" ~3 |0 M8 Q, X/ F+ E
  95.   }
    * K) D5 h- ~# Y% k; X
  96. }
复制代码
% }/ O1 o' c8 N9 [% H1 ~9 I& x6 \
函数描述:" q" A3 s! `7 j  J

! Y* n7 R2 Q8 n3 N& |此函数主要用于设置FDCAN过滤。, [) h! ~0 a/ Y$ }
$ n8 w% C$ C+ R+ D1 `+ p
函数参数:- _9 Y4 j' M& v
" h' g5 m& |# |  Q
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
( w% B+ n7 b# K* s6 Q; o; O5 ]  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
$ M9 W: i* z! A( n# v  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。/ t5 P3 m7 X! h! W! Y/ z
使用举例:
  B- d- y& N! P( d5 n/ R) N* V
! _" p- a* J8 `& j; l9 O3 q
  1. FDCAN_HandleTypeDef hfdcan1;
    0 L+ f+ O$ S6 A5 \" B5 }* c8 u$ [
  2. & r$ [6 ^7 @" n" L' V/ K! Y
  3. /*6 g2 d( q( B, y% a8 ~: \( i
  4. *********************************************************************************************************5 w3 L3 O# i6 i
  5. *        函 数 名: bsp_InitCan1
    7 T  v3 y- C, Y. f) l! D; F- t
  6. *        功能说明: 初始CAN1
    4 y/ O/ T3 l4 A6 [+ {- @* K
  7. *        形    参: 无3 j% G# O1 q3 J6 T/ h# {0 C
  8. *        返 回 值: 无
    % A5 `! x3 |' Z  d0 {( X
  9. *********************************************************************************************************% }7 a1 u: h/ {& Q. `' O: R" ?& o8 Q" w
  10. */
    , \& I; P) _; q3 i) G. T$ n. A
  11. void bsp_InitCan1(void)1 O2 B1 Y( t  w0 z0 F
  12. {         ( E0 U& x5 U" w
  13.         
    4 n3 J; _" j- r) L
  14.         /* 6 }& f. }& h5 v# U5 a
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。  l, Q1 F% F/ d$ p) e
  16.                 FilterID1 = filter
    - v; W# t) M2 V: y3 @, A9 O
  17.                 FilterID2 = mask% n+ `5 i9 ^  L4 |
  18.                
    9 x# s! M- S6 g
  19.                 FilterID2的mask每个bit含义
    ( ~! ~! \- Z; V$ [5 i
  20.                 0: 不关心,该位不用于比较;
    8 t8 q2 [7 H( t( V
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。, _$ l0 s0 K2 [& t4 S* |) `
  22.                 ( C# ^2 B& m9 l% l  x
  23.                 举例说明:$ G9 V4 ^# x0 E# |  F$ V+ r" T
  24.                 FilterID1 = 0x111# S/ x( X6 S" S
  25.                 FilterID2 = 0x7FF
    5 f2 t- `) Q# ]1 F; p
  26.                 表示仅接收ID为0x111的FDCAN帧。' @& n1 @; E' ?- k4 C
  27.                
    5 z7 @- R/ ~- w* N1 Z& d% n  \
  28.         *// C( s+ l1 ^' g# B
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */
    2 }- g  x& o; i9 Q5 d
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */9 Y" m! m8 n. E3 k* o) a
  31. sFilterConfig1.FilterIndex = 0;                                                   
    1 @9 v; E; t  M% a$ Y3 R
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */
    3 C6 d. ~# O1 t! |+ N
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */) r( U( M. M' t' F* C  v& J5 R2 q
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
    + O+ O. B* i# N, S* t7 r/ `" A
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
    ' P- I, Q0 S# ^& w4 L1 F: D
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    5 Q4 ]  Q% H/ Q+ Z- q
  37. 5 Q' Q% ]* J, Y/ L
  38. }
复制代码
* G4 H4 d( [: v" }5 ?" R; f
91.4.4 函数HAL_FDCAN_ConfigFifoWatermark* l5 J8 H1 l* u1 T" U/ s
函数原型:
  P" Q- j; ~* ]; j7 ~# X% a+ R1 k0 b
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
    ) W& v5 A/ Q4 K& @" U1 M
  2. {( V. ~6 _* F  }- T" b& d
  3.   /* 检测参数 */2 K- [: j0 n" }5 X) z
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
    / X! A# g' H$ [6 H% `' k+ _4 J8 {
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    3 F+ \7 S) _* R5 G/ [
  6.   {/ N9 l: m/ E' \/ P1 O
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
    ' ]/ L! N3 x; }: w
  8.   }
    : b# \3 V/ l& b" B) S5 G, H9 _8 J
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
    $ d8 }# M9 T- C% e  x
  10.   {: V6 l$ ~# `: r1 u$ c- s0 L( J
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));  \7 \6 H9 X% V) Q/ N: O
  12.   }
    . B1 b' V4 p; F3 V9 r! P% B
  13. & L7 Y1 e2 }( A0 B( ]: s
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    ' F: E& P: ^& _1 D6 E2 ~
  15.   {  B) k$ J5 `. f% L
  16.     /* 设置发送事件FIFO */3 C! V8 C! d, F: d2 i1 u% j
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    1 c2 Y( y- y: G5 A7 [
  18.     {* B) H2 u3 }7 u: o
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
    9 b) ]* p8 [8 C6 ^$ W
  20. }( p  D# d! @. x1 g, @  O$ Y
  21. /* 设置接收FIFO0 */- W" B* E* B! b$ X
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)& P5 \+ `+ \. T; {+ B( Y" J  L5 ]& ^
  23.     {
    # E* K6 G2 M5 |1 |" D
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));
    9 S, d- B6 ?  V
  25. }) r# X7 l3 v9 N% R/ `4 M
  26. /* 设置接收FIFO1 */( d% @) n3 `- x. K2 S( Y
  27.     else
    6 K3 l2 V1 E" S3 c; s
  28.     {* T6 f% R8 C; I! U
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
    # j! b- B0 Q% n$ F3 I! j
  30.     }
    2 [+ ?% u0 z2 n( |/ @

  31. ( B$ L! Q3 {; @, ]( O
  32.     /* 返回状态 */7 D$ B% N  `) a
  33.     return HAL_OK;
    ) E9 e; y" ]/ r2 u
  34.   }
    - _& N$ w  ^+ j/ P+ r& M* |
  35.   else
    8 ^' P9 y; _* Z# j9 M4 J+ y+ b: D0 d
  36.   {
    % U) M6 ]( v( j3 H. R8 e3 I
  37.     /* 更新错误码 */* b. w3 I& _2 I
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    ) E7 A, J8 k; L( _5 i( T, N- Q( u

  39. " E4 B9 s/ k8 O" u* Q+ ^! Q7 r9 k
  40.     return HAL_ERROR;2 R3 d2 ^( o" ~6 ^- |' g1 L) B
  41.   }
    ( i8 g1 \$ u' U. q1 N& I5 D* p
  42. }
复制代码
& k6 F! I4 u! N# L' h. f! w$ Z2 T
函数描述:$ h# {. d4 `* O; |
" D# m+ D4 r, W6 i6 H0 L& E
此函数主要用于配置FIFO Watermark
7 ^5 B1 s1 U. ~$ F* ~* ^* C$ c
3 I3 k, v$ N5 F2 g6 j函数参数:6 P: @2 Z! j: e( l& m* L0 P+ ?: t% k* l

  M* A% f# |4 q9 q  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
8 s1 f1 f8 |6 {) a1 r( j  第2个参数是FDCAN FIFO Watermark1 ~+ f0 [3 l( G
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */% }" h! u8 I  d7 r7 V
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
      N7 O) v. i: t' X0 |! t
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码
4 Z' K6 r" N3 s/ P: o
  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。; @/ r7 N; }+ |8 I
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。& C5 r8 g9 S) x7 ^; ]+ U5 E5 |8 Q
使用举例:9 b7 D2 m7 o0 w: Y, D' g6 t# ?

* s# Y* R# }% O2 O: U
  1. FDCAN_HandleTypeDef hfdcan1;9 {1 N9 d) ~8 h/ A; e0 Z

  2. 8 f! }1 i9 b+ T
  3. /* 设置Rx FIFO0的wartermark为1 */
    3 h. Y+ ~. Y7 ~0 r6 R
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
+ Y0 n2 k( F  Y6 j4 Q9 I
91.4.5 函数HAL_FDCAN_ActivateNotification
# Y. H) q) m5 F' F8 T6 a" N( O函数原型:
6 s8 r4 ^5 t5 c9 j, F( ]( y
$ `4 c4 \4 C& p  d) d
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)9 [8 H, R* H% ]. Q
  2. {
    ) s) \+ ^! K: M# F, p# q; d! A
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    9 l  x7 X! Y+ w7 F6 _; o+ o

  4. " C$ X3 U3 a. |! V/ l3 D8 h6 y2 r" s
  5.   /* 检测函数形参 */" Y" e- |, f3 a& b6 _
  6.   assert_param(IS_FDCAN_IT(ActiveITs));
    " r4 y: u3 u: o6 H

  7. 8 B5 S4 q$ H. i, Z
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))$ I5 B  q# D$ E
  9.   {" @; r! l/ _; R4 i& L, [* g
  10.     /* 使能中断行 */9 H/ g  t6 [" w( V+ [$ T
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)' M1 K( k  j) d: ~
  12.     {
    2 t8 h( o& b# }
  13.       /* 使能中断行0 */
    6 C  p2 c3 K! z% U- W0 ?3 @9 g
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);1 |7 f8 j0 Q8 V1 Q  V# P$ v& d
  15.     }
    ( g: j6 q# I9 x1 @' q- v
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)0 c# a. G& c8 V$ l2 a# i& z2 O
  17.     {
    # H( o) K* V9 n) d- G6 c. S2 ]
  18.       /* 使能中断行1 */5 L% v7 W3 p9 g8 @
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
    0 i2 ^9 J( d3 ]& R6 D+ N( w2 e6 [
  20.     }5 M; ^  F& z  u0 ?
  21.     else
    ( X0 f8 W- g6 s) X( F3 E* r
  22.     {2 k: m- i2 ^( @3 T
  23.       /* 使能中断行0和中断行1 */
    3 G8 D7 E; y% D; c' s8 @
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);$ t* z1 Y7 l! \* f! [0 {' D
  25.     }+ `$ F& k* s5 y; \! P" q8 F

  26. 7 C" u' h/ K0 d% Y
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)0 j( V* V2 F( B* o+ i
  28.     {
    6 o" k* p9 T( `6 Y- F
  29.       /* 使能Tx Buffer Transmission 中断 */
    9 ^* C7 U$ d% T2 ?" |
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
    5 A( @4 Z6 h" {* ~) @
  31.     }5 N9 Y6 d$ `& l, Q, p/ I
  32. 3 O( P- x1 D" Y
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
    ; `6 i; x$ f' \' i- z- ~
  34.     {6 H* c- J/ `( X% }; V% N
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */
    : |% S6 R& _' o% ?. M& D
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);" S/ T% S; I. m4 |; ]
  37.     }. o& V" S0 a# H1 k' X* b8 X& I8 ?

  38. 6 I  u; C8 R1 \9 Y" q1 l8 u
  39.     /* 使能选择的中断 */, T/ T$ z' F5 {0 q
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);' ~0 Y; H7 N6 d0 I% U+ a& @

  41. - B  P- b  f4 B( |6 p# ~
  42.     /* 返回函数状态 */' Y$ Z/ a) J# Q4 `: ]$ S
  43.     return HAL_OK;
    3 r4 ]9 s! t: {6 S
  44.   }; L+ r# F6 s; a3 Q5 \( ]
  45.   else; X. {' p& P) J* K- C
  46.   {8 D6 Z+ C. b. E$ g8 P  r! n
  47.     /* 更新错误码 */
    6 S3 U: w7 ?6 C; G
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;6 H% k! b+ K) s$ k& x
  49. 0 h3 b& Q/ V/ }4 U* w# {; i) u% V
  50.     return HAL_ERROR;# D# U, z/ }  S3 y9 R
  51.   }, W* J4 ^" V$ k- J
  52. }
复制代码
3 n1 L" n" ?, C6 R& a: v
函数描述:0 s* q0 K% T, R# o3 q" u

0 E1 j$ e# J: k& i$ B3 o; A8 U8 r此函数主要用于使能中断。
! H5 N/ p" x" A0 `; U- h
2 ~1 z1 H( F1 j9 V( Y" m9 f函数参数:- T# n/ n' x: h! k% N4 S* d

5 J7 S) m/ s/ `+ ~* N. e; O/ C1 n4 u- w) j  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。. N( e( n! _" d6 ^8 k( [# s) M
  第2个参数用于设置要使能的中断,支持的参数如下:- ^' j. |/ _$ J5 w" ^$ [
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  - {& B) @) n! f
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */
    3 G5 t, o9 _. p1 [) a$ E) B
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         8 W( ^8 f; O, M3 D6 a% e4 r; q
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */
    * ?+ W5 o% ^- B+ E) F' _& V
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer   a+ @( X9 ?. P& z" B# y. y
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
    + q! L& v' o/ p
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */
    9 m! q' z5 @6 Q/ F/ s$ `2 H" B

  8. ( s! n% R# J) E0 w  I  u
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */* r( N4 y: G6 f) F' d
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred
    2 W8 }. }6 }6 n# ^/ ^: `( Z
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */
    : z2 \5 }6 b4 ~* D
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */
    ' B+ [* Z' E, u5 J
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */( _. p( |# p. A' H
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */
    : w* P6 `- i+ \

  15. # I9 `5 l8 V' H/ @* A
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */
    % Q% W3 y& H7 ?" N2 N
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */
    : q  {1 T# ~3 j( P8 Y
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
    : R" Q; q( Q' q1 y/ k5 E9 [
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */
    : G0 N6 p8 ]2 b7 |2 H: Y+ ^
  20. / E. j  ~* t' {
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */$ c* W0 j1 P* A  j/ Y% Y8 B- |6 e( T
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
    & f  `6 C( }! @$ j( ^/ k: J
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
    . q) i4 X6 |& T
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */3 N& N  i4 f6 T6 d# J! K

  25. + Z4 z* G  g. q/ Z2 ~5 J
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              : j- a% o6 ^2 m- m% o, n
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
    4 ?* K; @; _9 S1 U! o
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
    % e7 C0 C* [6 ?4 @: z
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     # |! ~, `$ e  y
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            $ [" O# t, z- D
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              8 S6 n" E: M& P( _
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
    " h/ H- A- c- d9 d- D
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */. t( ~5 c- ?, ]
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码

1 F6 |5 s$ ^/ @1 R9 f  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:# p7 }* ]: \2 K6 C
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
    8 A# n1 U: z/ S* Y8 e
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */4 ]# j2 Y; ]" e3 J
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */0 Z' G; J& M% s$ v: ~9 k; h
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */( X1 j  s. G; {2 C/ H5 A5 n
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */
    ( a6 i- k% }& b- G- n& M$ I
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */2 \) s0 U7 y9 r- v  A  e# G, W$ Z
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */% C8 f8 D% [/ O9 Q
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */1 ?3 y2 C  h2 w' s! _# j
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  *// T2 p: I4 q' W) ?
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
    ! K- F! f3 `9 N3 k  O5 U
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */
    - o# b9 o  D* C# q# L7 X8 j6 f
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
    6 s" u: ^) E4 Y7 |3 L
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
    . N, ]% Y) Y) C" Z
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
    ' F. }5 |* R8 Q* F, ~
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
    ' ^" f, O) A% f1 e) Q, l( E0 N7 b
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
    , i$ w6 k$ t3 v) c: Q5 b' f7 d
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    1 V" t. Y0 z5 I2 }: Y" K1 E
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */8 V2 s7 C3 w& a
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
    4 n! q3 X$ s, ^/ U
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */5 \0 Y* t5 w) V; g; y
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */0 W" K" p6 g0 f5 }
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */5 D+ b0 v- E% X7 a" D3 q2 k8 R
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */
    * S* D1 B. I/ f' r
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
      t) N1 n, A( S7 m. `9 B0 M# @
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */# T( n1 A: o5 `3 m
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 *// o5 t  U, L& ]0 D9 p
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */; I" L( }2 S  [* H
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */
    ) g( x( U' w! N6 F3 o
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
    ' B4 X) V4 P" |! o; k
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
    / m7 _- t% Q# }8 A
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */7 F' k$ L0 u5 ]- @. ]( z
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码

  B* p4 b) |( W0 j1 _( x9 A如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。3 Q" W" p; `" x; k, m* Z

& E! D, C# S, `- Y% n  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 L7 T: [) D1 K, Q7 O5 b! U8 l
使用举例:
$ Z9 U1 \) q2 D1 x* x% u
0 }& C% X# w% O  L: p  _FDCAN_HandleTypeDef hfdcan1;" ]" D8 G- G' \( v. P2 p

% v/ O0 W2 b/ F( C+ N, `/ U# A/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/8 X, k6 |2 f: V3 t$ I- T  N
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
- D. a$ b9 \. J) Q+ K6 x: @' l  O  C91.4.6 函数HAL_FDCAN_Start1 j$ n+ I. o! w( A; }- ], y
函数原型:: J9 ^9 |" ]& [7 L4 }
+ J* c, f9 H  t9 I/ R
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)
    9 B- h$ V* ]: R( |6 y+ \0 _4 n& ?
  2. {
    7 m; I1 `# w9 A$ y
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)3 J. U% C; r0 w( t# e$ M" ~
  4.   {
    " H) O/ R8 k7 e& Z1 s
  5.     /* 设置FDCAN外设状态 */
    ( a# B" v- }/ p0 d5 k4 v$ I
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;% X; W6 B; b$ |5 E8 d: W$ H  z
  7. 2 [% O  {7 G+ j5 J. o2 ^' x
  8.     /* 请求离开初始化状态 */
    # N3 K" ^+ h3 p2 L% F: U2 ^' g
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);4 U( C7 q! M1 e1 h7 i; Y

  10. 6 u8 A3 |  C, M' U/ J4 m
  11.     /* 设置错误码 */( G& T/ b" \8 K: Z, R( c
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    1 C7 E/ ^: p. i2 M: Y
  13. $ e* R9 w2 E" ?  ?2 u* t( `% \: ~
  14.     return HAL_OK;' {6 V! i7 K! `: T4 Z
  15.   }
    / C; Q1 L' i2 h. z, w0 k
  16.   else4 X* d+ L( {' m+ z* ~
  17.   {1 Q) R$ x- j5 p9 [" M
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    2 a( y6 Z; c" {0 n" b7 l

  19. - G* t# I4 a, N- Q% T0 Y% P! }
  20.     return HAL_ERROR;
    $ O' R; _8 R& m
  21.   }
    ! g- r9 ^  f5 E7 z
  22. }
复制代码
! l7 g& C) T2 j: t, g  k" D+ X( g
函数描述:
- G0 H5 v8 Q& j. e. [: q
3 R" f# Z8 `7 i& U此函数主要用于启动FDCAN。
! m$ N# [2 V, C7 T$ ^
+ w( E0 K2 F$ J& r1 v5 A函数参数:) H& }; }- r3 P8 ?3 `3 u2 Z# Z4 }; P+ X
" C1 C5 Y2 M, o' p7 C( j  d0 B  F; i
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
# V% n, ?( v1 K6 Q: F  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。0 g# F1 `; ~7 a/ B- t
使用举例:
6 g8 r( R% W! Y# m- ?  M% m! \# |; k( s
  1. /**) H; a4 M) t, c+ ^& O: D
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.1 T; J3 r) ?3 ]: @& P. ^* D
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit) g% L2 K- g. {+ Z/ r; R' [
  4. * @param  WriteAddr: Address from where data is to be written" C$ l1 q* f( W; h
  5. * @param  NumOfBlocks: Number of SD blocks to write
    , t1 h. Y0 y. V+ a6 _% o) H6 j% {
  6. * @retval SD status% B' I. |8 s4 w* `- u% n
  7. */% Y7 Q& Q' G3 ?7 c" ^# ~8 l0 S
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)  O  \/ y* J7 ^# K% D0 s# e
  9. {3 }9 _% D5 h* c  T1 N" |  r
  10. 7 H2 \+ X0 [& n" n/ n$ j/ L5 H6 I# N
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    0 e7 c* ?$ z- z- a! \
  12.   {
    ; {/ M. F% J+ \: H1 j" I
  13.     return MSD_OK;
    6 w9 f% q& S: q7 p
  14.   }
    3 y' G1 w) P& }4 R: t6 G
  15.   else
    - v* L3 {  Z' ^$ B
  16.   {
    + F6 f# k9 w- k- {' V- }6 W2 R+ C
  17.     return MSD_ERROR;
    & T6 j3 {7 ~5 b; s: [9 v, N$ G
  18.   }# _/ h" R3 r; B1 m  H0 C3 q8 V  r9 C; a
  19. }
复制代码
. r/ x8 H! \& s/ M
91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ. `) R' q7 `& X
函数原型:$ q( I6 y8 h" [
' W5 b% o, O7 W" m$ {
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)2 n4 B" v( W! L: Z
  2. {
    0 ^/ h1 d8 I. o' ]* _$ Y8 _$ [
  3.   uint32_t PutIndex;
    1 ^# l* w* L7 [4 L/ u3 E( e
  4. / n' t% D$ C# s3 V+ t' w
  5.   /* 检查函数形参 */
    - }' g1 p7 }& X- a5 V- b1 n" c- c
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
    + H1 Q1 ?( k! O
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
    % t5 K; I2 L- F% k& g( f
  8.   {3 p' |& i+ d9 R/ `1 d  X
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));: U  b( M% O$ Z3 H0 N
  10.   }. D' R3 N/ k8 Z% k3 G& ]
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */8 @; [; t1 y. t7 \+ D# Z
  12.   {
    ' ~( T$ H' G1 Q) K' Z
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));
    ; q% F* d9 @  v7 v
  14.   }0 u0 W7 c4 ^+ `# W$ s/ s
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));7 {" h( I' n/ E  Y7 F8 ?
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));& |' P* `* J1 K. l( d8 v4 X
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));0 Z/ e7 S: U* G2 Q6 V! c: C0 g
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));! H( n* ~: t9 x  Q9 V4 j) J" k3 U
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));1 r  J2 _9 b3 k0 t; `  R, F
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));& j) a" b# k) t, d/ d
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));  t! A4 G( {8 F5 e) i9 q
  22. 3 L) h4 Q* A3 |( ?( R
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)2 l' k! L6 E) r! e" ]
  24.   {
    & w' a$ O, l  ^+ `$ ?
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */; v) w9 Z! H( ?0 o/ ?
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    " {: Z* [# w* U# i( r
  27.     {" f0 D. c! k" J3 r, _, H
  28.       /* 更新错误码 */
    ' o! Q- |' @4 S8 \3 D2 F2 x8 W8 B
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    . J  V; c2 U- J# r& L1 y# V' u7 @

  30. , m$ d* P* B' Q! m
  31.       return HAL_ERROR;6 N& k) P" Z8 R1 J% w9 `
  32.     }# V0 s6 x5 P8 F! o
  33. 6 K# R6 {0 r* |8 u
  34.     /* 检查Tx FIFO/Queue 是否满 */
    8 X4 T, k( \# b" I) ~! U
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
    + [/ q1 t3 I4 a$ K0 O9 W
  36.     {
    0 z. h8 z1 P4 L7 S& L
  37.        /* 更新错误码 */
    * _3 z2 e& [5 \. ]0 ]' v6 ?9 C
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;
    9 j$ f  ?9 s4 r# S. i

  39. ; ]5 Y2 i3 y4 f9 i' D
  40.       return HAL_ERROR;
    # R% }# q/ ~, ^1 O7 M
  41.     }
    + Z) B' m5 O2 C# R# s
  42.     else1 i; t0 ?4 M- [" \6 B
  43.     {2 W+ O$ F( k0 c9 u. G
  44.       /* 获取Tx FIFO PutIndex */8 ^; u7 e* d' K+ p! L
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);* ^7 `2 E1 v9 V/ W
  46. * q6 G" t- g* E% R( ?. T- O
  47.       /* 添加消息到Tx FIFO/Queue */
    5 `1 P+ c- N; ?% U$ s
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);; F0 C$ c, k! ^  c
  49. ! a' b) l2 |. v% b9 h2 G6 d* b
  50.       /* 激活相应的传输请求 */0 v+ ~( Y3 Z7 _5 [$ E4 Q
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);
    5 g. C( Y# \: H' ^- ~+ b* x2 K! N7 Y7 B
  52. ; E# ^4 }% q) M9 U# Z4 z
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */
    # |& d+ s( ~, b6 u0 G
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
    6 Q$ x" q( }9 {- u/ Y- w% {7 J( o7 p
  55.     }
    1 e/ G3 X8 m5 C4 h+ o

  56. , v! ?1 p, w: u, |
  57.     /* 返回错误状态 */6 S- W! G. \$ r* N* z/ G
  58.     return HAL_OK;, n- F$ J1 f; c0 c( t
  59.   }
    # `" Z# H# E# D. y" v# L$ q
  60.   else
    ) M; G  \" _2 e' S
  61.   {
    ' B3 }8 s" m+ |% i/ Q3 {3 Q0 C
  62.      /* 更新错误码 */
    $ F! X; I$ J, h0 Y2 D% j; y
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    - ^* B0 J( e2 e/ a* o9 o5 C
  64. - P6 X. A3 j0 O- y6 s- _& Q+ k
  65.     return HAL_ERROR;
    + L1 _$ o" M/ z2 P& _2 z! a
  66.   }
    ( D2 h3 P0 {, y8 i$ o( Z
  67. }
复制代码
6 L$ _- f8 o7 w8 O& y, G9 G, s
函数描述:
5 k9 D3 {; ^! h: `0 V* K
& ?: t/ n; K/ @  u: U3 K此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。$ `) n# k( ?7 w/ L1 B$ q- `) s+ s3 x

5 J/ ~5 {" |; w8 q1 m* X函数参数:
% Y6 _, r/ R1 Z. O6 @( H7 d+ }
/ j# Q9 b! n. N5 M. U, r6 E  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。5 m# B: E/ z/ b/ U. G$ ~( p
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
/ U+ b, \5 e$ s# E" \$ h  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。6 v7 i; z5 b! K' R; m
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
4 s: Q2 J- Z$ L' M4 i" M6 i! k使用举例:- P/ P& K% l1 g- k; |# D  Z
# A1 t' A1 g' _/ b6 T$ c2 _; l
  1. /*+ L; g+ D0 e5 t& c
  2. *********************************************************************************************************
    , }9 Q& q6 D! d6 l/ G4 P% l5 q9 V
  3. *        函 数 名: can1_SendPacket# b7 e" S7 f7 `  D( g6 s
  4. *        功能说明: 发送一包数据  }3 m* W: I2 n1 {7 T6 Q3 N2 c& d( u
  5. *        形    参:_DataBuf 数据缓冲区' s9 _) j1 H1 ~4 h" ~9 @
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节2 V* U6 `; o; e( w( f, Z, M
  7. *        返 回 值: 无
    ; G+ B! B4 j" }6 E9 I5 t
  8. *********************************************************************************************************6 n- D! B' u$ N! ~. U' g& k( m
  9. */& O' j$ v7 v. ^9 B' X# P) r
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)8 J3 n) z, J) g6 j* _
  11. {                7 k3 U6 n. V# `$ X; W
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};
    + @+ D3 j7 T9 H; Y
  13.         : R; {" k, y& D* |7 C" v
  14.         /* 配置发送参数 */9 V5 h/ H# l# y# \0 T3 H2 P9 J
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID *// E% R- _- @& C) O0 K( n# i
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
    $ C3 R* x3 G. w/ {0 N( E+ k
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
    4 p9 Z" f, i6 v& q* n  \! R5 r
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */
    2 b1 }2 T  k9 |- _& s1 L% ]
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */% q( w% g- _( k* C+ r+ O
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */
    2 P, c, K& K+ K* T
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */
    & s( v( {2 F0 x) G  J
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */. ?( o  q; e0 g  ~% ^5 R
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */% K7 V5 \5 s' O* F
  24.         
    / c! X. Y9 g- z$ R) p( l0 r
  25.     /* 添加数据到TX FIFO */
    8 A1 O5 H; \" z5 K% F
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);0 J5 A% k+ q7 Q& X0 Q
  27. }
复制代码
$ v# i+ O. L0 P* l: Z+ e& a
91.4.8 函数HAL_FDCAN_GetRxMessage
6 k+ x  G1 r4 s/ E1 y9 q函数原型:' T1 [, s, d& o7 _2 h" w# t

6 ~6 X0 D4 L4 d, l7 @1 Q6 ~! ^
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)
    $ T" c: I; z) W# K3 M
  2. {8 x- J$ a/ z5 s6 j- x: m# l
  3.   uint32_t *RxAddress;
    . @2 F. [" v8 @/ M3 k6 L& V3 K) L
  4.   uint8_t  *pData;
    : C4 ^( ^, I- b& e# D$ S
  5.   uint32_t ByteCounter;
    $ Y6 _+ y. {9 F& t% m& u' _
  6.   uint32_t GetIndex = 0;
    + H. B& Y$ v4 w( u4 Z
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;( o: r8 y! |3 S/ n6 G5 q2 V

  8. - H0 C& y1 r9 W+ |
  9.   if (state == HAL_FDCAN_STATE_BUSY)
    " c$ b/ M5 m. v
  10.   {
    ( m: L# y/ I! f6 Y* B
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    - r5 E$ U' q- P9 [3 O+ B( ?: m
  12.     {- k+ @1 o5 @! \2 ?8 y  q) m
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    4 s5 R4 W) o3 F0 i6 g
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
    ' d2 ^) o& B+ f. `
  15.       {
    ) j! q" f4 c2 m  I
  16.         /* 更新错误码*/
    ! F% \7 R& w3 v  L8 H3 Z+ i
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    " I. G* v* z8 ^

  18. 3 k: k% ?/ p! \/ [, A3 P  Q/ {
  19.         return HAL_ERROR;' l+ A0 F( s8 t9 k
  20.       }0 ~- P1 r3 ]" ~8 d- H. E) J% \
  21. ; |- b9 }% q+ m9 z8 ?, `( X
  22.       /* 检查Rx FIFO 0 非空 */
    0 w- n# |) y3 A' F. d
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
    : d6 S+ y3 E) H( G
  24.       {
    . P! H/ L) ]; ~/ Z9 m
  25.         /* 更新错误码*/" n) d9 e3 o/ U4 X4 S
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;# }  s( A* `  P% }4 A

  27. 6 Q7 c, O% p' ^/ h& r; m
  28.         return HAL_ERROR;5 x% j3 l( Y9 N9 ~; Y0 L$ E
  29.       }+ e) ~  ]* z( B; r6 T5 C
  30.       else
    $ \! \0 n% T, W2 _0 o
  31.       {
    6 v7 ^/ K1 z: Q+ N+ n+ J
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */
    0 u8 Y4 w6 N& Q0 y( y
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)$ }0 E( W; c; X# f
  34.         {
    9 R. {. j0 Y  u7 m4 B
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)+ ~0 I2 H9 B' h9 a
  36.           {
    4 E2 M6 [* R& `; |( ?8 Q6 p! C
  37.             /* 开启了覆盖模式,丢弃第1个数据 */3 ~8 B! H& D- G
  38.             GetIndex = 1U;
    + W8 Y5 u5 n( g# {% t- \
  39.           }, e4 p( ~5 J0 m9 X: f
  40.         }
    / C5 u* s% f& Z4 |3 b- C

  41. : Y" ?8 t' Y9 Y8 k' w
  42.         /* 计算Rx FIFO 0 element 索引 */
    + T. u% F) _0 p/ d) F" @$ I8 t$ H
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
    $ V4 W& F* e2 O4 s

  44. ) X- j$ {* Z& c9 u7 h2 ?5 I5 z2 R+ ~
  45.         /* 计算 Rx FIFO 0 element 地址  */% k) g9 w2 z5 S2 z5 s# n
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));
      K4 }. N/ c- D' A
  47.       }
    7 f' C! l" B4 F* {5 J
  48.     }
    " w* f2 F% v" ~5 f
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */* r2 [% N  o2 g4 I& i3 s3 [- K
  50.     {5 M" Z2 b6 T8 n3 ^7 t& q7 h& @) Z  b
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */+ ^3 T8 R+ {, h0 w' {8 F4 x; S# V% v
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U): q3 H5 F1 I4 q" H, u% G3 n
  53.       {( E/ _! E- I2 E' N9 T
  54.         /* 更新错误码 */
    * f) F- ]6 r, @$ i( t
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;8 `% P% L5 a8 p

  56. # |5 Y; ^2 O0 Q6 G& e' [0 }% y
  57.         return HAL_ERROR;
    / f4 \  i3 y' R2 L) `" o( H
  58.       }3 ?8 ?; ]% |6 f0 m

  59. " Q; p5 ?4 a# L; F& D5 u* Y
  60.       /* 检查 Rx FIFO 0 非空 */
    + C1 w% }; D% a% v
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
    . G: [- K, W1 e
  62.       {/ e4 v' ^$ q3 W1 ?7 e' p7 ]1 R8 O4 ~
  63.        /* 更新错误码 */
    9 N+ G! V, l. n
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
    2 O3 j" x% e$ ~0 x
  65. 4 z' h, ~0 U$ E5 {
  66.         return HAL_ERROR;+ @! X  w8 I- a( x# B7 R/ S
  67.       }
    . J- l2 p3 d+ b) E- y+ f
  68.       else
    8 `; R) y9 ~3 t. P  x0 w* j1 |2 e+ z
  69.       {
    ( j% P# G# K6 C0 C  D3 b0 I2 B% u
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    9 M0 g, H& I. L, n1 [% R9 `3 L  R
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)0 {5 s/ w" |- ~6 n8 Z4 h8 W
  72.         {$ E' l0 G% o( T3 q
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
    : h% i4 Z) X: {# X$ a
  74.           {* P+ D) d& y5 {3 }9 O& B3 D
  75.             /* 开启了覆盖模式,丢弃第1个数据 */: X# b: M1 Q6 F& D- D8 ]: r" N7 g* v
  76.             GetIndex = 1U;
    & I; c0 y! J6 Y5 f8 ?
  77.           }
    7 N2 {0 `0 j3 }1 e5 \
  78.         }
    - F' {: }0 Q& _

  79. 1 z8 J/ @5 [" Y6 E; o' H
  80.         /* 计算  Rx FIFO 1 element 索引 */
    ; M4 i, C: P5 s/ J0 N* C( ?: k
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);9 N- T$ {2 m* h. }5 ]$ x

  82. . N, c& t3 ]- J. {! l. p8 }
  83.         /* 计算 Rx FIFO 1 element 地址 */2 f. `6 x0 s4 [/ I4 Y, T
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));# c  y# i6 M3 y. w8 D
  85.       }/ I) l" Q) V7 J& F9 m6 N8 D
  86.     }' ?, q, D" s/ \( |
  87.     else /* Rx element 分配了专用 Rx buffer */
    ( U5 g! k% Y. ^/ x! b
  88.     {* f7 N" x1 |9 i% c2 K4 g/ s. t! u
  89.       /* 检查选择的buffer分配了RAM空间 */9 ]$ ]  E: |# u
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
    * P( m/ @7 j6 j( c. @, \' ~- x$ W
  91.       {
    ) n( t; A! p" _0 z! ~. J% G
  92.         /* 更新错误码 */2 u, _) |* w+ [4 o* X7 h* z" E
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;% Y4 x' s$ F7 n7 @1 Y
  94. " A  K. V& @* g& e" k
  95.         return HAL_ERROR;3 r# `  J& `/ U
  96.       }
    1 ]6 j7 D4 E4 W; z0 T$ F
  97.       else2 a7 z+ w2 F: p" g
  98.       {
    ! L% Y" J: A' v
  99.         /* 计算Rx buffer 地址 */4 U9 H3 w8 e8 L) s/ D
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));  c1 \6 v8 ?8 x  _/ j9 v- B
  101.       }1 W8 f9 _* m2 n$ b
  102.     }) w. A& e- G. U0 L8 W; W

  103. % T% m/ \. S- y3 d- E3 @- [1 e: B: `
  104.     /* 接收IdType */2 N+ x2 W0 T8 J) ?
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;: e# L3 G  G1 c& h5 y, |

  106. 2 c* }" p: ~8 B# F& w% Q7 S9 B# Y
  107.     /* 接收Identifier */
    / V/ Y5 D9 L) m: ~& P0 g( x  T* Z
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */
    : ~( u; O) n  l, t9 z* v: H7 i
  109.     {
    - ]8 i/ k, J, ~/ I
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
    , d7 W5 f) r) Z5 s- m
  111.     }# I8 j0 }5 w, m% W2 a! }
  112.     else /* Extended ID element */; ?$ J7 E- ~2 P6 d' [
  113.     {) `$ e: R. B! Q2 q; x
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);7 @6 r9 {3 ^& ?6 S3 h+ g+ u( z
  115.     }
    5 c5 R0 Q' G: n! C: C; B, }. i5 H
  116. 8 i. V! I9 _+ v. q
  117.     /* 接收RxFrameType */
    ! c" ]- w( Q& a* k* l
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
    ' T! ^, @  X7 C: H5 H9 Z
  119.   e. Q$ Z) C; W- I* q8 T
  120.     /* 接收ErrorStateIndicator */+ [; E0 ~9 N+ r' n+ f
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);! g" h  Y/ G0 G, [3 L- z& d

  122. 2 x6 j8 O+ o% F8 {: s$ X3 J/ \- u
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */
    * U. U1 D4 K/ J3 J
  124.     RxAddress++;
    6 T0 W! Z; A* {# w& w

  125. 2 }( m3 y( [/ A5 J- ?
  126.     /* 接收RxTimestamp */
    ; C7 O/ W, r$ ^/ G( ^, {% l4 ?
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);  c: p$ H  n6 ]- Z& f3 p" K
  128. 0 C  m2 g' M6 k- N+ d6 a) n1 |
  129.     /* 接收DataLength */
    8 u1 U* ~: b( A
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
    % l2 C% X; f9 H

  131. , _% n+ w6 K' n. [3 E9 t
  132.     /* 接收BitRateSwitch */9 \$ d6 W8 t. R( x" d
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);' ^5 @7 [- u& H( C' r$ H, I

  134. ' B" u# c" z. S, U2 g) J
  135.     /* 接收FDFormat */' o* ~: `9 M' T3 G, S' \- i
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);/ S" s4 B+ l: B

  137. $ f- x, M# r" q* t
  138.     /* 接收FilterIndex */0 {: v# V9 }9 @  o" v2 R5 P
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);
    ) o# M$ x' R" Q! u  h3 o2 p
  140. 4 q& ]% ^/ h3 B/ c2 ]% @
  141.     /* 接收NonMatchingFrame */4 Z# u. e- y( j( ~4 C4 }$ M
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);5 Q; k: w, y9 E8 d. T
  143. % x, e/ J' a9 e+ D$ l, r
  144.     /* 增加地址,指向Rx FIFO element的payload */2 b4 ?6 P# j: \# T5 s
  145.     RxAddress++;
    % w: r; u6 [" U% e# f! [6 n

  146. 4 L1 v/ f) p/ U: a; }% J+ S
  147.     /* 接收 Rx payload */
    ) C4 d2 ?/ J6 Z1 u  f
  148.     pData = (uint8_t *)RxAddress;" D/ f4 ^3 L: I: u
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)8 ?1 a: ~$ C% Z" L" Q3 ?
  150.     {
    0 O9 |* i5 I2 |3 L2 Y4 r1 j
  151.       pRxData[ByteCounter] = pData[ByteCounter];
    0 i3 c9 }) m- [) s2 F" m. W
  152.     }
    9 q0 k% h' ]! _/ h' o' |( ^; K+ L
  153. : \$ g. o, T' c" i) J0 r
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
    4 Z' }8 s' p% `! i# y0 K
  155.     {$ D" t) }" ~! m" n
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */+ v1 W1 ~- [5 L7 H, Q
  157.       hfdcan->Instance->RXF0A = GetIndex;3 L' n, Q! h# M! {/ b  x
  158.     }6 r8 V% |& s$ p" F& l
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    . Q! Y6 f  H7 R) [
  160.     {! \# E  Q# j/ D; Z' ~" m
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */% B4 p0 g% `. V1 H9 z; W
  162.       hfdcan->Instance->RXF1A = GetIndex;9 b& H1 `# E4 [3 J9 K) V6 ^7 R) S
  163.     }6 j; [$ d! z  h9 G& a
  164.     else /* Rx element is assigned to a dedicated Rx buffer */5 S1 L( A/ [! a  i$ |) [1 M3 |
  165.     {
    - G' N8 ]$ c- Z9 W/ @- y
  166.       /* 清除当前Rx buffer的新数据标志 */
    " a$ X% V) e. x& {- j* D: U
  167.       if (RxLocation < FDCAN_RX_BUFFER32)
    ( o" g' W; N  U7 Q0 Q6 Q3 L; G! S
  168.       {
    9 D  W9 n* Z' A+ s
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);
    " [  R# P  e7 G5 \, t
  170.       }/ w, X' i4 g& ]+ b  n8 h( G3 t
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */, E! ]% U* D: ^1 n: g" o$ S+ P
  172.       {4 S5 d6 r+ X! u3 c! Y
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
    / j8 i- [% l; q( h+ u- ?
  174.       }) h3 M* \6 p; S, ~; c
  175.     }4 r5 T- `( K' q% i
  176. 3 b/ ~5 q7 `7 b2 s
  177.     /* 返回状态 */3 }$ Q6 V3 J, Q: T
  178.     return HAL_OK;
    8 k* Y7 S: }2 }3 J
  179.   }4 o, Z1 R8 k; f
  180.   else. r/ P4 q5 R) N: \* i3 s
  181.   {
    6 X5 ]8 T  M/ j& N0 z7 x% H! R. F( z+ X
  182.     /* 更新错误码 */
    4 w* H; T) ^- e7 S
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;* j* x0 ?( ]$ D6 F0 a; F* `. g

  184. * z8 Y  M& A  Q! j
  185.     return HAL_ERROR;1 R0 D/ D$ G9 `1 ^; y, a% c% |
  186.   }
    7 }4 i, ?$ k* j( Q; l. G
  187. }
复制代码

) }( [2 w$ h9 @2 S/ i函数描述:5 O2 D/ F$ `- K
! l* I, t/ \, O5 O; K, Z5 @, P
此函数主要用于获取接收到的数据。# ?! z7 d/ T. k2 p6 T& g
0 E4 w+ b# ~9 `
函数参数:
4 m8 E( M; Q; X$ i, N( h8 C* u
3 Q# Q/ J$ j4 M# @; t7 ?" ^  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
# g0 A5 i! V6 C+ S6 ?  第2个参数是读取位置,支持如下几种参数:1 j  {0 e7 `9 J$ H9 N
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */5 _' N$ d- T( q2 G, Y
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
    ! r3 [, K" [1 p
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */; R3 H( W/ D2 U2 ]# G
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */
    ; w1 V! ]# O$ B' g& Z2 I# e. q
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */( N; L' S* Y3 F5 X, g. m/ Q
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */. K5 x4 ~1 y0 m# y. u
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
    : N' Y! ?3 B7 E  \5 I- L2 U6 J- T' D
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
      E( J, P" W6 h$ h
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
    / S7 d% H; b: p/ I( @, T: c
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    / `( z  [/ ]% H
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
    ) V/ h& {! F/ R3 I
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
      E6 Z0 b2 f8 \+ d! f3 X" k( T' }7 T" S
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */5 F# q! D* Z# u
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */, [1 y$ T( ?( V- q7 C, B) C( I
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */2 {8 s4 V: o2 P4 Q, T) h; j: }
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */' H6 `! h! a1 H- W* u/ ^
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */
    & @0 {2 H, s; g
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
    " p6 K7 W( d9 ]8 q$ G- l5 ~1 G. Q
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */& k: u; R" n0 C# ~
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */+ i2 R3 e3 Y& P2 v' Z/ @' q
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */
    - P& e! b, i/ ]3 U  w, ^* ~
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */
    7 h, n! _, ?6 Z( e
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */2 I& k  T* n2 _4 S5 S. f, f
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */) f4 [2 m9 U  {4 `) b
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */
    1 i5 ?7 v) X# p
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */# ]$ T$ Q' x4 h
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */& g* ^9 w/ K9 p5 L
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */" k7 W" y) {8 I. r1 B$ T. I7 b
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */* Z" B: @- G% q3 x1 g
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
    ( q7 ]& {! Q* ]* e, \  O' @
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
    4 _# d1 t; p4 ~" ?$ e2 A, d
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */
    ! ~+ o# J; F8 b  ~+ Z8 i
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */! r6 W+ `) z6 S& k2 [' E
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */
    ) b3 u( p( m* _+ H6 t
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */  @! F, j- s# ~9 W
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */4 _7 s/ ?# y9 h: V) W' L
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */9 A1 i5 `8 R: [6 p: F& j' h5 a
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
    - l, J( h4 W, t3 N% b
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
    * W5 c8 M. a1 D- C( p) J& |
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    2 r6 b  B9 i& p4 K
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */6 ~8 r% O) B1 a: y9 d* _% y' d
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
    % i6 [! p: F; _
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */8 Y) w) x. O  x7 }* H" s- {8 `4 K
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */( Z$ c. Q/ _5 y$ H1 n) ~
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */" |9 Q: b8 V$ c' X2 v
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    8 x' o' q7 Q% n) ]+ E; V
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */
    : g8 K; A: B8 V% j* V3 d
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
    4 D% Z  Q9 }! I; L) R
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */3 e  _$ m( P0 j4 O
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */" O: a+ @& Q, j( N
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */+ C' V$ j, `# c  A9 S7 @/ c, Q7 |
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */
    % `' e  `+ A7 E7 H2 \- s+ i
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 *// ]- U  ^, T1 S4 z! D
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    : ?7 l% i/ Y* j0 P
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
    6 }$ E5 d/ D3 c: w/ L
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */& a# m- d! H+ k& A) V" M
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
    / g3 v6 l4 K9 D* x1 b! V
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
    " X# B, N/ d# T( M9 \6 g
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */+ q8 q8 b$ q3 t* D! h" ~
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */
      h  c* V8 @' T4 f2 `7 }
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
    6 ]8 m* _, C$ A- O. V
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
    0 e. Y' q8 q5 }* c- A- S, M
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
    ! z$ V1 {2 H6 |7 W
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */& z8 i  @1 z& x1 p2 w1 |
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */
    : }  r5 i3 e( z8 ]! W6 P
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码

! P: _& J' h* Y3 D* [  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。
9 e! u5 K* G$ u' P5 u  第4个参数是数据接收缓冲地址。$ }: _& R3 K5 f2 S
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
, ~/ r' [3 d* f9 g% t) J使用举例:
: a$ C: l1 t0 X$ M6 Y1 B; K0 |6 M, o& d/ U
  1. /*
    ( z7 `0 Y' M* D. _7 b
  2. *********************************************************************************************************
    1 o' z9 h1 @' |# G2 @
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback3 u  x9 z4 Y* I5 o6 P& f
  4. *        功能说明: CAN中断服务程序-回调函数
    0 ~, L/ a8 g# h, t* k0 {
  5. *        形    参: hfdcan0 b# \3 e0 W/ K5 m" H
  6. *        返 回 值: 无+ Q0 y5 I9 _% x) Q+ e0 P
  7. *********************************************************************************************************
    & H9 y, `: Y% r
  8. */9 f' F9 }1 M* S$ ^
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    ' I1 J; \* p. U. z+ [) Q* o
  10. {% G0 P- {3 B+ F& a: x+ ~
  11.         if (hfdcan == &hfdcan1)( `4 O+ _" C8 l, d+ ?
  12.         {
    % u8 ^) g# ^* A8 ~8 w/ H
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    + ~' a& d* S, h6 t0 n- u
  14.                 {
    6 @: F6 k% t. V. Y# ?
  15.                         /* 从RX FIFO0读取数据 */3 `2 g- d/ X3 c: ]# S- l
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    ! G. S. j" W6 X3 ~) Z
  17. . F) D* h0 g, ~4 ^
  18.                         /* 激活Rx FIFO0 watermark notification */! }2 G6 N7 ?' Q2 {! V6 g
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);" o9 k; V0 n( @  I3 ]1 D, h
  20.                           l- p/ F5 o" e* s9 }" ]1 u2 }
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
    ) u- S$ ~" V4 i" L# y7 ]# S
  22.                         {5 M( e1 o) y) U+ g% D
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */  w- f. Z8 }7 l& ?) E+ f9 y( @
  24.                         }
    & T& a; Q/ F  M! ]8 K5 }
  25.                 }5 S5 ~4 k1 ?; ?  x0 r4 l
  26.         }. t1 D3 c( ]) o( f7 {
  27. }
复制代码
: l! i2 }1 c- X6 G8 a
91.5 总结
! O& s- d) e7 l0 s0 @. h+ @本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。
  u9 z  M, S& n4 H1 t" A, H3 e
8 H1 H6 n) Z3 W  `, O; C5 C7 D- }& L+ ^% e
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

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