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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示
  F3 [7 \; K7 |0 H  FDCAN基础知识点可以看第90章,已经进行了详细说明
! N4 o" B6 V+ ]3 M  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接/ b; T9 z/ t' K) P2 Y
91.2 FDCAN基础知识# s  }& e& x7 G/ P1 H. Z
FDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。* q  T" X9 w+ w, T% o( ^

) H7 @/ X' Y) t' K0 B* k91.2.1 CAN FD协议介绍; ~6 u$ o& k7 |/ r4 q) _6 e9 G$ O3 Z
STM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:
1 }7 ?% U( f, t6 w# ]$ A
' M" B8 e: C' x5 |(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
# }. W. X$ L" {$ c( I6 H9 z8 R0 ~% P' f2 R$ H; |7 D  _3 F, X
(2)可访问的10 KB RAM内存,最多可分配2560个字。
1 k2 j/ |! G7 \; c+ N$ A0 ~2 j6 y4 X! w5 s7 P# ?
(3)改进了接收过滤。
3 i* V) @2 t+ A5 a
9 R0 _1 \8 d8 T2 G0 q" \(4)两个可配置的接收FIFO。
5 t- ^0 F# D/ {4 {# o
5 S0 }+ b6 c- K(5)多达64个专用接收缓冲区。
6 `5 l: G* v9 U0 n; U
& p! {2 Y) m! V6 N(6)接收高优先级消息时的单独信令。0 O$ _- v# p5 y% w/ h7 M' Q

0 d9 ~/ _( I* k(7)多达32个专用发送缓冲区。; J5 \# Z# `0 s( V. f
: t- @6 W. ^! Z1 `( J9 P: L( k
(8)可配置的发送FIFO和发送队列。
6 j% h$ T4 W$ d6 O- L- D
+ D% s9 }( ?, S! ^(9)可配置的发送事件FIFO。
* R* d% o: n7 P+ ^9 `5 x" H4 ^# K4 ~/ x
(10)时钟校准单元。
5 a7 q6 [4 c8 O8 U% c: r$ f* q" p
(11)收发器延迟补偿。$ v6 U( e$ ^2 r: |$ D; ]
0 o$ t  C2 Z( {, B! X
下图说明了FDCAN框图。
+ x8 b8 k7 B, m" ~) f' c: L" q4 Y) b& C( y5 q2 H
0 R! N0 v4 t  w: Q- V( G( n
f4f1d5cd872648458911e8be8ddfffe0.png
+ W" {# y$ q% n4 F  [4 E

) v  e" X: w- Z/ `, ?. D6 v2 U& e- `! y; g) D0 O
通过这个框图要了解到以下信息:8 @& @2 f' T7 r" G

# j# U5 B1 N7 L5 O0 r(1)CANFD1和CANFD2共用一个RAM空间。
: ?2 y; ^1 H5 b6 r, ~. U
5 D1 x1 a  g' R0 S9 c7 ?  K3 Y3 I(2)每个CANFD都有自己的内核。8 M$ S( u. @; x8 F

1 J  L/ O  o# s(3)CAN内核实现协议控制和收发移位寄存器。$ h) g6 J5 b0 L# u7 t8 p) j

1 l7 V1 i0 g, I% l(4)Tx handler控制消息从CAN消息RAM到CAN内核。* Z4 K! A, I8 B6 i8 p$ i  M
: o. S" r. K& \: R0 }$ e, q
(5)Rx handler控制CAN内核到CAN消息RAM。
# H2 r& \. f, k- z3 x$ C# H0 ], V
, ?% i# _8 r$ |9 R% r2 P) g8 {91.2.2 CAN FD特性1 E5 A" x4 v- O
(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。
6 ^5 U6 A* t- g# p' a, x4 T! a6 d( X! }3 @
(2)提升错误检测,支持高达CRC 21位的校验和。9 M/ A+ N7 F, ]3 M; w

& i6 f- t% Z" R$ q: C( ]6 \' n8 U- D(3)消息优先级。
0 S5 C+ R; A! U" }8 {) R0 `0 S4 V3 o
(4)保证延迟时间。4 z* a+ U, q/ M' b
9 F, G; l+ ?0 N! ?& }
(5)配置灵活性。* }2 c& H! y$ ^
7 q' K9 G* a; u# Q6 S% v$ A9 f, @
(6)具有时间同步的组播接收。# M$ F( R' d8 e$ U$ [. B( N" m1 V5 c
- `! B; F/ |: L3 ]2 q0 B% C" E
(7)系统范围内的数据一致性,每条消息最多64个字节。" f+ k& U0 b, o/ h2 I

5 o) D) r0 A  _9 d& ?2 k4 t" o(8)多主机。
, x- {( Z: Y( K$ Q
. r7 ^! L( y6 B  W* a(9)错误检测和信号。. d* k1 |& G1 r. W& t: R5 d2 |( C

5 t' k3 M0 u/ q6 L7 l0 r+ v(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。% V; ?; X, F5 \7 G; j
1 n; A& B* R- f$ C; ?
91.2.3 CAN FD格式* k3 X2 P' c% i' h
- r0 o. t( l/ ~/ Z3 |
c692adda5a1149b0a6e3d8a30745fd62.png
+ v7 k  r: |* C  i! l8 Z- Y. |

; z* [* N6 B) A$ {. d) n- [  J( d( w; E0 p: M4 h! h3 Y
第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:
' T5 {! D/ G! s6 q" s" p) u, D$ ~/ O, V- T& N, N. B7 P' o: ]/ a/ o2 s
(1)帧开始(SOF)。4 f3 b, S' J, ]7 R! O: r0 y; b( S. q
3 l# Y: o% }6 T! ?
(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。4 j/ K! G+ R$ L- |
" x- D4 c# j7 P3 d7 q& l3 ~) Q5 z
数据传输阶段(The data transmission phase)包括:4 D2 M0 ?2 W/ v) ~( A6 R

; K, y3 o4 s" W2 u3 f. z(1)数据长度代码(DLC),指示消息包含多少数据字节。
' f' \* v$ g; y+ U1 v: z0 H+ d1 |4 t+ }* |2 e
(2)用户希望发送的数据。
! @& |1 `1 k: x! L2 S' o( ?; S% c
0 w* B8 v0 s) ]8 T8 C9 B' f(3)检查循环冗余序列(CRC)。
% d* ^2 u6 g7 k. t5 [# \+ i
) A' m& s( a+ q; h$ S(4)显性位。
! b) G+ v; c; g" @* G. k0 k+ `. \4 ~2 S, D/ ]
第二个仲裁阶段(The second arbitration phase)包含:) r5 B7 ?# Q/ Y% y
+ d; V0 m" v! J! _
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)
7 E( N/ z4 I0 Z! b( b- C
7 V: [! s- P4 A9 p2 k& o* @(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。
& x' b9 H" i' r' s# T
2 R$ F. u# l) C3 ^注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。  k- }( |( d; E# J9 i9 h
, h0 w3 [4 R5 |! P' V
91.2.4 CAN FD相比CAN2.0的提升
8 v. ~. B# V  A. S( |* `CAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:+ ~9 x2 c1 J- c* n$ u, j6 m
, J/ N, S9 T1 z
(1)17级多项式对最大16字节的有效载荷进行CRC。/ h+ d4 G& Z4 Y$ R5 D

0 w' P1 E1 f4 h. M(2)21级多项式对16到64字节之间的有效载荷进行校验。
  A8 \" \# p2 h
% z, J9 B( ~. M. U. d6 J) `# j标准帧和CAN FD的区别:  ^+ @0 g, v+ c9 d5 ?5 ~' I, `

+ O! H/ Y4 w  w8 e! ?# G2 c1 @! n
" g# C% u% Z9 F4 G4 ]( U
050433e4b8fe4f4d91de7eb85d5e6bdd.png

2 N3 S2 Y" O; i8 f# B: f) U
- v6 v0 J5 g% q2 `
1 o7 p& [# o1 k( ]/ t& }标识符后,CAN 2.0和CAN-FD具有不同的作用:
' f2 Q  {: k, l2 z  ^( J  C% ]+ D
! Q9 [4 c9 b9 C3 v1 t) v- H(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
# v/ i6 E3 d/ y7 o# ~1 U3 Z/ S" K6 f/ u" V/ @, B0 O, H5 W5 h
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。5 y) G0 ?+ F4 P! _) _3 \5 Q
: Y2 s/ {7 t: H/ j6 I/ e: J
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。
! _! p! p( i! _9 x( X
* V) {7 P1 G' x2 [0 G) l与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:
$ W; B5 i" n0 t' X# A& V1 l3 b7 k8 X/ L; q5 b5 f6 d8 S
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。
! k  u/ e& c: H4 S/ |7 [4 t& F# ?; W; \
(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
0 G2 a' D2 T& W7 f9 {: y9 v( j
- o9 n: k( e0 x1 j, f: A/ u* T(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。
& N" ~0 t1 G# W0 T" c
0 A% X1 f) j# c5 m控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。
2 A4 r, i0 Y: m& q  l8 i6 P4 C" O: M9 k# @

; s8 A* b6 A& _/ z2 n5 n3 j
c4fbc9fa3f184422a77784de5280382d.png
. ?& j& I( N, t3 e8 i
' Z6 o' n+ E! J! [' C7 x
; @4 X& D  W8 P& Y3 a$ t2 t
通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
+ H  G# ]7 ]' b6 G) g* _/ ~0 i+ |
+ C5 V: ^. h; q(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。
$ D/ h2 W2 g& {8 R2 n  r7 r3 C: X. W
(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。/ r. ?2 x2 o9 X% {  v

( _" U2 c  @# W2 ~- H9 Z8 g( k另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
1 t; O  \5 D7 l3 n* P9 _$ P' J; H/ T3 I/ j! @
& R; k1 `: ^0 [
a00dca8056bf40dc860b52366afa5197.png

7 y. V! C$ O0 R0 t, c5 u* O, d3 {/ R; e4 `( Z' s/ M
& s  j: n. Y6 M# S- [& d
91.3 FDCAN总线的HAL库用法
' E8 [: L$ g- z. M1 H, u2 a/ _91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef
3 O& f0 d/ ^. r& h+ iFD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
" D( d8 S) ?) w6 y& Y. a- d. \% g+ w( q0 ?/ k! |3 C
  1. typedef struct
    1 ?) X; n; o4 R* ~3 Q
  2. {
    / W' k3 Z  _/ G0 g
  3.   __IO uint32_t CREL;   % r! U' n4 ~0 u8 l8 k
  4.   __IO uint32_t ENDN;        
    % A9 N! V$ H) m6 f( z' j# f0 M3 D& u9 H
  5.   __IO uint32_t RESERVED1;    ; e* n8 @/ f* _8 i7 w' M
  6.   __IO uint32_t DBTP;        & E: g/ M2 L( V/ r; f
  7.   __IO uint32_t TEST;        7 C" `! {8 Q' c7 @5 G
  8.   __IO uint32_t RWD;         % ^, u6 f2 ^9 x# M, r$ b
  9.   __IO uint32_t CCCR;         
    2 V4 I2 y" G# T' k& a4 E
  10.   __IO uint32_t NBTP;         
    4 `# w3 [8 h  R! p8 T) \. K( d% {" R" U
  11.   __IO uint32_t TSCC;         
    5 x2 C, x0 e* g' A6 d
  12.   __IO uint32_t TSCV;         . R( w# D( v# g9 F% \- \
  13.   __IO uint32_t TOCC;         
    / K3 |2 M9 b' n
  14.   __IO uint32_t TOCV;         
    - u, a/ ~# F9 A) D# c1 `- t
  15.   __IO uint32_t RESERVED2[4];( ~: O/ u+ o# l, G5 D1 n2 T
  16.   __IO uint32_t ECR;          0 p: Q* H3 P& v$ _: c
  17.   __IO uint32_t PSR;          $ n2 y  O! [' G0 M* V% |& i
  18.   __IO uint32_t TDCR;         
    8 E/ B% M  ], R5 r2 k( E9 c
  19.   __IO uint32_t RESERVED3;    1 V  x$ }2 O; C& p
  20.   __IO uint32_t IR;           1 w! H; F3 L: z) w4 O
  21.   __IO uint32_t IE;           . S$ y) ?8 x$ V  x* q% ^. b
  22.   __IO uint32_t ILS;         9 e) T) m1 A$ d- m
  23.   __IO uint32_t ILE;         1 v8 ^; y5 K3 W' Z' W5 e# z
  24.   __IO uint32_t RESERVED4[8];
    + c1 d* z5 F* J- G# c& U
  25.   __IO uint32_t GFC;          - B( X( _) }% {( [: J) D5 M
  26.   __IO uint32_t SIDFC;      
    0 u, M8 W8 f0 p: ~5 x. \. x4 A
  27.   __IO uint32_t XIDFC;       $ f$ s# ?: a. W" C
  28.   __IO uint32_t RESERVED5;   - t+ X# w6 k; m
  29.   __IO uint32_t XIDAM;      
    8 m) [* ]' b; l: S* m
  30.   __IO uint32_t HPMS;        
    ) H  }( _; s; [% B) s) O
  31.   __IO uint32_t NDAT1;       5 j' t* q7 O. N! R! t
  32.   __IO uint32_t NDAT2;       , M- V7 d2 C8 {# q- K0 V) D. I1 x
  33.   __IO uint32_t RXF0C;        7 V. o+ S( W' f( }# ^6 d' q" G4 U4 x
  34.   __IO uint32_t RXF0S;       ( Q# n: R( o+ q! A) t% V, }
  35.   __IO uint32_t RXF0A;       1 D: X! P7 n2 `+ _6 q
  36.   __IO uint32_t RXBC;      
    6 B: t) E$ a; `
  37.   __IO uint32_t RXF1C;       7 b& Y9 _+ b) z! W5 B( t0 s$ o
  38.   __IO uint32_t RXF1S;       % _) y4 I2 @# u2 D' l
  39.   __IO uint32_t RXF1A;      
    ( g, _: k% S  Q$ M
  40.   __IO uint32_t RXESC;        , Q2 H6 w7 c/ Y7 u( E& C
  41.   __IO uint32_t TXBC;         4 G6 ~) J" ]9 _  s+ z/ N0 I
  42.   __IO uint32_t TXFQS;        
    - l+ Y; \. R& }2 T- I
  43.   __IO uint32_t TXESC;        . k2 ]4 O/ o, ?' m8 K' r1 k& E
  44.   __IO uint32_t TXBRP;          N$ ^* N5 r7 E/ b
  45.   __IO uint32_t TXBAR;       0 C4 E/ t5 r6 g9 O+ E$ V
  46.   __IO uint32_t TXBCR;        
    ( n( a0 Z2 U6 _( ^2 J. V5 o% h
  47.   __IO uint32_t TXBTO;        ( T! p6 O4 C& T  e9 B7 w
  48.   __IO uint32_t TXBCF;       1 ^8 W. P' K9 \; M8 {  x, @8 T
  49.   __IO uint32_t TXBTIE;      , n: [3 L1 G. F# g$ m
  50.   __IO uint32_t TXBCIE;       1 C0 ^2 t/ F; v
  51.   __IO uint32_t RESERVED6[2]; % H/ D4 _0 ]4 `# X. [2 w- J6 D( T
  52.   __IO uint32_t TXEFC;        $ c0 Y; c7 `: W" @$ f5 G/ \; J: }& t
  53.   __IO uint32_t TXEFS;        
    " A  _, q0 h( }% A. w  ]2 Y9 E
  54.   __IO uint32_t TXEFA;        - }/ A6 X/ |! I; L0 ~% N
  55.   __IO uint32_t RESERVED7;   
    0 V; S* B5 v8 j- j% t
  56. } FDCAN_GlobalTypeDef;
复制代码
8 U8 m/ y7 a9 x( |
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。, H! y; M& Y: X1 k: f- [" L! m
& A+ w0 U) f& x8 m" Z% p/ e' [
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:2 o; X; A$ X! y, c& q! ]6 a6 O( l
9 U$ O4 \2 t5 P) r. L1 K* k7 G
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    ; ]* I7 X, k9 L
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

/ m) s3 \7 B0 @5 e下面我们看下FDCAN的定义,在stm32h743xx.h文件。
& X7 d- X' u) L+ H# `0 U$ q2 v  H9 S+ f5 k( H4 h
  1. #define PERIPH_BASE           (0x40000000UL)
    / y/ T" k4 c( b+ V- R' L
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE9 j% \% j; c9 M( R9 S

  3. % q  w  ?7 f( b
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)6 @. G4 m% P# R+ t1 Q6 F% g, [( {
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)+ ^( z6 z* h5 |
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL)
    9 B5 F+ B  A9 z" H/ D$ L3 j
  7. 5 m; c" Z0 \3 s6 I  ^1 `
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000
    4 g. s& S0 c' j' [7 q. i+ Q
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)0 R% o% M3 Q( V5 V* A
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码

4 T* C$ C% z4 s. ]" Z$ W: I我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。4 V" I+ _- F! s6 P: V6 i4 U3 A
* F/ p: B. D* n+ i% B/ ^
91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef
% ?4 [6 y8 U" Q- m5 G) AFDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
" t3 N/ L, H6 m% |, O1 _0 X8 k" d) K8 f' @6 q
  1. typedef struct
    2 d: e/ x, H4 A) q
  2. {! @+ }0 O- f& X
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */* o. N( t  x1 m- q
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */
    0 F9 K" }/ l9 V' @# q2 s" p! h
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */$ u; O6 }7 f  F: J% I; A' a
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */" _0 G# T) |" m, c% i
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */. b' {) K. b. K  `5 Z' u( W5 B
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */8 b: Y/ E; }7 s9 D
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
    + X. F; S8 W2 R! \( j! U& x0 \5 ]/ g
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */7 X: Q( q/ f0 H$ Q& D
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */
    , ^+ O  J: J0 ~& S9 T, V
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
    5 w& H9 `. m" M$ |
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */& |) l* e6 C% c% o
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */" Q) `; D2 @  T6 [6 C
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
    9 `" j! j1 u) `' n
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */
    9 \. m' l& W2 I8 d
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
    / [0 \8 g! W4 f3 H8 Y  O
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    7 M* J* @: C; `( W8 ~$ e* |" g
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */
    % R: l0 ?$ @& s# Z  X- f# g* d
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */( }, r  h" V1 ?+ S
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */
    - {. A( a+ C! }3 ]# p
  22. } TTCAN_TypeDef;
复制代码

- }3 n! m2 _) a9 g" z' H4 ^91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef9 l3 [" V5 U; i- H9 K
下面是FDCAN总线的初始化结构体:
. x# Q  O. X9 \! _) I
. [# f  _. q* [' ~. [! w
  1. typedef struct6 u, O( w& z6 p& h, ^1 j
  2. {
    4 Q6 x& r% i# w0 K4 s- g' f
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.  v2 s) }: W  l% e
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     */
    ' g1 J4 `) y2 [; A9 {! Q% X" y( o! v9 [

  5. ( C# s  s& {7 ^, {
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.! e* O9 }9 z! S; ~! V: l! Q$ d" I
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */
    * I2 a4 j* S) R2 o! I) U# E
  8. * q* W1 c) r# B' M0 F. q
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.
    # g0 {  P4 y8 V  ~: h
  10.                                               This parameter can be set to ENABLE or DISABLE               */1 q& [+ G" J" H1 d/ s) Y( n$ T

  11. 1 r# I3 T2 q1 B6 W- F
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.
    ) R* G" c* ~! o8 E7 }
  13.                                               This parameter can be set to ENABLE or DISABLE               */# [4 Q6 j2 f: _

  14. 4 G2 v8 o% I1 |3 P+ q  u
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.; y8 F- Y0 R. l
  16.                                               This parameter can be set to ENABLE or DISABLE               */! x6 c, z$ ?2 |. b4 B

  17.   ^8 O% B) B6 Q% H
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is
    ' Q7 n2 i$ S: X+ W: N" u- ]8 K  j
  19.                                               divided for generating the nominal bit time quanta.% [' Y- G4 O* z1 r3 [
  20.                                               This parameter must be a number between 1 and 512            */
    6 w+ M4 h. c) U" ?% U. b$ C
  21. # i) H* x3 j6 ?8 P4 y1 q! N
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    . l, v+ e& N, K. U; r! q  e
  23.                                               hardware is allowed to lengthen or shorten a bit to perform0 V4 @9 B, e! a2 G& ~/ n
  24.                                               resynchronization.  ]2 H) S( {4 O
  25.                                               This parameter must be a number between 1 and 128            */
    3 t9 J" a4 Q1 f: T8 X: T
  26. / r" d- C2 ?2 W( v& K! T9 F
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
    3 N6 S- j: v( R6 _
  28.                                               This parameter must be a number between 2 and 256            */) v; _. V, ?/ h5 ?% Y$ Q$ j! n# q
  29. / v2 g; B7 z8 d& Z
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2.- w* c- p; D& w/ N: Z0 m/ }
  31.                                               This parameter must be a number between 2 and 128            */
    9 {6 [2 J& _0 E% d

  32. 7 a; j4 `& \; A* @" h
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is6 T; j% ~& ?9 B  p9 @* L; H9 U1 V6 J
  34.                                               divided for generating the data bit time quanta.4 `. A5 Y+ t! c7 S1 W
  35.                                               This parameter must be a number between 1 and 32             */
    ' r. N  A" R1 T# C- {# ^% J. N

  36. : H# j6 D+ q9 L; n5 c4 M, T
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN6 e: ^4 R2 @# i
  38.                                               hardware is allowed to lengthen or shorten a data bit to  K7 T& l/ V0 Q6 m
  39.                                               perform resynchronization.
    + X+ K: o# t/ e6 w2 i6 C
  40.                                               This parameter must be a number between 1 and 16             */
    + v  Y8 @- h# Z& e; q
  41. , j- F* }! d% F6 S4 m8 j* @
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.
    7 X2 G2 r  ^0 y, e5 R/ o. L) }/ _
  43.                                               This parameter must be a number between 1 and 32             */' {1 A, e2 w) Z6 B

  44. ' V2 n7 Z2 c8 y/ U; |" J
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.
      q! G# N" r9 T
  46.                                               This parameter must be a number between 1 and 16             */
    * a) ^1 F( I, g0 R1 E

  47. , \& |3 s/ t8 E5 D' j
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.8 |: ^( H# q8 K1 o( G. h8 \
  49.                                               This parameter must be a number between 0 and 2560           */+ [3 M" N) R. ]: p3 i

  50. 7 f. c9 j5 F. M! n( F$ Y$ k4 h' u
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.$ X& ]/ G5 m1 h9 b$ h( Q
  52.                                               This parameter must be a number between 0 and 128            */
    3 y: e0 r0 f* J0 q$ i
  53. ! f# }6 e( x6 d8 R
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.3 J8 x: L2 F. r7 \
  55.                                               This parameter must be a number between 0 and 64             */) M$ k& u" U! f- S
  56. % g2 o) W+ C! ~* v
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
    : [9 M2 q$ e) b! _  y" \3 l9 ~0 v% j3 Q) v
  58.                                               This parameter must be a number between 0 and 64             */' N7 N2 u% ]( a+ Y

  59. * {+ B, a& m% }" o6 O
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.% t" ]/ Y# `: |0 B
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */+ ]  \& Y2 k* ^  ~

  62. # I# t2 f( V" X- a, L" ^8 }( i# @" y
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.' R, g8 G1 o1 ^7 \0 d( x2 d
  64.                                               This parameter must be a number between 0 and 64             */( W9 }& I2 E( i6 R) e6 r- K

  65. , D0 w; G! l7 f3 X' G
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.5 N% W4 V7 Q) J" ?3 M0 v# B  {
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */$ P. {/ J4 k# q4 R# M# w: B# b
  68. ) C9 |9 Z4 e1 A
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.' e. E" U  }: T+ Z+ N
  70.                                               This parameter must be a number between 0 and 64             */
    ! B' D5 Y+ H+ [# K

  71. 9 \7 L) l" I9 c! R: u
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.0 K2 \+ `1 @$ m( F
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    " `+ \2 x. \% d; c6 q

  74. # ]* L3 E  K( {% |# }  j; c
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.; P' K, B$ D# S, w* M
  76.                                               This parameter must be a number between 0 and 32             */
    / c* S! T! o8 @2 b

  77. 5 g& X& c/ G1 K. G- M
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.2 v# o  h) ^9 l. l/ U) L
  79.                                               This parameter must be a number between 0 and 32             */
    7 @/ @9 W9 G. Q( G( k" Y

  80. ! N1 a5 c) j* J7 f0 x0 p' h, U2 t
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.; T6 v/ G4 P" J
  82.                                               This parameter must be a number between 0 and 32             */9 V" R+ E3 s$ `7 @3 Z
  83. % P" {* E* Y7 Z9 P) \
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection./ M; D+ D4 Y$ C# A* r2 w  P
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
    7 r9 n& P# t* V
  86. 2 Y$ [4 H7 ]- O! k; b9 z
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.1 L9 J4 }! {+ m8 B7 N
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */3 @: K2 n2 f8 L

  89. ; F- |$ V3 c) U
  90. } FDCAN_InitTypeDef;
复制代码
. R7 E4 I/ p& Y9 k5 l5 q
下面将结构体成员逐一做个说明:
/ ?' @; @* ~7 J$ @0 r
9 O3 u# ?1 ]8 ?' M4 Q6 k4 G1 h% @  FrameFormat4 [" V. j: m4 c9 [- R+ z( e
用于设置CAN帧格式。
' B: }. R+ L. f* D% _9 {
0 r  u# a7 K% ~- e; j
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
    4 G0 a6 K, d8 B6 U" k* b
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */0 i& `! l4 G  j" t1 s. y( \
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

4 I' e- k  U1 x  j' V; x- A* f2 t  Mode/ ?% y% [: m1 ^0 b2 n8 j
用于设置CAN操作模式。6 ^; m5 S& D* w' z# M, h. k! C
7 V; U6 I" o& ?
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */; S( F& W8 h) }
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */6 D* Q: [4 X. j% Z- {# n0 a6 V- J
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    ( G4 t/ g9 ?( V: ]+ o: ^
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              */% r  {# z; Y0 c( p5 J  z8 K
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码
3 J6 J2 Y; Q% k1 j7 I# |( i8 ^
  AutoRetransmission8 g; P9 {$ }$ w- e5 o& Y$ H) g
使能自动重传模式。  ]( C: c1 X1 L6 R2 S+ o4 J
: d: @: K. v% s  e8 t8 Z9 L
使能ENABLE或者禁止DISABLE。# ^" e6 F% |2 R  }( z

" o3 {* d$ a) f0 D9 [( J/ c4 ~0 C  TransmitPause
; L3 j1 x" W& L使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。$ }* A8 |( d( P
+ k; T2 W9 N; {
  ProtocolException& O) x* k% J/ h/ \- S
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。4 ?: I7 w& `+ O- U
4 ^; G  q3 o% o8 r. {* I: y7 ?+ T+ W
  NominalPrescaler
2 q  N( D. q# B2 `7 ^用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。: n5 \6 s% y4 ]. L' ?

6 p, R2 {- A! g  NominalSyncJumpWidth0 o! N0 B# l2 X
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。
0 Z9 _# r0 F; c2 Q. O! [$ J* l& d4 l( [$ ^. E9 @# p
  NominalTimeSeg1
+ g$ v. f7 ]4 N9 r设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。
$ r8 r' g# F/ A$ E/ U3 E5 x* K/ Q9 s: Z7 Q6 d' L) D% y% d* |
  NominalTimeSeg2  ~& S. K& k& T. l2 ~
设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。# F7 o9 d! A4 s
7 r& S. h* j5 @5 i; l' c; s; i4 W
  DataPrescaler  V; `* A3 Y( D! N
用于CAN FD数据阶段分频设置,范围1-32。& L* U  c# d* t& v( Q

8 N& A: W: ]) ?, [" m  ?  DataSyncJumpWidth4 J2 j4 P1 Z; t% F2 v! l! C8 J
设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。2 r6 e" s  p  ?6 d! `8 M) o) O
. u  X7 o, b5 ~, z! ^
  DataTimeSeg1
4 J+ y9 Q) A  a* j设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。+ i! E/ y% ~! Q1 c! x$ Y2 R

  _) i% s( p0 L; A) N# X0 c; `  DataTimeSeg2
5 i( R/ a; k% N. [; E设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。
3 L: d0 d$ h6 ?
: m5 h5 u3 {, Q. Y) |( V3 I( B4 K  MessageRAMOffset5 ^' |0 N: r- v) C/ j& c0 D- Y
设置消息RAM起始地址,范围0到2560。
- _1 h* N% i+ M# t
# ^6 c* L1 z/ I! v5 G  StdFiltersNbr! S9 I6 E2 I7 m0 e
标准ID过滤个数,范围0到128。6 t+ ~9 _6 M- H8 D$ o; Y
: T) }* v/ o' a/ j: X2 ~+ G
  ExtFiltersNbr9 ?# L2 k- r& c2 C% w& \5 q- I
扩展ID过滤个数,范围0到64。5 j* G/ q9 ^* v
; h; }8 ^7 T6 O9 e- z: k
  RxFifo0ElmtsNbr
" J. S2 Y0 z$ w7 LRX FIFO0元素个数,范围0到64。0 \# |$ _+ o9 G( \! c- k
- \4 q5 _" X" a7 |( G
  RxFifo0ElmtSize
3 h) q! t4 k; _$ N% F& GRX FIFO0每个元素中数据大小,支持参数如下:+ r9 N" T2 g) q7 X% q2 j, G& z6 e
( v9 z: N/ G! q- ?6 e8 R& X
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    % w+ G. p/ o6 Y) u
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */! S; r2 Z6 k' t: m6 I% `
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    & Z0 U; p! x! _5 M: S9 n
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    * ?" F9 K. {. m9 F0 L0 m& R7 z+ q
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    ; s( A% @0 v* j7 D# Y" R# ~
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    7 \# b3 s$ v5 W/ D+ G% D0 [& q
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    2 F! L  ]' o  G) M/ e
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
* M3 l, B7 U! F, i. K3 p
  RxFifo1ElmtsNbr! }- ]+ w+ W6 b0 k) F2 v
RX FIFO1个数,范围0到64。
1 }3 A8 B: k8 Z* V& t. I
" m$ r( k' t/ X) ?  RxFifo1ElmtSize
4 [1 v1 {7 _: T+ lRX FIFO1每个元素中数据大小,支持参数如下:
, ~& X1 K. @4 r/ c2 C+ g: z$ v. Y( Q. e( a/ C2 }
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    . h- h6 G) F( _3 s8 B
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */( O. j% U( r) I8 ?, X; O0 v7 p
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */. D8 H1 W) D( R& C
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    ' I+ M, z& c+ s* b
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    9 H; T3 _: n* B* ?; m% F. q" r
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    + ^5 r0 u* s; z1 B
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    # H, `: x9 |3 _
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
" p' q$ {& I* h5 Z
  RxBuffersNbr( j4 }; H' a) a$ x. l
设置Rx Buffer元素个数,范围0 - 64:
( l( D* ~  g3 H! q* t
1 _6 g% F$ S) C, M+ Q! x4 _  RxBuffersSize
) A, `- r& v2 p2 `( O* ~设置Rx Buffer元素中每个数据大小,范围0 - 64:
2 E/ r3 {& o$ @: k  e) u1 M9 j6 F1 B% y5 c. t1 t5 C
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */3 }+ B3 d6 H% M5 P% Y. r
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    % e6 j) [! s8 }7 R5 m* K, s  U
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */7 I. p" a; P, m
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */8 O$ K/ m. `+ D3 D& u
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */7 J9 j9 l; m0 F: [( W; }# B
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */& H" q3 t9 \0 I- ~. f2 G
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */' `9 {) B2 c: B( r
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
4 i3 g; z1 V# |# z3 Q) X& ~
  TxEventsNbr
( J2 \' Y& |' M4 j+ \$ @Tx Event FIFO元素个数,范围0到32。
; T# r" X) G' x% n2 s% @2 E9 f, @* T9 C% Z$ P  c
  TxBuffersNbr. S$ q9 e8 N  e7 }" L) i+ n
设置专用的Tx Buffer元素个数,范围0到32。
: I0 \& S- Y, d8 `. C) a* D3 P' j$ V+ j9 T+ E& h5 O
  TxFifoQueueElmtsNbr
' v8 l+ ~9 `" {. f% c' @: D  p设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。( |7 b: H/ Q7 {+ ?

1 E  {) w, m0 e$ ?0 h  TxFifoQueueMode
/ f- F  X  |. R+ h1 \设置FIFO模式或者QUEUE队列模式。& P% N# v, O0 R
& j( s0 o! ~2 G9 M
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */
    + y6 y/ [2 q$ Z4 D# q( d& o
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
# \' e+ D, H$ Z; `8 f+ m7 j% j
  TxElmtSize
5 o2 u# x  \. e* b6 ]# b! ^  q设置Tx Element中的数据域大小。支持参数如下:0 }. y7 }- W$ C( ^) V4 s. Y3 G
( A# O& m# P9 x# K5 ^
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */% M/ T. [( S$ N/ U1 P5 N
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */" V7 o. `, V& _( x
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */8 y# |: R7 U4 X5 Z
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    4 w" E1 X! _8 B( C7 D* [0 W
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    6 Z6 x$ i7 ]" P
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
    9 _( Y: Y* w5 R/ `$ G5 Z
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    & a9 n+ |" [+ }' [4 [" z. c
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

5 G6 s: j2 A, d/ O91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef, a& E  f& [7 C! I7 ^1 A
下面是消息RAM结构体:( y5 O5 N5 Z, P) K% j: Y
  1. 4 o' d; i  u  Z, n+ V8 l3 z$ u
  2. typedef struct
    9 w4 ^0 G+ ^( {8 r( v$ V
  3. {& }: \' }0 k) E+ d! \' M
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
    ! v/ k' k+ e8 f
  5.                                   This parameter must be a 32-bit word address      */& S# D1 {' }% @: T; g0 Y9 P
  6. / C! _! l  R/ b
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.9 ?6 g+ V; R5 F0 O, h& v: P
  8.                                   This parameter must be a 32-bit word address      */
      R5 u" b4 |/ W& E2 ?5 x

  9. / E) L1 ]7 i) C( H
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.& t' r, m7 T1 T: z- i" I% Y
  11.                                   This parameter must be a 32-bit word address      */: F" [# F  y: T+ I
  12. * H1 Q* ^! T. u3 v9 h+ E5 w" z
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.$ d2 r* x9 {/ j  h- x
  14.                                   This parameter must be a 32-bit word address      */
    , `0 C0 e" K) L( v/ D7 v

  15. 0 {  Q' B' i- f+ }. f
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address.# l4 X1 @% s7 @
  17.                                   This parameter must be a 32-bit word address      */. E; D  E  ^' x0 Z+ @( H- K

  18.   e; [9 m/ f- y, K. j
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.+ L+ \6 o- p" X* j8 M
  20.                                   This parameter must be a 32-bit word address      */
    / U. i/ F6 {; \& d6 m1 O3 `$ U

  21. + @+ Z! U, X  c" b, _
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.# Z  e0 h& `& E7 m/ F
  23.                                   This parameter must be a 32-bit word address      */: h: [) l/ x* W& d- [% ]9 t: P

  24. ( D: `2 y* E. P' A% i2 V
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.1 P+ d8 s5 o4 ^! F* u
  26.                                   This parameter must be a 32-bit word address      */9 @( u1 L7 `5 M, {
  27. 2 n4 w0 t6 U$ D
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.
    % V8 ^! w# M+ |6 k
  29.                                   This parameter must be a 32-bit word address      */
    2 z6 G( m/ U; |7 j

  30. 1 Y8 T  I  o6 x% q; L4 u5 z) k/ h% m
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.+ Z; v# o. n7 w: r  k; a( c9 L3 J4 e
  32.                                   This parameter must be a 32-bit word address      */
    5 f; D# k& t7 O: T4 ]/ N
  33. 9 m. E+ F. D" y* B/ L  W; M
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码
$ W  F4 h- t& Q, \9 q; m8 E$ r0 s5 j2 v
下面将结构体成员逐一做个说明:
. P: }% b) {# W9 B2 `) {
/ W" K8 I9 V- ~+ l0 q5 W" c  StandardFilterSA
: Q8 G8 d* s8 P5 |. W# p# C设置标准过滤器起始地址,必须是32bit地址。
  E2 H- \5 n7 ^5 n
# f2 \6 w( f  o+ G7 O. \, k  ExtendedFilterSA& {$ T' h/ e* e2 E. Z- @4 D# Y
设置扩展过滤器起始地址,必须是32bit地址。
# Y4 q  m/ o8 o5 b8 q4 B7 W
( \* A5 @5 o. ]! P  RxFIFO0SA7 B$ f1 u. R- D) P* o9 k* N9 K
设置RX FIFO 0起始地址,必须是32bit地址。
" R2 Q  |0 M, k6 \+ |2 r$ D& X8 b# `5 L* W! P
  RxFIFO1SA8 l5 V7 P' k  J) K- g8 Q6 |- Z
设置RX FIFO 1起始地址,必须是32bit地址。
& Z. Z% n, F" r9 o. {
5 K2 @) V! S5 v& [# i( o9 s7 j2 v# }  RxBufferSA
' h$ J$ l' C8 k1 t. Q7 c设置RX Buffer起始地址,必须是32bit地址。( R8 |6 b3 ]( N1 b5 n
. P4 a0 H9 Q+ ?! e7 M! O$ |
  TxEventFIFOSA+ U4 L, f3 X6 S* U$ M; ]4 a
设置Tx Event FIFO起始地址,必须是32bit地址。3 n$ M: C6 z: ^+ c4 F
) B, x9 Q9 ?, Z9 k# t. [
  TTMemorySA& h. U& G% F4 c1 @& y
设置触发内存起始地址,必须是32bit地址。: _& G' A& s" g$ n+ j8 o

3 n7 m0 c* l3 V( J" S  EndAddress
5 M' ]7 m+ T0 c4 C% c设置申请RAM空间的结束地址,必须是32bit地址。
. x5 g# d/ \  ?3 b$ c! o- U
3 [2 A* D; h3 ~$ x: A/ g91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef' }7 B+ j  t" Y7 s
下面是过滤结构体:
, z% z  Z$ O0 y0 c0 b8 \' _- r0 T7 D# h3 f; |' z7 v1 ~: K3 ~& k
  1. typedef struct
    9 K( g( Q! E( p7 l: G
  2. {! E3 g. O, Q# ?" v2 p0 U% `
  3.   uint32_t IdType;           /*!< Specifies the identifier type.
    1 z$ ~. e8 [. H- Q- o+ P3 Z1 o
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */8 d- |6 G+ q# u# M5 {

  5. 3 V/ \( H2 c# X
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.% w0 n( W9 E& X+ r: J
  7.                                   This parameter must be a number between:
    % G7 L: ?* u$ M/ s6 u" r
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID; [" T5 Z, }- z
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */8 I4 N5 W' Y8 U0 D# j
  10. & p' f" c. X4 S* {. I. C9 k7 i  o. T
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
    7 d% Z5 e& v- z- F
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.
    ! ^  Q& t4 c* `3 F6 m" h5 `
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted1 z  X4 N( |4 n, @5 x' u8 P
  14.                                   only when IdType is FDCAN_EXTENDED_ID.
    $ _. D+ H, Q4 U0 ^/ m& o8 c- I  q
  15.                                   This parameter is ignored if FilterConfig is set to
    . Z& u$ {( i% H* L3 E
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */
    * W+ T8 U3 g) i! e
  17. ; t5 ]  p7 `9 n/ E' h
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.
    3 J: C) K5 a3 d* \' B) A+ Z2 w
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */
    & ~/ z- d& [5 m- a

  20. % t! h" u2 Q4 `# ~& `+ M
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.$ D" o/ k4 J2 g
  22.                                   This parameter must be a number between:7 {7 h) y- d$ y2 y/ F/ z; n
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    3 _1 k  V* }7 V' d  G. H
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */( @: I1 Q2 o* O5 ]( I: P
  25. * c2 j, M/ J  `
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2.4 k# [& g, S# z: d/ k& o. p! l% a
  27.                                   This parameter is ignored if FilterConfig is set to: f- ]4 K" [% T! }6 a
  28.                                   FDCAN_FILTER_TO_RXBUFFER.9 m/ e( J4 }, J& R- K
  29.                                   This parameter must be a number between:* s, v2 S5 `; `. L
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    ) n1 g0 h; L- ^
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    * Y3 y% B' s/ _! a6 J) p6 A
  32. 9 t8 {9 X5 B2 Y- W
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
    4 g* C( @% v& c8 `- [7 f, O
  34.                                   matching message will be stored.
    $ B2 R, N& X8 y! |8 N) |7 b2 ?
  35.                                   This parameter must be a number between 0 and 63.
    9 @8 c- X% c9 V
  36.                                   This parameter is ignored if FilterConfig is different
    9 Q  W: p5 I5 L. r8 c; A( E
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */; n& p9 a, q' c- e- i" _

  38. " c# E4 a  D6 x- g9 s3 ?
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for
    ' b, k8 E0 R- E# v! m
  40.                                   calibration messages.# _( W  Y2 a4 W$ P8 P$ \% T, L' d' ]
  41.                                   This parameter is ignored if FilterConfig is different# Q$ u" r: K2 k
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.
    # ^, W3 N' K# b) |9 d
  43.                                   This parameter can be:( A! k5 V  r- A
  44.                                    - 0 : ordinary message0 R# p4 @! _! P9 D! b, a& s
  45.                                    - 1 : calibration message                                */
    5 z" k" W7 p; b

  46. ( S  l+ j, p! X( C% X2 j% j
  47. } FDCAN_FilterTypeDef;
复制代码

& A. I! x- n2 h: b  IdType; L- l7 j, F. m6 o. u& A
用于设置标准ID和扩展ID。$ b, ~( l9 m) [& I$ E# W: Z
' o; ~% b# n' Y, @  s1 \& ~
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    9 d0 ^6 }8 `& [3 ^8 x
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

9 c3 v. N" L# F  FilterIndex
) ]& N9 S9 N/ h5 M: o" u/ F' p用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。
' y$ p1 X7 J$ B# u
" Q' }9 ]& K9 D  FilterType
& t0 d. ~, W8 e0 }; x用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
0 z: D5 F3 ~. O3 n% A+ Q( o+ `+ X* y) i2 s: ?
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */3 _: t, q% W: o/ O0 `+ \+ j
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  *// Q) c% o* r9 l- E6 q
  3. ! d: T! f6 `: A) r
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */' {6 u# p/ m0 j2 B% h
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)
    6 N; ]+ x6 o$ [7 Y- F6 O* n

  6. $ Q( M0 e3 x- U0 l3 b) S, t
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */
    3 ~' T& L% H9 G$ m
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

1 B( `+ i9 ^9 @, s" W; E5 p! \  b  FilterConfig, M( X; K. o9 n/ W% \# T
用于设置过滤类型。
7 W( ?; E# Z2 \# g6 ^0 E  z. J0 X) S) Q$ D
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤% j" Y4 Q( i: A, S, Y
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    ; S. `% b4 Q! w5 j
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 1) m+ h6 V6 u, c7 g3 A2 g; b; A
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID4 u. s  R9 T$ X, _7 p+ r9 F
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级: N( E5 ^- X3 A5 ~( J# ]' y3 Z0 ~) v
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0' A+ Z# t% g, B
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1; b, f4 T: V" X7 J4 N
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码

* g7 G0 G. F: _+ v配置
7 ^/ E7 L6 Z, k( ~6 j5 {  {  FilterID1/ x: D2 q* N  |6 v' S6 R
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。
' R% q4 N: y9 Y2 C9 }- k( f% r" i* \, w3 x) d/ `) R  f6 q4 ^/ C
  FilterID28 J3 p/ |! f0 O3 p* S5 x) l
用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。" }+ V# _- ]4 G4 f6 {# j
9 Q! G' h# U( k, a  {
  RxBufferIndex% |7 G! L/ |: t  p3 a7 {
匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。, ?; c" t3 a3 y) c; a

) L5 L( k1 ~& Z6 ?  N  IsCalibrationMsg
# Q; c5 b( q1 ]! Q+ h! l用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
1 W! [3 l4 {1 |7 o
/ ^4 B3 q2 ^6 z$ c+ g, Z1 ^" k  W0 : 表示正常消息。& X# Q7 K; G3 Z/ ?7 @. O) S
# W  ?9 W. K7 ~$ X8 Y
1 : 标志校准消息。: p( t+ X: Z: y

- }5 L4 v0 }! z/ f1 N/ C91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
+ j- V& _0 @) g9 ]1 u, u下面是CAN FD发送消息结构体:
/ x8 n, e4 f9 T1 S0 u3 r/ x" e. j( H7 j9 f
  1. typedef struct
    - U" _6 v: t2 t0 ?; C' Q
  2. {
    + \5 X3 |% T4 o/ }
  3.   uint32_t Identifier;          /*!< Specifies the identifier.6 _4 A9 a5 z* H0 p& p
  4.                                      This parameter must be a number between:% p1 w5 t# i9 j3 v( Q( U$ `8 v
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
      ^+ t  f8 g5 }0 p7 J
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */8 @6 l) c6 O8 N
  7. 9 ~3 a$ B2 a5 I; u, p: K8 _' e
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be9 d) B- ?& v  {  w/ P8 r( Y
  9.                                      transmitted.
    / N+ d/ B8 m7 P6 X
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */
    . N  e: m5 {1 N" q3 V
  11. . d1 u, y0 W: ^- g. O) X/ n2 L
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.7 w/ Z" u3 X: X5 n! s. ~! T
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */
    - g4 q4 T* W- k, B3 X0 G6 |
  14. % U' r) X5 U; p$ W5 d9 ?
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
    % u+ c1 t. U' Y8 ^# a8 f
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */
    ; }- \8 o# y! d% k: h  X

  17. 7 ~9 m8 L- V+ U  K. d
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.  b/ k1 M% I- X$ W
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */0 [" K7 i3 X* E$ u+ |, z
  20. & D8 L7 s- y- b: Z6 Q) y
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without
    . [6 K6 }8 t8 b2 {" K
  22.                                      bit rate switching.! S9 P( y/ s/ h0 Q. c* M
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */0 h: |2 I2 s$ k. U

  24. ' q2 Q/ _" U: V
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or
    9 P; x' P" b( D
  26.                                      FD format.
    5 d3 J) ^$ m6 K
  27.                                      This parameter can be a value of @ref FDCAN_format                */
    / j4 w0 a  O+ }. E) a* d3 l1 }

  28. & c% o* c  q. {& T, Q
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.
    8 l/ _- F7 Z5 G/ q& z
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */
      j. l# r! p+ G$ X1 ~$ K: A7 p4 U  N
  31. / N, H0 x3 Q# @6 B
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO& ~4 v; j1 O, I  O
  33.                                      element for identification of Tx message status.# s) n9 o/ J4 B/ q3 P8 \+ ^4 `* a
  34.                                      This parameter must be a number between 0 and 0xFF                */
    $ d' w+ v$ j6 m& W. K/ z4 `. D

  35. 2 P0 E0 i+ A( U0 }& X
  36. } FDCAN_TxHeaderTypeDef;
复制代码
: C# [% B- ~9 |$ Q- i8 b
  Identifier
- ^$ {8 e1 N: C5 f用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
0 E5 ^: J/ l; J' X2 A* W5 C5 j6 \) _9 n
  IdType
1 v) L" D# r/ Z( [' Z用于设置标准ID或者扩展ID。) ]( D# v" S2 j) r) O

0 c4 y: C3 u$ e; s/ i. U6 S
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    0 r2 z; e. C' c3 G1 |5 v& s7 Y
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
1 b" g9 x( K: y) i% {9 c
  TxFrameType
( n" @" s% n0 {  p用于设置帧类型,数据帧或遥控帧。! ~( P* l5 v0 |, ]3 l

5 |) Y" a$ ?7 j5 x, k, {/ K
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    + O  W& O# M! W8 B
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

: ^7 n6 W% [/ [3 [' y2 I1 w  DataLength
% Z/ f& E5 j' F) e! ^0 l用于设置数据长度。* ]! |4 h) D4 E1 X; w9 v: j
" d0 i: I1 t( M1 y$ b5 u' D: \6 T
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */" l$ R  o3 R: l6 ^: C
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    $ K* S! F+ f  V2 F" c: d0 o
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    ; J) ~: I& q# X/ E
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    ! @9 `& ]# F* E( Y1 X& ?4 l. H
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    4 [% S  F: Z; I: g! G1 L7 |$ g- \
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */% Q/ w1 F6 t; y1 C: _
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    . z3 p/ y0 c% }5 X8 O! }
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    ( x8 Q# S2 o! V% q' P# Q2 M$ K
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */9 ^2 S4 O, z. i! a) d: d; c% j
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */7 A# G$ R- n6 [( i8 l7 O/ m
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
    ! C* E0 V# E3 g
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */
    % [2 A) W1 p/ f$ g' x/ I) c
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */( n. t/ F0 C2 Z; {; E) _( X
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    4 r+ t) h" Q5 V0 F/ J
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */! R! j8 I, J+ q/ g9 h
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码

+ B$ Z6 ^& X* N; I  m  ErrorStateIndicator0 ]; j9 h6 f0 u" l( F2 b8 E1 z
用于设置错误状态指示:/ n/ ?: G0 h$ f# e! {

9 [' W( B6 T2 Y) J* s
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */' v( n" ~: s% {
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
( I4 V- a8 |$ Y
  BitRateSwitch5 k$ f( `4 H* ~; q# T9 o, q$ i* o
用于设置发送是否波特率可变。
* b4 i" y/ ]9 I9 f+ K5 t4 y$ {1 F4 O9 B! H* O' p- p* }! _3 E
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
    4 {: r1 p2 F( X& o
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码
; g# u7 Z$ ?4 Q4 Y% g: k, S5 e$ q
  FDFormat& m4 x9 n1 _7 S: [( Q
用于设置发送帧是经典格式还是CANFD格式。2 i4 Z3 z4 H; @5 o& a& S
  1.   m' M) {' O. G# H" m2 s
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */: J: ~5 D- P+ P  U# ?) D% Q/ R
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码

' c9 }2 e# y  ^+ _' n( Z9 x  TxEventFifoControl- K- D/ Y; O) y* U6 ?8 a
用于设置发送事件FIFO控制。
" f) ]( |4 w' P
# p1 [' t" `# p% A! ]& E) n8 V( q) A
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
    - o: v2 E6 G8 |8 F+ t# x  z
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码
9 Q5 c  Q1 `/ b) Y- S  E
  MessageMarker5 U& J1 `' x* l4 X/ `! `9 ^# c
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。
' Q( A7 L8 C; U1 _
- Q. f4 [* X5 C( Z% E2 q! z91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef
( u8 [0 Z1 h; G6 T/ W( t" n. ], A下面是CAN FD接收消息结构体:
0 D/ ~& Y! E  s8 P! W
/ N! \" X, A8 n2 g
  1. typedef struct
    . P; w) a' C0 e) X. z. n
  2. {
    8 W) g) S3 k; U
  3.   uint32_t Identifier;            /*!< Specifies the identifier.
    3 n/ w) G: ]9 K# F
  4.                                        This parameter must be a number between:
    9 @- F9 ^, f2 v6 P2 I% U0 p
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID6 A+ F8 N6 ?2 w- W6 {) \
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    , [+ T7 H" p6 f, ^- {) Q
  7. ) w' U0 R( D; l/ s0 F
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.4 Z6 X7 }. P4 L) W: l9 O% q
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */
    6 y# u6 e, b8 W4 O; \* ^

  10. / P1 f1 ?* y2 {. L8 [) g. s
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.. ~  B  x. M: y0 c7 m, S7 v
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */) Y3 q# x) x6 Q9 ^; `( ^. M
  13. & A0 s% A! n  b9 V5 C$ h! O
  14.   uint32_t DataLength;            /*!< Specifies the received frame length." ?6 \, o  e. k; W! Z
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */
    6 k% u, i0 D. ]6 Z4 Q7 S

  16. 2 r1 g( z) n: m- M
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.
    . E- f  `/ E0 K  I
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */
    : r, b1 e% e1 G% g+ V

  19. ! {6 B$ I: a) A7 l) h/ ?
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit. D9 H4 S) d$ [  u
  21.                                        rate switching.7 ]! G9 z1 M* Z  o
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */% i$ x8 b5 \' P2 L2 H
  23. 6 V4 a! ^9 I# ]5 O! f/ F; N5 L6 @
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD$ R. H. [7 R* o2 L3 G+ k
  25.                                        format.
    5 G+ V& ?. Z; N3 m; p
  26.                                        This parameter can be a value of @ref FDCAN_format                */# Y8 w8 Y2 }  [- e4 p( A9 w

  27. , `) i. _; S. Z7 x1 F9 D
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame3 M% k9 y3 I! Q1 R
  29.                                        reception.
    9 X; V% g: b5 M" Q
  30.                                        This parameter must be a number between 0 and 0xFFFF              */& ^# ]+ C# o% ^/ l/ x
  31. ' |0 J7 X- v" b0 x* O
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.9 V6 w3 v! P& C9 U
  33.                                        This parameter must be a number between:
    $ S0 b- J1 s* Z: w% ^( Y
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID4 x! K4 K& r+ @/ I" m
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */% G4 I5 I2 i/ ^5 _% Q

  36. ! d$ e: t% j9 u9 X' N% Q9 ?+ G
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    ' u4 J  j4 O% R9 ?/ e, k7 t  l# Z
  38.                                          Acceptance of non-matching frames may be enabled via
    6 i- m( ~& K1 b; ]+ p1 Q. R
  39.                                          HAL_FDCAN_ConfigGlobalFilter().
    - j2 H* b) k" z9 o) n
  40.                                          This parameter can be 0 or 1                                    */
    ' b1 b( V0 o" Q. S/ g- h0 N
  41. " ~: @, L" j" q7 h
  42. } FDCAN_RxHeaderTypeDef;
复制代码

. A+ a: s" l. u  Identifier
0 e. j1 ]% X/ Z0 M用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。, v: q8 n7 ?4 I

4 u7 `0 r5 x% @+ q& R) V  IdType% {0 ?( P3 W3 S$ t) A6 h, c& \* ]
用于设置标志ID或者扩展ID。# X# |/ ?: ?3 H2 M5 Y
6 v' l4 b% `: o6 q
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
    5 P  P3 w% T! x, k5 x* Y
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

3 }) L1 P- a' [6 [  RxFrameType
/ n, u1 p1 a) G5 g4 j用于设置接收帧类型,数据帧或遥控帧: ~- y3 F+ l- _; K4 E

& W0 o( t+ }" S
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    # d7 ~0 E  G% A, t- L
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码
6 A6 c4 |4 {# P9 H
  DataLength
' K2 @/ n$ D" L! a) D$ m用于设置数据长度。
$ {# R2 S# t% z) p; h7 v4 K0 u
% G7 S, \2 T4 a  ?; q
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */: M! B) `& w( f! E" W* k
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    2 k# y7 C- j3 F
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    7 z( }( l$ X. W0 U1 S* ?
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */$ q" j; k, u, h1 O  ~
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    0 J- T& t) i# }$ W
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    / m2 Y' G. N! m2 q+ i$ Q+ s2 X8 ]
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    + x! Y5 B4 {3 m3 N0 w
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    8 S1 s2 K5 G/ e: V- v
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    : l+ B2 g2 C" h* ~- d* d. [
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */* p* w! W9 Y$ [# h, Q
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
    $ K4 V% M( p6 @+ O$ h! @& X! N
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */. j- A7 Q& X8 R. x  O. Z8 y
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    ' o- Z/ Q4 L) M/ |& \
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */% z5 j' R/ ^6 P' M0 u) K
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */& M4 p$ x8 k. a2 A
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */% A- }; H8 K4 H
  17.   ErrorStateIndicator
复制代码
# T" k# F" ^- M% `0 ]' L* d
用于设置错误状态指示:3 {3 q4 y, ~6 n& ?! I' |
* W6 I8 L: M* v$ E7 x# s
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */- p4 `, W/ T; T0 i$ |5 `
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
5 C1 S  c6 Y! b- p3 h6 W
  BitRateSwitch' D5 w/ d, K: W: e* M
用于设置接收是否带波特率切换
( r3 |) G$ D5 P# R2 N, [/ a, c3 u2 ?  l* a
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*// J+ p7 t. t3 F( V
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码

/ a; s1 f1 P5 M  FDFormat' n" J! s+ H( y% [7 J
用于设置接收帧是经典格式还是CANFD格式
+ F) z3 Y) g2 K1 e" Y
- o8 R* p' E: C! e0 t" ?6 E: n
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
    & |" s7 J0 ?, j, Z, A
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码
! J! d+ R2 D& I  B6 {1 J6 O
  RxTimestamp  U) {7 b8 e* l8 t) W
用于设置帧接收时间戳,范围0到0xFFFF。   
2 w4 B' |8 h/ M. L& r* n, c$ \$ [* o" f/ c
  FilterIndex0 y+ J! P3 ^' W6 t$ h) r1 O( d
用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。 , r' d8 f3 E) n) D5 Y' K+ k3 n- m
' e% V& e8 Z6 Y9 [
  IsFilterMatchingFrame1 M! f/ D# b- B  j
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。% J1 e7 I4 @! P7 n/ b) `

/ H9 c  _; N4 u( v# O0:表示不接受。  r) ]$ J+ t7 q; G7 c
9 i+ `) t; g/ @& r/ y1 [4 D& f% ^
1:表示接收。' q" M7 g# {$ o  _

. `& @) U5 m" t0 E: m; U5 [9 N91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef8 |: l& J! F# `; p
下面是CANFD句柄结构体:
! X6 x2 H2 c% e& |9 ?! Q5 U4 y+ m; S/ b8 R, P7 w( s* N
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    7 ?+ l: ~. b% P& _+ G/ T
  2. typedef struct __FDCAN_HandleTypeDef
    2 n( E5 b( V  Q9 K
  3. #else# E0 M9 J' T4 n% a
  4. typedef struct
    6 ~, n. o# L& p, ]7 `& C0 b" f
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    , L& O, m9 @! Q! n
  6. {8 @7 b3 W0 |" q3 [# ~$ O5 n
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */" `) @9 o$ a9 ]  z
  8. ( }2 k' |6 A: u( H1 j0 J
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  */
    ' j3 M0 B7 F& `/ |  Q

  10. / V0 o% Z2 B6 `, p2 ?4 j% L! `
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters */! w3 h6 e& h7 O
  12. 7 H, ]) I4 [0 ~4 |  \0 j
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */
    # H% c2 @  o4 c4 y3 E) d4 k
  14. / U. S' y, l+ h8 ?# Q  k/ _; R
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
    ; P% ~' w( T" Q5 a7 I0 J' ?
  16.                                                of latest Tx FIFO/Queue request */
    - F3 i6 J& n+ K, C

  17. # s+ j7 `2 p4 l7 F* k1 s9 X8 t) s) O
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */
    ( m- P3 v/ R: S8 ~" p" _% E7 H

  19. 6 g% {/ s; \% U: C6 b6 J* x
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */
    8 q* h* a& G) [4 ?* S9 U0 u

  21. 3 U5 Z5 J' P4 C! f. y/ X* D5 Y
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */6 n8 l" ]; t: d9 @

  23. - ]3 o- \) K: r/ E, t5 C/ [
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    6 e) ?9 D- I: ?" N
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */2 O) }2 H" Y0 n: L$ j7 f
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */
    2 r) ~( d4 B5 N0 c% @7 B8 I# I
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */  y! ?7 Z- k, l* e' B. d$ A
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */% T! J9 l( K5 V2 s' _
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */( L  B: q7 Y. O/ q1 q5 ~/ \
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */
    2 n4 q% K+ n5 G7 Y# o- h8 N
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */7 D, }' g- \% O/ f; y
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */
    9 S- j: m5 D! ?4 q7 e% x" T# h
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */
    9 H* X8 c4 |4 ]
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
    ; w' y$ v' @- h  c) K0 r1 B
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */1 I# I9 w/ K' y5 r1 j8 B- P3 o
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */
    " y8 D" e: e! ], f6 `; T
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */2 r/ z: u7 |2 J+ g. ?! R
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */9 Q. Y) ?% P/ o: Z8 Y  Q4 E
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */. Y' z1 C$ B  I) X6 t5 p
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */; F6 v* g- Y2 V' P
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */
    5 U  B( f5 N/ x4 o4 c- g7 q; ~

  42. ) M- K2 t$ M& _" D* j- `
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */
    ( R+ f) c+ O5 }" z1 x+ u: ], n
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */5 b% i  p0 L8 R$ {; E
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */& z! S  y* j1 K/ X8 {% c

  46. : j' i! t1 F( U( B. q
  47. } FDCAN_HandleTypeDef;
复制代码

4 i/ S8 X( n, @/ E$ I注意事项:2 x1 H5 U& x& f+ v# R0 w

" F- p( D& R! C" K9 X条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:9 @; n- F7 z8 L: v3 u* R
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码
# p9 N# {- e4 B
, ]4 u) k+ C/ J+ t
函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。, O! ~6 W# o9 C2 `, K: p
5 E+ Y4 Y- H* I& @5 B5 z3 D$ ^
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
0 a  L0 [! o% C$ ^/ L# n5 }$ i8 W2 j# {
  FDCAN_GlobalTypeDef         *Instance7 a. o0 V7 d+ ?0 E6 W
这个参数是寄存器的例化,方便操作寄存器。; w2 G- S( Z3 G" T8 A* o* D. k! U& j

+ j' L$ G+ h7 B8 I* L- k# V0 k  TTCAN_TypeDef               *ttcan6 G1 g1 m* l) a0 w5 }8 [
TT CAN时间触发寄存器基地址。) y6 w9 `$ r$ ?# Z7 M/ S
5 x$ K/ }  `& q( E& u
  FDCAN_InitTypeDef           Init
9 j; A" o8 A, M7 Y& {9 k' P4 \FDCAN相关的初始化参数。0 x: |8 @3 A' G" |

. z% h' J( d8 E  FDCAN_MsgRamAddressTypeDef  msgRam
' ^( }$ L) l  ~3 j! x7 {消息RAM地址。0 x4 G, a0 D& \! d; c- z( F( F
" E% Q/ ^% a# O6 Z. Y
  uint32_t    LatestTxFifoQRequest
1 h; T9 H: z9 ]1 v  ^& Q' w; bTx buffer索引最后一个Tx FIFO/Queue参数。
# e* w' u5 D6 N2 P& ~" m( ^( J+ R
6 J" U3 V6 U8 Q: z  __IO HAL_FDCAN_StateTypeDef State          8 \- H3 \' w/ `; b+ Y1 N
HAL_LockTypeDef             Lock          ! D8 J) i0 w' Z3 X4 c5 a5 Z

5 N7 T% o- Q+ O, C__IO uint32_t               ErrorCode
7 ~7 l1 r7 q. N7 |7 O. y- V4 t$ r+ [& h
程序内部使用的状态参数。6 U, ?$ B$ W6 O

/ L0 [) B& c; v, E6 z% ]$ ^  剩下的都是回调函数
$ U1 S3 W) ?8 g/ f( i91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
7 N9 q( ?1 a/ `# T# f此文件涉及到的函数较多,这里把几个常用的函数做个说明:. D4 x, g! E  N7 r4 @
: `; [& _- D$ Y% J
91.4.1 函数HAL_FDCAN_Init
4 u- i) e" u. Y函数原型:# j& T! K  |0 X+ Z1 C4 ^2 y

, C9 @: q; `5 w: I
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
    " ~  x, J4 r( V/ h" a% d3 z
  2. {& @3 W& }/ ?3 d0 [4 m8 H, s/ z
  3.   uint32_t tickstart;6 q) q6 {  L2 L6 l/ _) g
  4.   HAL_StatusTypeDef status;
    7 C% s+ K0 `  v, t
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
    $ j: d5 e: g4 [# k; g. l

  6. . ?% W5 V- N1 ~* p0 n
  7.   /* 检测FDCAN句柄是否有效 */  g3 [! G' U+ z, g: W1 [" g
  8.   if (hfdcan == NULL)
    0 e( {7 M- p; q8 k
  9.   {; }+ K1 [. L  G8 Z+ v8 U( Q2 |6 N
  10.     return HAL_ERROR;
    7 `: R  E5 ~1 T( f" U" R9 B
  11.   }8 p9 Z3 z9 e2 O; u3 N/ Y7 [
  12. ) p0 J1 M7 A" E! g
  13.   /* 检查FDCAN例化 */2 _# u8 g: s2 n4 ~6 ?. j! B8 q+ p( ?
  14.   if (hfdcan->Instance == FDCAN1)
    8 p7 B) y( k% u% |  C. u* S) L% d
  15.   {6 U0 ^- V, w+ [: o8 @6 d
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);! @9 I2 h1 l& x8 D. @2 S
  17.   }- k& u) v3 `/ ?3 N% c

  18. - U8 A9 ~9 Z# W( G+ v( E
  19.   /* 检查函数参数 */# o7 k4 g' a  p- H& r5 e8 S, }
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));' E4 G/ u" U/ m3 l, n
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));! _# _4 b! {- b
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));( w! Z' C6 k+ {/ J: ~# f/ l' D
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));) C1 U. [6 w0 }
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));' }7 o/ J! `3 T% c" w
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
    4 E( w. X9 i: \+ b8 _9 d' O
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));9 c4 X5 X) x  u
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
    : |5 [4 N" ]! b; G+ p1 U5 h8 r
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
    ; n2 P  z% y# [+ H+ I0 ^( W
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));7 P& _; ^8 Y$ e
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    + X, `0 }$ @  ~
  31.   {
    % Q( V4 R$ l: l4 _4 z
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));* l( Q( G! {1 G- b
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));
    3 N$ {$ O# T6 G$ |1 O
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));6 J) A4 |) ]0 W* l- k/ O& X
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));  T* L! g) g7 Q+ D- ^
  36.   }3 V( v; W) v; w* h
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
    5 R  W; u* n: j" J
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
    3 r4 ^2 y* ]) n4 s0 `
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    * [6 t' X7 \4 \# @
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
    * o% \, u/ ^$ u1 m0 M. E9 v  X
  41.   {
    3 {1 s9 B/ J" w# E$ A. v
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));' }1 H# A+ Y8 m' T
  43.   }
    0 x" m7 Q4 d6 i0 t5 a
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));; O6 i/ @! v7 P  D
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)  f+ s! V6 c* Z
  46.   {5 o. q% H3 W6 Z; }1 n
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));  g" r) p& F5 g; d( h* t
  48.   }
    7 G; T5 y: ^7 \( y. r  `7 @
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
      l; M. X3 Q5 a  |
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    3 x  \0 Z) ^0 B4 [
  51.   {
    . B3 i: p. [$ s  d9 v' k( M
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
    + o  u: e, q" L2 [/ w
  53.   }+ X/ _; j4 @9 F' Y
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));
    + a3 W; K, ?; P1 C& W
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));
    . z% l$ z" Z+ m' H6 v) D! x) Q& G
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)/ J$ s& `8 a) a. D0 M( A5 {4 q
  57.   {. G1 V2 s& ^" L9 w
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
    ! e& e0 N7 q$ Y
  59.   }. @0 f0 h/ G* s& t' ?; f( _4 ~" k6 J
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)/ F: r0 F. h% e, {
  61.   {- l( o& W& X6 n+ B( e/ r! d
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));! p' K! M- J3 x) ?
  63.   }0 r; X! R7 h3 L% O  ]
  64. 4 ^) X+ q% G9 L
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    ' K. Y' N( ^4 c( t
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    ; x% r, {# c& d9 _
  67.   {
    1 @! L: r! b) U+ Y+ P3 ~0 u
  68.     /* 解锁*/
    6 ]4 O: G$ w% k( `! f* ^; W
  69.     hfdcan->Lock = HAL_UNLOCKED;
    ) }0 E5 N: P2 q8 o' x

  70. + O2 P% h4 I) H) ~* F, O
  71.     /* 复位设置默认回调 */- u: a, R# ?) g9 I0 Y- V7 x% T
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
    4 h1 J1 `7 H9 ]
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
    % Z/ Y- Q  p$ [: L2 |
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    ) j5 h8 S: F' h, S/ R+ v
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */% x0 t5 G  y( \6 m. c
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */: T+ D4 K( j! g
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */$ s( |. J; ]6 y
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */
    ; B9 }; X1 T( K: W9 u
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */
    ! I( B. Q* R) u% C% L
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
    ( V( T! @( c% }+ R% c7 v$ h
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */) p& h% _% H5 t
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */: Z) Z- S7 I. z3 z* B4 i. J
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
    5 R" {# V  c0 s4 H
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */
    , Q9 U1 k% [" q) k0 ^
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */5 ~7 O" G9 I7 [
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    4 _( X  f- J4 V6 h9 O
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */: n- e" I2 q# g% Z1 q* _; G& [# y
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */; o* F0 j# h* G4 s% [+ h  M' N

  89. 3 A& }2 [7 m% |4 ^  o: q3 L
  90.     if (hfdcan->MspInitCallback == NULL)
    : u8 w( X  @3 ]
  91.     {- j: V: c% M  d, r6 L+ ~$ j
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */
    3 r6 V" u( c$ {! `3 `
  93.     }2 B( Y0 |/ n, z* m0 `

  94. 1 B. v6 O! b* H) t
  95.     /* 初始化CLOCK和NVIC  */
    / ?: F9 [0 Z0 [/ u7 D0 e
  96.     hfdcan->MspInitCallback(hfdcan);
    . `/ a; [; C& D7 k
  97.   }5 I4 J% g5 y! {* [5 ?
  98. #else
    . m  h5 {2 ~; l3 V/ V5 P; N! P
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)9 j; H: Y7 f* n8 p' Z% W/ A3 l5 ~$ m; _
  100.   {
    * r8 t2 r3 c# @6 n& \4 Y9 E
  101.     /* 解锁 */
    ' z1 ^+ @+ k0 R2 n& a8 {
  102.     hfdcan->Lock = HAL_UNLOCKED;
    7 d+ A& I2 K7 W- K

  103. 4 m4 s$ f! `- Q) N4 w! a, w1 J0 b
  104.     /* 初始化底层硬件 */
    ' j9 Z5 U! `: O) n( L, I
  105.     HAL_FDCAN_MspInit(hfdcan);" F, j+ Y: Q: _! T; T8 J
  106.   }
    & C9 p7 n& @5 M* O; [2 Y3 g
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
    4 d+ Q# ?. i( r8 V: R+ |! O
  108. / ^3 D" \! J/ b3 w" W. ~! M
  109.   /* 退出Sleep  */
    5 r7 ^) z- F1 ~  R7 Q
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
    ! V+ ^6 t/ g1 Q& X
  111. # }1 w( L' V4 d. c/ F. T" p* J  _" N
  112.   /* 获取时钟 */; m8 R6 p  z+ B) V$ C: {
  113.   tickstart = HAL_GetTick();
    2 H5 L8 D( F& V. |/ w
  114. + F8 C6 ]5 L1 p6 r" [" A
  115.   /* 等待Sleep模式确认 */+ ^0 _; n! Z! K5 i6 c
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)/ b3 w' P% K' Q5 c1 s
  117.   {
    " L8 k+ w+ Q* \- [( ^, }
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    ! h) O9 c5 A5 d! ^! V* s) m" l
  119.     {; i" W8 A  P! @! W, |' o4 V
  120.       /* 更新错误码 */+ l7 a5 k' I: \: I$ w4 D6 k. ~; r
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;" J2 \- @# j9 [- ~5 A
  122. 1 W) ?$ V6 i$ M$ E
  123.       /* 改变FDCAN状态 */: }$ D8 V; Q0 j' d$ U& j; D
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;5 Y. e1 R, S  n

  125. 0 F# w* @1 S; p7 a' w
  126.       return HAL_ERROR;' w' f& c7 |( |1 {/ {1 a
  127.     }1 {. e, K  F  A  b
  128.   }& O) t: `# {4 r2 F2 x. e
  129. 5 f0 h9 [, k# o5 v
  130.   /* 请求初始化 */* y0 l1 H7 g" x; N
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);  i) W3 Z0 s& f# v- H5 x9 U

  132. 8 [. v, g2 S- J
  133.   /* 获取时钟 */. A2 c9 `6 D$ a9 |' Z3 W- U" w& L
  134.   tickstart = HAL_GetTick();  h5 i0 ]4 r# B! r8 b. C
  135. " C& B; w$ }; E* M. j. V. @# r
  136.   /* 等待CCCR寄存器的INIT位 */
    9 g! r+ Y* p% a+ s. n. r
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)& {) q6 \6 W$ m" J+ Y
  138.   {" g( i; m( ~* F+ t
  139.     /* 检查溢出时间 */- [$ ?( K! `) U5 Q( f9 S: Z
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
    3 R8 j) m3 K2 t+ Z$ X5 R3 b
  141.     {; k/ M3 m/ o) |& g2 q
  142.       /* 更新错误码 */% c: _$ d8 ^) A" @0 g0 C! `
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;. D8 w$ x: Y+ D% c, |! l( ~5 U

  144. 9 s' @8 z  Z" u4 |2 _
  145.       /* 设置FDCAN状态 */
    / Y/ P% q3 P& k% n0 y: x
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;4 N8 t; ]1 T/ M
  147. ! X" k; M* y# T4 Y
  148.       return HAL_ERROR;
    # Y& H! q3 Y# N6 G$ [4 ?  l
  149.     }
    4 F2 a1 g; ^" A- ?! t8 [$ [3 ?
  150.   }# P  v% f1 j% c+ [$ z

  151. 8 M' r' V# B1 S1 {0 \; t
  152.   /* 使能配置修改 */
    , L+ _5 D' L+ y7 ^# t9 [0 ~3 ~) M
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
    2 V# J7 A9 V4 J* D% Z6 h7 F

  154. $ A# i8 i1 J# {
  155.   /* 设置是否自动重传 */
    0 d  \! _: w( ^) r7 j
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    0 E! D( w0 }/ \, L+ m
  157.   {+ {% J( L( b5 x* B3 h( n
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);6 V- Z" W8 X; V' F& t
  159.   }
    , I6 i" f. P4 z0 b: v
  160.   else8 b8 F. i  M/ ~* ~
  161.   {6 W( o4 e8 E! b1 Y" w. ^0 k
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
    - F& E3 X4 U  Y! e  X7 T+ R
  163.   }
    # C& @+ k( j6 I' E% K" a8 M4 }
  164. 5 V4 W/ c" ^5 s1 q
  165.   /* 设置传输暂停特性 */' {8 A; I( u6 i1 Q
  166.   if (hfdcan->Init.TransmitPause == ENABLE)
    8 I, f; }/ X2 O8 f( `' J" P
  167.   {/ [5 ^& H1 u' O7 v
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);: _! G7 w9 ?/ b; ~  `0 L9 ~  C
  169.   }6 R& j: Z. p1 \$ t% Q  T( Z; s& }$ C
  170.   else# E* N+ C3 _) V
  171.   {  A9 z0 \* j- A' W! R$ }6 ]& Y
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);* w5 ?: u+ t+ z+ Y
  173.   }2 O! S3 o, b# k5 s
  174. 2 |1 S0 H' ?3 c7 ~/ j$ x0 U
  175.   /* 设置协议异常处理 */* k9 N+ T/ U/ [3 y" M# M, n
  176.   if (hfdcan->Init.ProtocolException == ENABLE)# Z5 m1 q$ `: d- Q! Q
  177.   {. X( m' d6 s  x; B$ ]! c% r" [/ q
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);, l" O+ F. y) b, A. D* @
  179.   }0 L! N8 h! F7 Z# v( |2 K& O
  180.   else
    7 G5 ]9 W! o" W) j- Z6 P
  181.   {
    6 Q. _  Z( D3 I. I& c: G8 ~
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);* b0 ?. P) M3 q" Y1 G( K- S8 @
  183.   }4 j& q4 ^( P% F
  184. 3 I9 J# l; Z9 H0 J; e; |7 Y7 A0 x
  185.   /* 设置FDCAN帧格式 */
    / ^* m1 L# d' k7 u7 V/ M3 q
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    5 h4 G0 \; N1 t  u$ e, V
  187. 6 Z2 j$ ^5 v  l5 F% g: Q- u
  188.   /* 复位FDCAN操作模式 */
    # n7 V' _* s# _2 x) f: T3 L
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));
    % f6 Y/ S& s8 F( W9 t" i# ^
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);4 f& r# Q2 G# [( w7 [, K

  191. - X+ [; s/ Q3 x" S; K3 f$ W
  192.   /* 设置FDCAN操作模式:
    ) O, @9 s% n6 R! Q/ H+ w: H! r: p, X( T
  193.                | Normal | Restricted |    Bus     | Internal | External) [" _; V6 l8 ~; ?
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack# a3 U8 f  T  D5 q' m
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    1
    % O, I) k$ @3 o
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    02 b/ j+ }8 ^$ u' |4 y( F0 u
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    12 b% K/ n4 S" A; h- u- Z, k. {
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0  g+ p8 `$ R7 c# J2 K& |
  199.   */
    ; F' Q# t+ V/ Z) B' `
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION): M2 x0 h1 G6 p7 H' [. }
  201.   {, X- D7 ]* a5 Q. f+ ~8 D- S. x
  202.     /* 使能限制操作模式 */
    : b1 \7 ~4 R; V9 h6 p
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
      r% {" F3 C1 ]7 e2 F
  204.   }' f0 e/ x6 W% F  {  b: A* M5 O
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
    3 Q7 }# A4 C# r# M$ P
  206.   {" i; @8 V+ I( r8 ^8 J: c# U8 Z
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    4 v8 o$ K2 k/ h* s
  208.     {
    0 |$ l$ \" r2 j9 L9 ?
  209.       /* TEST寄存器写访问使能 */
    - X6 `0 Y$ x0 h  E$ h# X
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
    ! s' n' N. G4 o2 V" v9 }# M8 P  _

  211. 5 y! n& l$ h% _3 L- F
  212.       /* 使能回环模式 */  J/ v- g: o( G; M8 F5 L7 U
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
    # [0 }$ @! U; B* E

  214. % L0 L. ]. V9 V$ m! ?
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)$ j8 o9 w) s& f: q  a) N) D8 P; I
  216.       {4 M" {  Z# O" O* `/ [- g( S
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);1 K6 V7 o3 g$ ?: s3 _9 ^
  218.       }
    & Z: y% \2 A8 J7 A& a- S
  219.     }7 R# Q1 w9 P8 I
  220.     else
    - s. I# [* `* n
  221.     {
    4 A; ^% `9 j8 b" ^- q- j& T
  222.       /* 使能检测模式 */# n* T+ z' ^: h0 o! C
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
    0 x1 J) q) ]2 Z
  224.     }8 O) s- w4 g/ D8 g, ]0 P
  225.   }, f0 K6 Q. f$ z2 o
  226.   else8 E; P9 c5 P3 y4 t9 {
  227.   {
    3 a4 j; x* b( e" a
  228.     /* Nothing to do: normal mode */
    6 g& a" b# A4 |
  229.   }
    : i, c. G/ P0 B4 e% H0 W
  230. $ p3 f7 }' e# S2 J6 L6 r' N
  231.   /* 设置nominal bit timing 寄存器 */) _, L& k; l) E2 M" c" B3 ~# M9 B
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
    : t3 b& N8 y0 z8 H! [
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \
    , X! a- R; @! x& j3 \; h) |
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \7 s8 ^$ @* e; e" K9 X' g8 c( k
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));5 y: T" T6 i4 i
  236. 5 a& b- j" W" y6 N
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/; z- L6 \; x3 Y: u! y! X; ], }4 A
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
    9 f# l5 L% H5 a( \) E6 c- ]: E
  239.   {
    ' X% z& k1 o0 o5 v! Z1 G2 h- P$ k+ o9 A
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \1 S7 h- S2 z6 _
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \
    . b9 p3 u- f$ X1 V( |# q
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \. r4 O- O8 ?) A! G+ G! b# n9 ?
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
    9 h7 q- _1 c) `  w. V* j- s
  244.   }4 y" r8 @9 a6 }* v4 j6 ]

  245. 8 G% {6 h# q! E1 @2 w- ~) n# N
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)) j" |, I5 b& a/ Z  H$ }0 N
  247.   {& b8 `" D) P/ a( a3 `2 l
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */
    ) I! j* o: F8 m+ C
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);: D: |: m7 c* S5 |* W$ I' ]
  250.   }
    + d+ _, `5 }% \1 ?$ M
  251. . o# q  A, Y. x8 p2 h. `
  252.   /* 配置Tx element 大小 */9 F5 }6 S0 H% |) L4 m& C5 }
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)) f6 J& u, `2 b$ i+ D
  254.   {
    " g9 w2 Z, s7 e) e, [; V
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
    / I- ]% ~' B5 l2 t4 U1 J( L
  256.   }+ y' T+ a3 D$ k+ A% v9 Q8 @) \' @

  257. / U( T( w- l) m$ [7 @7 C
  258.   /* 配置Rx FIFO 0 大小 */) K# e+ @2 f; s9 e- y8 g4 T: G
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)1 O! k$ X& Q- n
  260.   {
    ' b, M+ P7 m3 G  x1 M8 z
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));" F$ c3 V; C) l$ D$ ~
  262.   }
    9 C8 t0 D$ j' K
  263. # v4 V$ O5 J% b' j7 L* w9 C
  264.   /* 配置Rx FIFO 1大小 */4 T4 o4 }& F6 e' u
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)" x4 c, x" m! u( r2 R
  266.   {5 H. l2 U5 G* u1 F( B. D
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));, l3 o( G' E0 \# _9 w
  268.   }  P! Q/ \- Y' R4 j! E8 `

  269. 8 T7 A. W- r$ W) F1 C
  270.   /* 配置 Rx buffer element 大小 */
    ; H3 f4 H" v/ N+ X# D& Q. o9 K* q! d0 T
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)
    ; c: a4 p( \2 ^$ v8 f  h
  272.   {
    3 U. ?8 n$ f+ W* I9 [: M
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));- S/ s* i& Q; K; m. u, {/ A5 K
  274.   }: D. F3 Y0 p4 L0 y
  275. + h" B# {8 V6 z- s2 I/ o
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init 8 k8 m0 o+ k) }; ?
  277. 后调用HAL_FDCAN_TT_ConfigOperation */. s& R' j/ J6 Z6 \% U0 p
  278.   if (hfdcan->Instance == FDCAN1)+ {$ |% ?. ?. ^( Z1 ^) Z
  279.   {
    2 x4 O$ K& A- [- l
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
    " b- @0 b. `) p3 }& j; h
  281.   }
    5 y1 i! p$ K, g6 d
  282. 5 N* S( v( h4 m/ Q, y8 U
  283.   /* 初始化Tx FIFO/Queue */3 p" R# d/ l7 P5 \! F, M
  284.   hfdcan->LatestTxFifoQRequest = 0U;
    # E8 V6 ^+ j" Y- b2 `" z. u, o

  285. 7 D( \- i. {- Z$ D! ~; G  P
  286.   /* 初始化错误码 */
    1 w7 o! v+ n! p
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;; G" y& V* D/ Y' F6 y8 Z* }1 w1 B8 r

  288. . }1 ~4 M% m! O% ~$ X8 E  g
  289.   /* 初始化FDCAN状态 */" a" w( y" ?1 H* W+ k- C" Y
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;6 q0 Q9 }" {! b8 v0 \2 z

  291. 4 N1 H8 Y, I) Q2 M: ]% o
  292.   /* 计算每个RAM块地址 */7 Q  K" o9 F1 |% `/ k
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);4 O: q" Y+ g9 {+ X7 K  O

  294. ! \( K+ V. g; W# q
  295.   /* 返回函数状态 */! e4 s3 e* r3 i. S
  296.   return status;# s' X2 e6 A1 q( d
  297. }
复制代码

- U2 L. k1 s- c6 p/ j' f" Q函数描述:
2 f. J5 _9 b- c. I  Y8 v. R3 B
5 b9 h" H* A  r4 D此函数用于初始化FDCAN。
$ ?8 h3 }3 ^, @- n& s2 ~: j9 D$ `6 S- x+ z/ _2 i& ]; Q. W
函数参数:  g2 O4 L; h* @7 T- U" u

, _5 G. K* P! `' u" c  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
. D% r; d" C" T  x  `9 D( u+ A2 p7 N  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
5 J8 K! ]) E, b  J, v+ ~6 K7 o1 V4 y注意事项:
3 q$ Q/ G/ W; h" t" M0 r5 v
4 `& F- b; V7 D2 K' O* w函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
: ?* u5 E( |, l/ P& C  c如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
! N/ L: }6 A- }' ~/ j对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。
( n- U) b. \" X. h9 _: y/ B  r& A& u5 f# [5 T9 e& T( V  n
解决办法有三
# V1 x8 Z: X" B- D7 K5 U; V1 h
3 e% K: R% N: i& ^' {方法1:用户自己初始化FDCAN和涉及到的GPIO等。& n8 r0 @1 u0 k" n2 \7 V1 E- r
8 Q3 r. b% k7 C& z; b
方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。! _' W$ Q8 d7 y" w8 i3 y, ?
' E/ g  f, D4 r5 b! j
方法3:下面的方法
' p0 l$ G, R% I; I7 Q. t; k" a+ o! s! O% [
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)( J3 ^8 ]& n3 m% w8 B& ^, H
  2. {
    ) B. V: W4 m' O; ^
  3.     Error_Handler();- ?8 u5 F$ P* v3 h1 X
  4. }  ' A, f' v5 Q8 b. O" e2 [3 V
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)2 M, }5 A# e9 A0 n! J
  6. {
    + ~- h5 }* ~- q4 ^
  7.     Error_Handler();+ B) R) O. N2 t$ C- B# L
  8. }
复制代码
1 i8 e) j3 j' q& p+ {6 j
使用举例:
% I& z: J* I1 ~* U( `% a$ a* i$ \/ L2 _. P5 m4 |' K8 W2 a
  1. FDCAN_HandleTypeDef hfdcan1;
    " L0 R8 N! J1 a, h9 |, f
  2. 3 ?* j8 l4 ^, j( c
  3. /*- x& r: h4 k9 k" u; F
  4. *********************************************************************************************************2 y$ R0 q% X7 t1 T. j8 t! k3 y; |
  5. *        函 数 名: bsp_InitCan1  L7 b6 I  I, g/ {/ q! y" X
  6. *        功能说明: 初始CAN1. O# i/ d7 G( D: t1 `% B! T
  7. *        形    参: 无) E  I" A- k2 {( I+ u# N) I* u. E
  8. *        返 回 值: 无
    8 H5 p* O4 K9 V/ |! J4 r
  9. *********************************************************************************************************' [6 h) v8 N% n0 X
  10. */. i% G9 Y! N" F3 i) V6 o; w& a
  11. void bsp_InitCan1(void). {! K, o% I: c2 M
  12. {         
    7 ]5 q- H3 [, {, X! h' t
  13.         /*                    位时间特性配置
    ( ?5 q' W( K6 d2 F# z7 w
  14.                 Bit time parameter         | Nominal      |  Data
    5 U2 B( ]- w; z
  15.                 ---------------------------|--------------|----------------$ ~/ ]1 v# _% Z4 {
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz
    6 u" d: x7 Q( o" p" n$ @6 U
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns
    9 ?& ~/ z& L* c
  18.                 Synchronization_segment    | 1 tq         | 1 tq
    , D1 I3 F9 ~0 f, h5 A$ Y; ~
  19.                 Propagation_segment        | 23 tq        | 1 tq
    ' l9 O" I0 E! f- U: G+ N7 ]
  20.                 Phase_segment_1            | 8 tq         | 4 tq* U) O- J6 G( c% N' d8 l1 S: ]5 r$ }
  21.                 Phase_segment_2            | 8 tq         | 4 tq
    0 }7 ~( W$ X# A+ u. H
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq
    " T6 e- T$ V* _: P- {6 S3 \) e
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
    & T9 B+ s2 U' b' W7 y; Q
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s0 z5 g. E5 j% y! M
  25.         */2 d! M% \0 K* p! v/ z- }
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */            
    5 L0 v; A& A4 P! b  a  i0 l+ T
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  
    ( k( h3 M$ E$ e7 x& n
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */ ' e: Z. T2 ~, ?" w: }0 G2 P
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */ . X" h0 p0 Y( R4 O
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */
    & d4 O. }- Y( a) o2 c
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */
    0 p1 _7 ^1 v% F; \5 S6 z& {) t! ~
  32.         0 N# g; l% N; Q
  33.         /*
    ' j7 ~6 n2 T; c$ \' E, S
  34.                 配置仲裁阶段波特率   o- a! K0 D$ W5 ~
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是; L* P0 V1 E6 d* Y
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        
    # i* a5 I6 x# @6 ^& L9 w
  37.                 % v' E% J8 U) X3 N
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    % y$ o: A7 A9 T/ v. a
  39.         */. j: S9 |  b7 Y9 D+ N
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */
    + V6 e$ u, O# Y2 g7 i8 n- f
  41.         hfdcan1.Init.NominalPrescaler = 0x01;
    % ~, ^/ \9 b/ C1 A) {# ~9 C9 n

  42. / T  q/ J0 u6 Z# n" r% l2 n4 b
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */  L! m/ R$ l4 h4 g- @7 {
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08; ( |9 N, v' v, ]4 {2 o. K" t

  45.   r0 T) t7 ]' j# j; @
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */
    8 @; Z) Q: ~. J
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;          " L6 W6 s1 L, t
  48. % [* a5 V4 c  G" E) H# V
  49. /* 对应位时间特性图的 Phase_Seg2 */
    0 _/ v" h0 F" [! i" g5 }% b
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     6 T9 s  V" A. a2 h$ K; l* e% C! p
  51. . N1 O* j! R4 ~+ i( U

  52. % S! T1 n" L* D
  53.         /* / t3 q% O1 p, z- X$ p
  54.                 配置数据阶段波特率
    ; Q( u! G6 z4 T
  55.                 CAN时钟20MHz时,数据阶段的波特率就是+ ?/ q  m' F6 V, }% I
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps* X8 _) D$ ~5 n6 X, }
  57.                
    ; n% Y6 u3 |, D* W- E# a/ u% N
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2* G) s% |8 a. w( e2 w9 ]+ N/ Z
  59.         */
    ( T7 o, x/ ?% `, Q- q/ `& L1 B; e
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
    4 z* B/ s5 C$ x) V9 Q5 s  \  v
  61. 范围1-32 */
    6 e0 _. f0 K0 i1 ], R" S# @7 N8 c' j
  62.         hfdcan1.Init.DataPrescaler = 0x01;
    0 f5 n' R0 y& n! H

  63. ) H8 r4 _5 q  |8 d) ]' q
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
    : s9 [4 N  Q! i7 X& F
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  
    5 \! k7 s- Q! B: }
  66. 8 k! M  g% @  l  h* ^+ o0 W
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */9 r! _6 _% t. p. S" G5 `; X3 X, ~
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05;
    8 h$ d; c" w. |5 X4 J( V1 l

  69. ! m7 P, v0 i+ y$ C
  70. /* 对应位时间特性图的 Phase_Seg2 */                : F# Q0 C( _0 r9 @
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           # {+ T$ `+ A: w/ \3 R+ r! Y
  72.         
    2 a1 L7 l4 V  y( h2 x# O& r$ G
  73.         . Z, ?, w& M5 H, w* I3 K, K
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */, p) V6 D( ?! J6 M8 U7 ?# c
  75.         
    4 D4 G; F2 L$ q
  76.         : N; n1 B  a: t* @& L2 h" V* O
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
    & g2 f4 A' K1 ^. |! h6 M& v
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   
    & }5 h0 _; @8 C
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  ' B+ {8 Y9 i7 q( t% ]
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   
    ( {1 w, l+ y" {' ^7 F
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
    8 _3 b' {/ \/ g  w; Q8 [
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */' {: \6 p" X- M: G1 y
  83. 1 d+ F% f; O! B9 P5 f/ r7 _  m; w
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        5 A9 Q$ D- u: O5 U  {  b
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
    8 ]$ r& j+ U5 [5 A. w0 j; ^3 w
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */
    & g5 _2 Z2 r$ P
  87.         
    ( g- d" h1 V5 V- Q: H9 u
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */
    . s8 X! o8 w8 H1 z3 l
  89. hfdcan1.Init.RxBufferSize = 0;                             
    ( G* z  Y1 n- j0 E
  90.   U" y. F, e* H$ Z
  91. & [' y5 m6 a& o+ u5 k
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        ) T' E, S$ R8 Q& o' ~/ P0 U
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
    ( M* t% G! @# a# I5 c
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */1 }* B# B6 a+ ^. P, a. N
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
    & b% K: p6 _/ x/ }$ x

  96. % P8 n( b$ J& a3 ~( B
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */
    / Q; T- M! c0 ^; b+ d! L# N1 N4 d
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;         
    + e! M8 [' `% g  z8 M
  99.         HAL_FDCAN_Init(&hfdcan1);  B1 O+ u. l/ U' N4 G; j  ~: E

  100. 7 S2 w4 N" N) x
  101. . e8 _0 }$ t: J* S+ d- }
  102.         //省略未写
    : S" }) n0 g% f7 {6 A
  103. 0 |8 p0 \' e9 w! ?( U& Z
  104. }
复制代码
8 c9 q+ V5 X; C
91.4.2 函数HAL_FDCAN_DeInit
6 ?* _9 x8 C( f: e' i5 ]函数原型:( U% t+ J7 b4 Y& `& N; V7 a: h* V9 b

. x9 }; ~4 y( c- n
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)- Z( z, A; |  r; X* S1 Y: ]. ~
  2. {
    9 k# K% d+ Y1 W9 b0 m
  3.   /* 检测句柄 */
    , K* q; \6 O: ~9 b) J
  4.   if (hfdcan == NULL)
    * L% j+ ?4 L2 H2 N% K& l3 ?
  5.   {
    , O) F+ A: u4 e3 u+ \# N* r" Q7 j
  6.     return HAL_ERROR;
    ; S5 V: T- A( W0 l$ b
  7.   }. X# \" |7 V$ t

  8. $ E0 }6 O- Q. z0 u
  9.   /* 检查函数形参 */9 ?! D! w( T  p1 Z
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));: o+ c& {+ Z! ~9 K

  11. - @6 J/ H7 P3 j: _! Y  }
  12.   /* 停止FDCAN */' @- k$ }, N$ B9 o5 S1 D9 ~# F
  13.   (void)HAL_FDCAN_Stop(hfdcan);+ Y. t( x" Q2 R6 s6 r+ z" j' m
  14. ! d9 Y: r! ]4 Q1 G/ i. S
  15.   /* 禁止中断 */, X1 L6 H8 I5 f; |# N' y
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));% s* r* `+ d5 D) R- K
  17. 2 n; \! a5 q! ?( a. V/ x
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 12 ~, l6 h0 ^& a4 l1 g- O
  19.   if (hfdcan->MspDeInitCallback == NULL)# D6 h' m: z" T# c6 H$ _
  20.   {: K: r' Q  f% O0 o9 m& V
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */% y5 c1 o! `% Y# J  P- Y: G
  22.   }
    + n& d. M) y' q9 d; L2 r% U( |
  23. 4 R* H& }5 }. O
  24.   /* 复位底层硬件,如时钟,NVIC等 */
    " b* P' F; J  N6 a7 X
  25.   hfdcan->MspDeInitCallback(hfdcan);! K; L' [3 g. o0 t( Q0 Z* J6 L2 i6 }
  26. #else
    6 G$ x3 ^" `6 m( x8 T
  27. /* 复位底层硬件,如时钟,NVIC等 */; D& N' Q! J1 N8 r* o2 F) F
  28.   HAL_FDCAN_MspDeInit(hfdcan);
    8 h" s" y: \" g( e1 q
  29. #endif 7 Q3 V- r0 _' S) {2 [8 S
  30. 7 W, }( z. {: H# b
  31.   /* 复位错误码 */  V* Z5 M' I: j- g# f4 a
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;7 D5 ?: h; ]  o+ g2 z
  33. . I; j2 c' ~( {' ^
  34.   /* 设置FDCAN状态 */! [: C0 U, w% K6 _7 ]
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;% k: G+ e! u1 V7 A6 Z' b4 p) e
  36. 1 z8 V, z# t. w/ k
  37.   /* 返回HAL_OK */. K! f! n! h8 ?: E3 `
  38.   return HAL_OK;0 O0 c( M& ^4 q" U
  39. }
复制代码

1 }; A- @; U7 f, `& E( |6 T( A函数描述:% ?& Q9 J; L! ?* U# D

$ y3 J) b7 d& S用于复位FDCAN。
7 o0 q# g3 @" P- m* c
' L6 n$ U  R  g7 p函数参数:
% ~' O3 r0 B6 v2 a! j8 J8 |: X- V# E6 d" M+ Y3 O
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
1 G5 M) i% M' u  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。7 p' g0 L) r- l. y$ E$ ~& l4 w
91.4.3 函数HAL_FDCAN_ConfigFilter
+ g7 B. w6 I4 T' d  I函数原型:
+ U; ?5 J0 C; x' ~6 |
9 t8 Y% \8 t8 w& _% a
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)* H6 M1 a5 D  ^. a  t/ |2 l) m
  2. {2 U8 {7 C* [+ q3 ~
  3.   uint32_t FilterElementW1;  s4 l' c8 h. h" a. V
  4.   uint32_t FilterElementW2;9 I1 [' s, w9 r0 [: {% ~3 T/ E
  5.   uint32_t *FilterAddress;
    " f  F" i$ V8 w
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;  p+ R! ^& |5 o5 N3 u1 n4 q$ L
  7. ' j8 T5 E, E" }! _  [4 `; l
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
    9 m* U7 x3 n+ K2 L( S% Q
  9.   {
    , K# b) A/ x+ d9 \
  10.     /* 检测函数参数 */+ ?! B- {( T1 q) c
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
    5 U+ D: o/ k. d5 Z
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    7 d5 R* c# e/ ]6 I$ \2 T2 o
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)3 `8 Y% O% \% E1 y6 s. U9 O# F
  14.     {3 B: p& m3 s# A) d% g; u
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
    3 R+ l5 O( v0 W" Z% u) L# G, o0 i
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
    5 ]1 R; s3 L1 P
  17.     }; [; \0 b/ U% r4 g' u% g
  18. % e7 R' k; Z0 O& w) K: i' @: Y: n/ ~, @
  19.     /* 标准ID */9 z: I# P% Z% z0 v* ]
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)1 T7 n$ v% w6 B9 @1 u" x$ A
  21.     {
    ) c* n) N' t( f# V$ ~1 T; U3 F9 C
  22.       /* 检测函数形参 */: s$ A  q8 R% _, A0 g( Q
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
    + o6 _- l! a8 c0 f3 t
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
    / F2 l2 i1 b& X  W; V
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
      A5 l0 k& @0 {2 i" g$ t! T1 e
  26.       {+ {! l6 V# }* T# o
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
    0 k4 E- Z3 x- }9 _' @
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));+ S6 ?# g% m& q1 C
  29.       }
    9 S* F7 i4 V" q4 F+ b1 v8 t

  30. # x" {7 W* b5 C+ |
  31.       /* 构建过滤元素 */# t! t" m1 Q- d6 S% j
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)" k' a6 O% X+ _) K
  33.       {, t4 a: V3 u- M  v& I) u  d
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |
    4 D4 Y( @' y  U. w8 b. q2 O
  35.                            (sFilterConfig->FilterID1 << 16U)       |
    7 b2 k4 C. l) N1 M, _
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |4 O5 y8 L2 ~5 K3 @
  37.                            sFilterConfig->RxBufferIndex);
    3 p# o' i8 d. k+ m7 o9 d2 G
  38.       }' _  Q3 F% f( A3 j( W8 a
  39.       else, S0 Z/ c# [- Q+ p. S
  40.       {
    & g4 ]4 M2 e3 o- f7 [% L
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |  D& o% O+ T; b4 e* k8 b
  42.                            (sFilterConfig->FilterConfig << 27U) |/ }- ]& \+ o4 u5 C2 R# i( j
  43.                            (sFilterConfig->FilterID1 << 16U)    |
    * t  A5 r( [  {) Q
  44.                            sFilterConfig->FilterID2);
    ( t0 A- u$ @9 p/ _! l$ @# a
  45.       }
    - k8 P; C5 l! U. \" V

  46. ; `% I8 M) E5 L* F0 A) \
  47.       /* 计算过滤地址 */# z" V) U# y& t  _
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));3 N+ u$ q; r; x1 @; Z6 }# K  ~
  49. 0 d( G! r  ?5 b, `
  50.       /* 将过滤元素写到消息RAM中 */
    - ^$ A; Q. `9 i2 q, Q5 Q6 _& q5 V
  51.       *FilterAddress = FilterElementW1;+ Q% B7 V8 e# W, A
  52. }" U1 `5 M# ^" ]0 B) q  ~; ^
  53. /* 扩展ID */
    0 X. D( E% j! p' P2 d( E9 t
  54.     else
    5 o* J- {5 h! _# N. N0 w& W
  55.     {" E: r) x& V) B4 d! H/ q9 X- Y1 h
  56.       /* 检测函数参数 */
    : j( f9 L- R2 a- Q, a1 F; [
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));
    1 f3 Z9 i& |% O- i- W
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));
    1 X5 V8 z  v$ K1 H
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
    1 G& k8 _/ }1 P  W0 s2 W
  60.       {) r; a  y, S+ ^$ h. u" S( G& z; p. ~3 E
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));# ~% Y8 S% j- N- a% n
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));
    $ q9 B" I% A! P1 k; v8 ~5 G
  63.       }
    # u: L5 B4 \7 Q( r
  64. : ^. [7 p, G7 p8 u. K5 i+ S5 K3 O9 }
  65.       /* 构建第1个word的过滤元素 */+ V0 h& w% e) W; }& H) V2 I
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);$ _/ T: S& p: }4 ?: K4 X) p: ^5 L

  67. 4 q: j9 Z" V* n  E
  68.       /* 构建第2个word的过滤元素 */
    ) w" l0 k6 v- _* Z
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    6 Z8 ]: e2 F1 h( I
  70.       {
    3 Y* F* N% `. J% b
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;
    2 w6 T% w7 c8 |5 Y3 o0 D. i
  72.       }  ?. S) f, ^, n  B5 p  z3 z
  73.       else2 w8 D6 `3 s+ {9 k+ F: T
  74.       {& o% a2 F! C0 Q" y# ]" c
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);
    4 V. w) K* ~/ d, v1 i& ]! `
  76.       }
    & C* E( U6 |: V5 O1 f

  77. ' S9 v# ?8 v. L# m; h
  78.       /* 计算过滤地址 */
    9 R1 K) l/ o9 L5 |9 X
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));" V7 N! e) b9 c2 V) O3 v
  80. 9 ^9 Q' X. X) d- E6 E" d% |) o" x
  81.       /* 写过滤元素到消息RAM *// f$ Z5 N( F1 w" g- T8 d
  82.       *FilterAddress = FilterElementW1;, e* G; v8 x& d: t7 E4 q
  83.       FilterAddress++;  w+ a% C  x2 M" @' S
  84.       *FilterAddress = FilterElementW2;
    ( C6 A9 v" _6 d& |6 K% i0 k
  85.     }, g2 E0 S+ {! S: i

  86. 8 O0 `$ O: i+ M/ N- k
  87.     return HAL_OK;  }! L$ N0 f3 ^( [; |6 T
  88.   }% v- V7 ?2 }& D" @$ z
  89.   else
    8 Q) P( p: e7 E! l8 g7 o  ?
  90.   {
    0 g2 q7 X, b- }- b2 Q- D( |
  91.     /* 更新错误码e */6 Z- G8 z3 I0 _
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;8 m& G3 }( V* X. F2 C

  93. # j7 {. W5 B& p5 ]
  94.     return HAL_ERROR;
    3 w6 g7 W& p4 H4 E) `& r6 y
  95.   }" `  y* S5 r# r
  96. }
复制代码
2 N: ^2 D; S% O. S( N5 {( C" o: N
函数描述:( Q0 M# [. b! h4 j) ^

0 l( m  ~' q2 m6 H  f此函数主要用于设置FDCAN过滤。
3 d( l# |, N( ^; q/ u5 m1 c0 c. b* |# m
函数参数:
( [( k( V/ v7 k6 d& W% Z0 j  t7 ]% ^# k, P& t9 R
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。, A% }( |/ ]% M  x) z' l
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
- _5 J. i0 p  [" ]  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。+ V+ }, H7 K2 E$ ~1 k" }5 c
使用举例:. h1 q; B6 e5 R9 D& G

9 I# R1 Y6 I; y: a
  1. FDCAN_HandleTypeDef hfdcan1;
    / Z. |; D' H  ?" M* |# D

  2. - }$ M9 T% u1 n/ H9 b- w
  3. /*8 O4 g. `$ K1 t  h" y
  4. *********************************************************************************************************9 H6 B6 I- T& A: v2 e
  5. *        函 数 名: bsp_InitCan1
    " i# G1 P  V: e, M1 w6 B3 T2 m
  6. *        功能说明: 初始CAN1
    / _$ k2 @+ O; K0 v1 T% D  L0 v
  7. *        形    参: 无; _6 W3 R+ ?& v* r' U7 E" \
  8. *        返 回 值: 无
    : t9 C, J" F2 E; w5 U1 c5 Z
  9. *********************************************************************************************************5 y) @5 v; s1 O, O
  10. */
    " M0 R4 U# p3 W7 a$ y5 |( F5 h
  11. void bsp_InitCan1(void)% M; t, m' c; E* Q- s5 x
  12. {         
    % `$ l& ^1 f* X  b% z
  13.         " \6 @! A6 ~" i% ^/ J; [! S
  14.         /* ! q+ x4 j6 [9 J' g3 a: Q: w9 b
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。# W* {$ @& u+ x- M0 H8 q3 E
  16.                 FilterID1 = filter0 e+ ?) b" C1 L3 F7 e8 A0 p( B- D& J
  17.                 FilterID2 = mask% ?' H4 D5 I6 h5 U
  18.                
    ; |, ^( J  t( t  ?# p- {3 s0 J
  19.                 FilterID2的mask每个bit含义
    ( ^' F) ^! k. D7 @# r: j
  20.                 0: 不关心,该位不用于比较;
    : ]! L( f( }1 t
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。/ y% e- F' h9 ?' x( _
  22.                
    1 i! a6 i& f8 J7 ?. d7 f
  23.                 举例说明:0 q% @/ h1 I! }& S7 R
  24.                 FilterID1 = 0x111
    # A+ v  J& k4 l+ y& Q
  25.                 FilterID2 = 0x7FF
    / d6 Z2 c5 a! l- ?( f
  26.                 表示仅接收ID为0x111的FDCAN帧。  d, `4 X( w5 y, Y
  27.                
      q: }2 ]8 v" X
  28.         */
    2 q+ J% `6 U; d( R
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */
    - E; k1 U' g0 c* h0 b. B
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
      M& q, ~+ g- V* C2 ]
  31. sFilterConfig1.FilterIndex = 0;                                                   - L1 w8 v; E% l4 w! r: d; ~
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */
    ' e6 e  _# t+ T' K1 o& i
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */$ G) p! \4 w. F
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */% D( n7 h; l  l8 ?
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */2 Q  @2 d" \- c  X
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */
    # v' [/ @: v, v! K

  37. , a8 \. w+ |& Z& |- N8 F9 y
  38. }
复制代码
( S' s& v- d, {& K3 b' z/ n# Y
91.4.4 函数HAL_FDCAN_ConfigFifoWatermark; _2 _9 V8 o7 f
函数原型:
8 A' K0 `0 T3 k5 o# d( q) q7 B+ P+ b( b5 ~5 I2 S- z, Y" o+ G& A
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)) y. l5 c: O6 L7 t+ q* X7 @8 Y
  2. {, U3 [9 L( a" ~& E, ]
  3.   /* 检测参数 */
    : Z7 ?! Q  n4 k! s5 c8 m. Z  [
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));* V# L. o9 w( o- e
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    ! G$ |$ V5 i  m
  6.   {
    " M* @6 t6 w5 E$ U6 l2 }4 G/ R% V+ i
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));3 D( @! d3 P' a3 s% |7 f
  8.   }
    # y1 i* W; I8 |) U8 E
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */3 k0 i; b1 }# V! D2 e! @. `
  10.   {3 r9 k' F3 h- Y" Q3 |: q! u% \
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));3 s( y5 g) c( q: f; [
  12.   }. X* L  u! ?0 ~1 l5 Y0 {. [, i
  13. " O$ W2 l4 y3 O: i5 T; {# x. L
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    9 b) z; a+ q4 C  A0 q3 {  y
  15.   {
    # g9 \& f2 F3 a* F( N6 O& o/ F
  16.     /* 设置发送事件FIFO */1 s& N+ A% I3 f  ^6 a4 X! i
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO); G* [: A8 R% W8 b" M" {
  18.     {
      q0 d; |- \9 x0 j& t9 ^, Z
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));
    : N5 c( h6 a+ x
  20. }% F9 j% `1 t- o1 B7 O
  21. /* 设置接收FIFO0 */% b. D2 `3 m  K% y, ]+ k! g% Z
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)
    + Q) {0 H  b& a* k- A2 Y$ F/ l
  23.     {
    - Z+ I; B) c* s+ m7 z
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));* y! W' _! |  u/ E
  25. }: q/ k* g- F  ^, X
  26. /* 设置接收FIFO1 */& ^( F+ W5 z& K
  27.     else
    9 A" S" C( e6 I  w
  28.     {
    ' T, k2 F6 N/ o) I2 f& ?6 E. u8 x6 G
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));
    8 G( A) H' {$ F% A4 G; x* G
  30.     }, e& C" V7 `* e7 S( O- V

  31. ; @$ v9 ^0 N4 }( K( B, w% b' Q
  32.     /* 返回状态 */. {/ Q- a6 |1 {3 o/ r2 p7 n( `
  33.     return HAL_OK;0 p0 t7 C$ {/ l- ~* }1 g
  34.   }6 V: f* w3 C! S8 {
  35.   else
    ) O7 s3 y. y; c' ]/ Y3 v+ k' o
  36.   {, d! ~; e$ t: [
  37.     /* 更新错误码 */
    ! l% Z2 C3 {1 ~+ V
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;
    # [3 u) k3 t7 J# Z3 g) _2 V6 M) ?

  39. 9 W: H8 h+ F7 Y# a+ Z! H4 U
  40.     return HAL_ERROR;- h/ h- {' w, A7 P+ z
  41.   }
    9 N" W) H' ~1 a  C6 \6 c
  42. }
复制代码

7 z, {7 Z1 R# e函数描述:
1 k6 ?1 g' b* L& m) l1 [+ H+ m1 g0 M2 S# K
此函数主要用于配置FIFO Watermark2 X, w2 w- @/ v5 R3 j" a6 H

& m$ E* e0 L8 p, o$ ~' A! {" Z  B函数参数:
, C$ T8 P' c( |
; R  p. o- ]1 V1 ?4 d' {5 I  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。# `$ Y. E- I7 u' R
  第2个参数是FDCAN FIFO Watermark
5 F# s. S' V6 h1 s. y% Q
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */) r6 Y  H: g3 z1 c+ C* h7 h( c
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
    & f( Q& Y7 T- f( v6 e
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码
& S; U& N5 }7 L/ P" Z6 q( e" |& f
  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。
, \: A7 m% p1 P  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
1 u. w" L4 o; W2 ?3 [+ Q使用举例:. K2 D2 |. s' m: U
5 m) f: a3 z1 }: `
  1. FDCAN_HandleTypeDef hfdcan1;( [  p5 K# a8 L0 L* J5 i
  2. # {; v2 L" k: e( m# k" n3 E6 t
  3. /* 设置Rx FIFO0的wartermark为1 */! p6 }# }* x$ J
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码
- P/ I# b% X6 i2 T# B: D
91.4.5 函数HAL_FDCAN_ActivateNotification2 c3 w" f$ f& ?5 \, U" z
函数原型:4 c' l+ t1 s3 w7 ~

& E2 R! M& k: Y1 Y! ?
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)9 E. h+ m0 R9 r$ w0 U3 C1 f
  2. {! K  [; {/ C+ L9 K5 l5 I
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;0 J1 z7 Y8 A& J8 M; j! l- _

  4. + G; L' U+ m5 B, o" N
  5.   /* 检测函数形参 */; c! V/ R2 s* V4 q
  6.   assert_param(IS_FDCAN_IT(ActiveITs));
    # u# v3 P. Q$ S7 N/ ]4 I( Q) K/ N
  7. * y1 c+ c6 P5 T- }2 @9 L7 m0 m2 q
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY)), q) l, f+ `! H& f% J
  9.   {* r% k9 Q+ l  C- L* T) m( J
  10.     /* 使能中断行 */
    - u. k. r2 ]' ~- k* c
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
    5 M4 I* W0 e! |6 S* Q
  12.     {
    7 [; a6 x. l6 {/ A9 n7 F
  13.       /* 使能中断行0 */. g, r( w( l! r- I3 W! F" d
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);7 B  z( o* M8 c3 M
  15.     }
    8 P* G' Y7 D" U0 Z% G
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
    ; V7 y, X- S9 T; \- r
  17.     {/ d7 f# o: B" j9 v  a
  18.       /* 使能中断行1 */
    ) l6 ^# w& c) U. E4 ~
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
    ' G. K  [1 a* r9 h+ \
  20.     }
    0 V2 y. ^* d, t$ O. l
  21.     else
    / ]. d  u7 ^9 v6 P' @
  22.     {! p  z  A% X# |. V5 ^, s) n
  23.       /* 使能中断行0和中断行1 */; T9 y" c' }) i9 d
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);  o1 v* B$ R: F
  25.     }
      c( _5 Z8 o3 T' D1 h; s! d. B+ T

  26. 5 Z; @) B- }5 L
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
    & [$ L' ^' s. h. ~( ]  K
  28.     {7 b* C, w8 ^3 W; ^
  29.       /* 使能Tx Buffer Transmission 中断 */; t" P6 S8 K1 e( I* {
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);
    " @6 e% \% J' L# M- O
  31.     }& _5 ]' q5 ]" s
  32. ) |; ?5 v" e1 ^/ |1 b1 D  e# F
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)! Z4 @/ `  n2 b6 {/ c* |/ H+ k
  34.     {/ K5 b1 R! X+ W6 j
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */
    $ p  j8 P. Q+ r- @4 b4 E
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);/ ^+ q, R! P, o& X; r! V* X/ [) v
  37.     }* W( _1 s2 `3 |$ G( r5 |9 r
  38. - S3 ^, I! C, \) ^1 n+ W4 r
  39.     /* 使能选择的中断 */3 v; R! O( u" `" j& T
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);3 U- R1 C. P& y% T: T6 Z

  41.   c5 w, f/ d2 e
  42.     /* 返回函数状态 */- L  X# \, u0 N* }5 N9 [/ D5 @
  43.     return HAL_OK;
    ( B* }  D8 h; t9 F' c
  44.   }
    # V  s; d. b+ j! n
  45.   else
    1 ~% ~5 X5 {4 H! B
  46.   {" q/ O- |( Q. I4 b
  47.     /* 更新错误码 */
    ) X. D  r( a4 k1 Y% O' n
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;* Y1 B* q" p1 ?, w7 Z7 a$ Q3 N0 ]
  49. + T6 b" V/ a* a* ]
  50.     return HAL_ERROR;- R# R0 l% T! t, Y/ i; I# W$ I
  51.   }
    ) W) h3 Z4 u/ n: u' w& {) L3 W
  52. }
复制代码

2 D9 ^9 ~4 N6 I  |, Y$ u函数描述:
2 ~" G- U0 i% N) `* d" h  o% f( |+ q! Q2 {  ^. ]4 P) K! i% q) |
此函数主要用于使能中断。. ?& i2 _3 k  N, j* }! ~+ U
) i% ]' n; G0 `" a+ K
函数参数:
4 C( O: Z9 X) W# E  t
" N- B9 i4 t0 G; B3 U0 ]( p5 }  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
- O" J9 k+ w- Z, C9 U  第2个参数用于设置要使能的中断,支持的参数如下:6 u" x; d+ s$ T3 q, g
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  
    & h' M. ^" g; Z" L4 }9 Z
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */$ Q/ D5 O& Q5 N
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         + N! P: ?5 S( `9 M/ F
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */& q" d" }. W: c; d
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer ! O% U) S: O; [# h) B
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */
    3 D2 O% I, K! @" t9 u* R7 |6 t
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */9 `! n( \) w9 L' c
  8. 7 B6 l+ E- l$ l2 {' n) K+ r- ^3 r& ?8 r2 E
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */! V7 w3 c6 D2 F4 Y: b9 r
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred * i! M# e  k% X% N9 ?+ e
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */& Y% B7 X0 F% K1 k" F
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */; Q2 W& x% t* D- A( t
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */
    / v  b. ]0 ]7 G' z  [2 K
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */0 c9 n1 v" s- B8 H: x
  15. 8 R( P! \' `% j3 `4 {  ^: }
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */; y, c* h* z" E" R9 ?" e5 s4 _
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */8 B6 |6 P, O' ?5 C2 t
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
    , E2 H3 \; k* ]% I  W, C* s
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */
    * s# k7 c! e+ P& r+ R) b: V: A2 P
  20. # j1 ^5 g) P, m3 f3 k+ y5 P
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */
    + i& S. Q9 |: n
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */
    : E7 j, @) f! r7 R
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
    2 M" g2 E  Z# d) O' m
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */
    + w0 s2 s( {0 v( k
  25. + W9 a2 |: b, |
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              
    8 ?" r5 ]: ?3 J: D1 k( M
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
    - t1 _# c; ^' C; E6 ?
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  , z$ J: Y0 n" n
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     6 l( f9 \+ K7 {: y
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            + l5 \; z' Y5 {
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              5 w# [) t8 I$ A( }# ^. K! W
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */: _# O: F$ E, F% o! s- T/ @
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */
    8 N. i) U7 y6 O. e' `. `1 Y' M# }* }
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码
4 y% H% g& d5 a1 C
  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:
  A  V0 Y* k( F4 r! N$ O
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */
    - V! @) B6 X3 c2 D
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */+ g& [2 W$ P: y9 b" K0 W
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */
    5 `, L. y  E- a, H! M+ p
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */# T. s% p6 ~; l' w( F1 @' ]0 x$ S
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */
    ) P' W9 ^7 Y4 ]# I2 W6 n& J
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */0 w1 ~4 y0 r+ P& W4 \; j& J
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */: F) f) p- v! @, n8 P- c: v- P
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */
    4 Z% \3 G, R$ @+ C5 f: Z: X* Z" g
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  *// j5 a' y4 s3 X% S# X8 l/ O
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
    0 w; \6 C  Q4 z- I$ ?
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */5 u6 v# B( ?, C& V. ]
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
    ( p0 e$ G* V& `1 d* ]; {" d. m/ h
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */4 ]" r; [6 d% p8 k% x
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */
    ( }# p' r# T$ ]6 d
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */( c) |4 o' A) v( J
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */$ R# d2 F, J0 k0 v3 r* u
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    ( Y5 T6 H! }, G! k2 _$ s" K3 @
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */8 M) G2 I# ?' [3 u. @* j( l
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */# w7 \% q% S$ I" p0 y0 ]5 O% S
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
    ' n5 Z* X) P/ r) [
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    ; d) {1 Z; N& p1 \; p/ V# u
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 *// x4 w+ ~) P# c( I$ p% r9 C
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */0 h' W8 m6 Z& B* t4 m; ]
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
    . |7 s9 X: _: H/ E
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
    , ^' K8 m0 X2 h# `
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */
    6 e! @% V6 |1 c& J# I# M
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */  T, o& ?6 X+ V6 \' ~
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */
      G1 d# H% r6 G! }. i9 ^7 M
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */
    4 D! q6 O& X8 f) Y6 i9 i5 ^
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */; R* }( D! S! [, b
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */2 q, p+ a( r6 W% h
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码
8 b: L# O) i6 G8 Y, x; W5 ?0 W) P
如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。+ G, w( v4 a0 i2 m  {4 \+ O6 G

( d7 d$ v. e) t3 F" u" S2 C  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。: F$ V- [( A( {' `9 t
使用举例:! O. P$ o! T9 n* J2 d6 c

( i& y. \( P3 x4 I% V) O+ |& pFDCAN_HandleTypeDef hfdcan1;
+ k& }6 d. ~$ J( r2 f0 Y
4 ^# x+ m9 j" {5 K, s3 e9 |# C' Q/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*// X" q, L/ l+ Z! U8 j% f
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
6 I" L* I/ ~  `$ l5 h& f91.4.6 函数HAL_FDCAN_Start
* K5 x# E6 r& `函数原型:
/ S& {+ R+ T- N/ c, p- Y7 j3 d% y7 [2 ?7 {
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)% w6 d/ r& p! ?; E% L
  2. {5 T. ~5 w0 r) [0 e8 a9 @: s
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)3 R2 y8 P! i* B& M, k) E* z
  4.   {* Z4 }! h  j( y
  5.     /* 设置FDCAN外设状态 */
    + O6 t, M0 X. ~" A& `+ V; k. P$ d1 R
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;' N# q& v$ M- I4 B' |: z
  7. 5 u3 p' J& U4 a- k
  8.     /* 请求离开初始化状态 */
    . |+ F3 w% q9 d1 q; v
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
    ( m; ^% J" v6 k& |# u7 Q
  10. % R" l6 U' Q/ ^' r6 ?6 f
  11.     /* 设置错误码 */
    / D1 D# }% e! L0 D4 G$ z
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    + f8 ~; B" V! [/ {
  13. % r, I+ \% I: S# F; e% K4 `# k8 e
  14.     return HAL_OK;
    0 r6 j  q, i; v# T6 s
  15.   }3 [. E9 f8 ?0 l3 ~8 U
  16.   else/ @" U: B! l/ H. a
  17.   {
    & a% I/ h# a* R% R
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;* v- d4 L' w% ?' x7 S" h9 N
  19. : v+ i4 g- s* e
  20.     return HAL_ERROR;
    ; A: k" ?5 F7 u! s7 l' g, b' N
  21.   }
    0 @* T2 y- Q# \  I1 ]
  22. }
复制代码
2 a1 O6 Z2 @5 B2 `
函数描述:
( Z0 l4 L3 m6 H
1 U; X% O( F1 y' T4 ^1 c此函数主要用于启动FDCAN。
: I3 j% g8 G9 U& F- ?
' `' _5 u0 t; F  M8 j8 B函数参数:
3 u) t4 n6 Y$ m0 |1 Y7 G! a8 u
! {2 F+ [) {8 F: y; j8 g" u8 f: Y+ b  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
3 i7 y$ v- ~8 o0 H) \8 \# R  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
% C! e* \/ {( B; `2 y  I使用举例:
; \7 d: k5 i+ L% c  R& u0 \; O9 Y
1 \  `+ b1 n; Z
  1. /**
    6 l# ?3 x7 `6 K6 G, }6 n* s
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.0 Z: n( W, c' J+ N1 U
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit
    5 R9 g( N) ~6 l9 d2 \8 O4 u
  4. * @param  WriteAddr: Address from where data is to be written* f! v: V  |& U  B) }
  5. * @param  NumOfBlocks: Number of SD blocks to write: H  J  q+ q! a9 I2 M
  6. * @retval SD status; L: O! n9 A6 R8 L. o! ^+ T' |; j% V( i
  7. */6 k5 w6 B# F) V
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)  e1 {" E5 z$ T5 V% Z7 B, F/ |
  9. {
    2 Y! c/ H9 Y6 i# M; o  J* s
  10. 3 Z! ^9 T* ?2 f( f1 Z
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)& j) ~1 ~- Z1 c* k( E2 ^/ _
  12.   {
    9 ^9 p! ?' u# b/ A2 }. V
  13.     return MSD_OK;" g' @- ]' X9 _9 d
  14.   }5 D" N$ V  o# a  h; N
  15.   else! M5 u! _' V" S: B5 `
  16.   {$ C3 ]9 ]5 k6 q$ e: s7 s( l
  17.     return MSD_ERROR;6 f3 E. g; b( j2 ^) O6 a
  18.   }
    . T* ~) l9 u* p7 }
  19. }
复制代码

- d2 z4 w2 `% e0 x91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
" \1 G' `9 U1 }; K函数原型:' w" }% H& o; ^; ^1 a. Q* N9 |
5 E5 m9 p6 T7 c* S0 {0 Q, O
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)3 m. e! }! G% V! N7 Y! h9 A
  2. {
    , T3 F" T9 C) R0 Q* P7 Y$ E2 B
  3.   uint32_t PutIndex;& `; R8 b8 b& Y, Q) P# F
  4. 7 b9 }& `1 j  H" F
  5.   /* 检查函数形参 */6 S' j1 ]2 }' l3 `' G6 _) p
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
    % p# A" i3 w6 n/ A- V- A
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
    , s9 `0 _$ M8 {: `6 P, x
  8.   {
      o+ E6 T- l1 G+ j6 n4 I6 l7 A
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));6 O( k* G9 A3 L4 b
  10.   }
    4 D* ^* v; N1 {$ D- I2 b8 Y) g
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */$ m, s6 X8 N0 Q* C( a/ j. j
  12.   {& V( U+ @* Y2 f. C" g+ C3 x4 v
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));$ |3 [! s. u4 v9 b
  14.   }/ A. T% ?0 o6 z0 d
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));; b( o6 q8 D" B( L
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
    # u! k  \4 `6 R
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));; c9 b& c( O9 u2 N
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
    % q# o2 _/ I. h- d9 |, ?; o. F
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
    2 M. ~" b8 b! F
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));
    % ?2 ~# s" }2 d7 A' e
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));6 Z( M- V) V% |3 m! N4 q

  22. $ F! }, }7 `0 ?! d8 U2 {! e
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
    1 [2 ?5 [- Q# @$ ?
  24.   {- c' s. q( `: n6 z8 x: z
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */- j1 V$ F/ `8 P6 B7 T8 w
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    : b3 w+ @- w/ F
  27.     {
    6 l" e, o) |9 b! k( L1 B
  28.       /* 更新错误码 */
    5 G5 Y% J5 B' w' u
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;# z& y9 o- |( c: b

  30.   b3 }, u+ r! c7 u( O
  31.       return HAL_ERROR;1 f# A  l7 ~1 O: o: S* J
  32.     }
      G  P) t+ T# P  y, ?

  33. 1 t9 t0 H/ }0 G
  34.     /* 检查Tx FIFO/Queue 是否满 */' F/ `) K4 g- D4 c" a
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
    & X, c3 p# ]0 b1 F, c" U" a7 ^0 E7 `
  36.     {
    ) j: U3 p! B0 G4 p$ w# x" E
  37.        /* 更新错误码 */
    ; v) X* p" ?, s. b' O; b
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;) ^6 V0 \: d" [# b8 `
  39. $ G! d6 M2 S3 e* i3 v( q) G# @
  40.       return HAL_ERROR;& u2 e" y5 w% B8 O+ W1 z2 k, q) V
  41.     }3 y7 P1 K! X# \" B2 X: L
  42.     else
    . }0 f8 p7 ?  K1 }0 U2 I
  43.     {
    0 Q& x2 u% P5 j  [( [0 T
  44.       /* 获取Tx FIFO PutIndex */1 k$ V; u3 @+ ]8 A" X5 V+ m6 X4 J
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);+ N& e2 w' U# i7 u4 y6 j
  46. 8 d: w1 D7 @6 r. M" b
  47.       /* 添加消息到Tx FIFO/Queue */! F7 ]/ ?! E1 ?
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);
    " C6 Q! S' z/ a

  49. , ?4 a7 C3 T, @% ^9 y; K( L
  50.       /* 激活相应的传输请求 */
    0 Q* u) w( @4 x: k
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);
    ) _4 \9 Y5 B3 _/ b) ]( \# G  D

  52. ( u$ {1 ^' ?# F& \* ^
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */( X1 }$ z- y/ l  m: N7 B
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
      B4 V, }7 Y8 }% g( |
  55.     }; K: M$ M0 Z' q8 W* h
  56. # }# G$ z% z3 g6 ^5 J/ D" [
  57.     /* 返回错误状态 */
    & d  g7 y  U3 f; q: d1 d) M
  58.     return HAL_OK;
    1 b# [6 N9 R$ @/ m$ @' X; ?
  59.   }
    . P3 D# K. x, A& M9 |5 Z
  60.   else. t# \* S5 q6 r  B9 [6 k
  61.   {
    3 Z( C* X. p( O6 e8 O
  62.      /* 更新错误码 */
    ! J* @6 T* z+ O
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    , K; Y: C" R7 G, @* [, U; R6 n
  64. 2 _1 n9 x7 s5 ^2 l) m
  65.     return HAL_ERROR;
    # i( f; Z) h0 Q
  66.   }3 X$ Q1 H0 L- C
  67. }
复制代码
1 b, R/ @( _& ~* t! m
函数描述:  P- t- h# B" D& [5 o& _1 Z& X

2 |, C# F6 C* _/ z# [此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。
- i& i& M* n, K. Z
" x+ [% v: ^6 U1 g3 u( q8 d  }1 D: r函数参数:
4 T; D* F; E: }9 n( _# O! E2 K. h5 Y, h; Q, n. [. o- V
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。" _/ d( {/ j; O8 F! q& S
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。& A- B! M! t4 @# e& j* h
  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
" s6 V, e3 N) V0 @" [+ V  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。. B. e0 ?* e; A9 v
使用举例:4 I+ W8 n, r/ {4 S0 u

; M. d( z2 f8 O% k0 ?' K
  1. /*! w5 o0 u1 f- `; Y% G
  2. *********************************************************************************************************9 u; V7 C( d8 z. Y2 h/ M' u, [! {4 K
  3. *        函 数 名: can1_SendPacket2 w) X7 y& t" ]5 S, L5 ]  J" ^
  4. *        功能说明: 发送一包数据
    ! C5 N+ `. e% b2 E3 b' ?5 a7 O
  5. *        形    参:_DataBuf 数据缓冲区, ~+ N: P& C/ s3 F6 ?- D1 E( [
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节
    9 ?) Q& j' J  s* A  k
  7. *        返 回 值: 无
    6 k3 F; i1 U& O# |3 W. c' M
  8. *********************************************************************************************************; Z- ]: i0 _. r4 |, Z" ?
  9. */
    ( s" J/ G7 s+ k6 v
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)/ z$ ~7 N4 d  P& N
  11. {               
    ; w5 [* r) l; C) h
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};
    & t7 p$ w) R, k) M
  13.         
    1 \- [: |# z9 x0 v5 ?; b9 L
  14.         /* 配置发送参数 */; H5 @, G: r6 P& F% x
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */& [# j9 R& O6 `1 w- o( s- b
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */; X0 q" ~8 f: ~( E
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
    . n1 u6 p8 E- K  y5 z4 K5 N
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */
    ; e. |  b, w* k$ ~/ ^2 Z, W8 \
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
    1 Q0 b" w9 j. q* ]
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */& T! O8 E- N/ ~9 i
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */. L& H; Q7 T( |& m0 {8 r
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */5 `) \! D( q4 e0 [. D$ @5 v
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */
    6 R  T) \* R7 n+ b+ s
  24.         
    ! \9 s! V( Z8 z$ m+ J) }% q/ A8 v
  25.     /* 添加数据到TX FIFO */6 d0 A* ]0 [; r6 O
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);" j, S. F2 z' Y1 h8 p
  27. }
复制代码

% f! S  v; n. F2 M; ]91.4.8 函数HAL_FDCAN_GetRxMessage' r3 U2 ~/ P" P# {- G
函数原型:
+ g8 z( M' u2 \& a3 i- a# y1 C; ^8 v
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData). d$ z! ~. N! }( v
  2. {
    7 G1 j8 x" m! e5 i
  3.   uint32_t *RxAddress;
    ! m+ }' ]& Z: {
  4.   uint8_t  *pData;9 V8 n9 W, `' J  C* E6 a
  5.   uint32_t ByteCounter;+ E; V, x- H1 N/ }, d5 r
  6.   uint32_t GetIndex = 0;
    ( c) j: Y! @  J& c0 A. O, b4 s6 y
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;
    5 z2 Z* u9 }4 }# l
  8. * S3 |+ D* S1 I
  9.   if (state == HAL_FDCAN_STATE_BUSY)
    3 _7 \% E7 p6 I- j3 B
  10.   {* s# s) x0 h+ Q( l7 ~9 h
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    ; Y& }! y: J" w) a# C5 ~5 Q
  12.     {# S1 a% P/ `( M$ l2 I$ Z. ^# [" [# U3 a
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    4 f* A3 _: i! @0 J0 V% ~4 I& \: _
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
    / j/ s% D  I0 m. D" x, ~6 t" V, e
  15.       {
    7 {: s5 C5 e4 m, }9 ?9 C% r, R8 M# F
  16.         /* 更新错误码*/( o) k5 A' @6 w7 c- _
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;' d4 T8 z6 [) ]* ], e8 O3 {

  18. 7 n0 C9 \. z; [! E7 c
  19.         return HAL_ERROR;- [- }7 E4 v0 `/ E1 h# g$ o
  20.       }
    2 p# f8 N$ {2 M: C# E5 C  p' F
  21. : H+ l! L8 _% ?
  22.       /* 检查Rx FIFO 0 非空 */9 {8 Z8 k3 [5 @; J: v
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)+ s4 _: i- `& L$ S& S2 L
  24.       {
    4 }3 M5 v+ Y6 @, H: v" e9 ?
  25.         /* 更新错误码*/6 m) y: ^" K8 ^4 k+ p4 }
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;( X- {9 P1 T+ O: K
  27. $ j& O# ?) ^# C  s/ J
  28.         return HAL_ERROR;3 f. ?- n+ P  z; V
  29.       }! s+ y: F2 {4 w* w5 ]( a% G
  30.       else6 h9 s* \. H+ r9 N2 F. A; u
  31.       {
    " o3 G9 G) @1 S- n) L. w
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */
    $ j! W4 @) F) x$ l! Q1 e" c0 E
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)' }* V! U0 C+ V9 V' d( ~6 J
  34.         {
    2 q* F9 ?' T6 B. X- o5 J
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)( S! I1 n( [& h
  36.           {
    - J8 J* l' e. u, O
  37.             /* 开启了覆盖模式,丢弃第1个数据 */
    8 L( c; T  E+ \3 |
  38.             GetIndex = 1U;
    . n. l5 l+ i2 n: D7 ~5 m( F* {6 S
  39.           }1 R' g- l6 J6 B4 b! Y/ T1 R
  40.         }6 k% z$ u& u& V6 R
  41. % a8 o$ K, \; C6 D) L; {6 c
  42.         /* 计算Rx FIFO 0 element 索引 */% r" c3 O$ I. D' D3 \! w2 ^2 [
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
    7 c2 h) Z, O8 `, u

  44. ' k" c. ^: l6 I# L4 X
  45.         /* 计算 Rx FIFO 0 element 地址  */1 r4 a: @  H. L
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));- j9 O% t. S0 E
  47.       }
    3 d& K; }% e- u1 |1 E
  48.     }
    8 v; T. N) D5 b0 C7 T/ J5 Q
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    7 w2 v. w5 b) a* {8 U0 f8 I) g
  50.     {
    ; O" V8 y2 u( A) n: _
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */
    9 B3 {7 O$ h% o) U
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
    5 Y! y# g& u! l% }# N, B
  53.       {- m; A% R& ~. U" R$ j; y# w! B
  54.         /* 更新错误码 */& F6 x, n9 h/ U$ b4 R* `7 A, `
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;. r3 E9 }- S: J8 t/ B
  56. : R8 N, F! n$ _5 {3 T5 M, S. T: f* P
  57.         return HAL_ERROR;
    # [% E+ Y2 y9 F$ l
  58.       }
    1 \) Y/ k' H2 q

  59. " \. r* W7 a9 I9 h. H' r) h
  60.       /* 检查 Rx FIFO 0 非空 */
    8 \2 k) @7 u( M6 @$ Q5 m* L0 b8 f
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U). m- K& `- Q1 B8 ~# _
  62.       {2 A8 P! M4 M. q# b
  63.        /* 更新错误码 */) Y* |* q) O. u* t
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;8 U5 }6 e. ^# w1 g! k
  65. 5 y, A) `; `* E/ N# R
  66.         return HAL_ERROR;2 V+ U! |$ y) p, D# K
  67.       }* ^) F1 H; m. t/ l2 F
  68.       else4 z- C+ h# ?( g( J4 E: J
  69.       {1 H5 C' ~/ {5 O( C! ~2 |  x1 c
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    ' ?5 c4 G. K' W$ ?' L+ b
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)
    & o  \- G. _, v' \6 V  m6 P
  72.         {0 G  x) f: X. ?8 Q5 e% C3 Q+ ?
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE): Y7 u" O+ ?, {
  74.           {8 p: E% v% D7 m4 [) R/ R( Q% ~* |
  75.             /* 开启了覆盖模式,丢弃第1个数据 */
    ! H2 `  D$ u+ }' X0 R3 s
  76.             GetIndex = 1U;  B' W) g1 ^3 s) }3 i  l( @
  77.           }9 m' ?& d5 q% o$ _
  78.         }( a+ ?3 e3 ^* ?2 X. E
  79. ; y7 P5 l+ y/ a! B( `
  80.         /* 计算  Rx FIFO 1 element 索引 */* S' S5 N$ N  b! m
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);2 W8 C5 e/ x- o, w4 I4 u  f

  82. 9 s* \5 ?+ B+ G5 T( F
  83.         /* 计算 Rx FIFO 1 element 地址 */
    ! |) S" g, |! {/ \( ^; g
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));+ z2 p/ h6 w% C8 h2 U
  85.       }
    5 ]6 d  t3 k% k  \$ T- B1 l( s) O. A
  86.     }9 ^' e8 P) O7 m3 J  v
  87.     else /* Rx element 分配了专用 Rx buffer */7 H9 _+ N% x% k0 c" e" p
  88.     {6 t5 j8 C; B! p$ L6 O, p- ?
  89.       /* 检查选择的buffer分配了RAM空间 *// |9 Y! D, g. D* p/ ]" x
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)8 e2 Z3 M* p" L# U
  91.       {* F/ I7 k% V: O' e
  92.         /* 更新错误码 */$ r  z1 N* `9 e1 a
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    # v+ Z1 K  x- W5 t/ j

  94. : z7 M4 D1 S  E: [, t2 o
  95.         return HAL_ERROR;
    / e3 z; G8 `( g& t# r. ?! Z
  96.       }
    7 R/ f" Q3 H0 H# [% x" X5 k$ o
  97.       else
    & U' M. N$ x. w0 ]
  98.       {
    ( \! M! Q+ J" P% }
  99.         /* 计算Rx buffer 地址 */4 k& {, b. n( d2 Q
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));% Q& ^% W: Q3 L" G2 h# k
  101.       }
    # `; j1 g2 X+ J7 H& Y# u* k
  102.     }
    " W- X2 l) O. t' W9 [* l) Z- M

  103. 9 l6 f) m. u, n' e1 ~
  104.     /* 接收IdType */
    ) s: O- v" z  i
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;
    " z8 Z5 d5 U6 J

  106. 1 R* J% `# s0 K0 ^
  107.     /* 接收Identifier */
    % f( S1 U4 T; r1 R+ R
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */- M  ^7 I- M3 T, ^1 d' o
  109.     {  f, @. a# {$ t( D7 W) @
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
    ) q" Z+ `: @; W9 r
  111.     }0 }& ?$ \: u  g0 @& k) p
  112.     else /* Extended ID element */  N1 N7 R+ c: r9 _& b
  113.     {
    . ~6 P; v2 s6 ?) k
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    # d+ t( c6 T8 f
  115.     }
    ) ?' n0 ^7 G* M- U2 B$ ~5 ~; K
  116. , |$ B, |/ s. e+ t* l
  117.     /* 接收RxFrameType */
    ( D" M8 r/ b7 I, e# G
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
    # ~: K  G/ m  {" O: J% m

  119. 0 q9 D  @7 m' N" J4 g
  120.     /* 接收ErrorStateIndicator */* ]  s' L6 o. b. H3 f: ]7 h
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);8 i6 g7 J" |+ F5 i3 D( G: S8 k
  122. 6 m. v7 }/ x" ^( M% @9 g6 Z
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element */
    * X" Q" h2 O3 K1 P/ O! d# z! N
  124.     RxAddress++;7 U- H' L+ x, r
  125. 3 o5 b7 N) c2 }( U: G1 R
  126.     /* 接收RxTimestamp */
    % a0 `, k' Q0 h8 q/ Z$ c
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);
    * q! s, ]# {2 m$ P

  128. 7 r9 \4 f& \0 H. W
  129.     /* 接收DataLength */1 C$ n) |% \( Z4 Q4 e) u4 v+ \
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);  I: c) d* L. F! O, t% E
  131. . w5 G! g/ l% g6 k+ J; @) S
  132.     /* 接收BitRateSwitch */
    " K- X' _6 @; A; V: p
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);
    1 T. n, G0 c+ @0 i3 n$ n$ C3 q
  134. 5 {. m" l& W5 r) P. m- H
  135.     /* 接收FDFormat */! l+ f) G; x( x+ P* U; W
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);
    , p( H8 S* S; w6 k8 s7 c9 n

  137. - e: z& t9 _3 Q" O7 L9 l; f& B: Z2 S
  138.     /* 接收FilterIndex */
    + v6 z4 i( O. T2 L' I9 i3 G
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);: J% ?' ?+ T$ b& m
  140. ; e; H' g2 A" a- o/ G% i6 K
  141.     /* 接收NonMatchingFrame */
    1 X& y. U/ k+ ~4 C# E
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);
      p$ S' M+ z3 ?1 _) |8 x
  143. 7 Q' z. Y* o$ z9 P- g, V
  144.     /* 增加地址,指向Rx FIFO element的payload */
    ) U( _$ k! z" Q$ d/ O
  145.     RxAddress++;9 `* g- i% ^0 `

  146. 9 j  s% |) m9 j6 n$ y% c, c
  147.     /* 接收 Rx payload */1 s. ~& Y# ?2 ?, h7 X
  148.     pData = (uint8_t *)RxAddress;! E! U+ C0 b) p2 [
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)& ~& t3 X) Z. b9 S3 {) u  Z
  150.     {
    * F7 X8 c4 M: b4 p8 G
  151.       pRxData[ByteCounter] = pData[ByteCounter];$ W* G8 C$ E& f- ?
  152.     }, S; e2 T3 V* C' p6 W7 K# d2 P% Y

  153. / Y4 s  C8 n& M; c# b6 r. q
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
    5 A- e- r* g: ^" A# S3 S0 ^1 v
  155.     {. Z3 `6 }/ l$ S0 r
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */3 W/ C2 x2 {1 e* S" D9 m, X
  157.       hfdcan->Instance->RXF0A = GetIndex;
    5 i! U" t- F+ K- H" Q! y8 |
  158.     }# E* }# A2 @; r7 ?$ C
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
    ( p0 h+ O6 j" b" i
  160.     {
    / y( O) k" [. L( v( Y
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */0 k: ~% ?2 `% j4 h4 I1 y) k* B3 }
  162.       hfdcan->Instance->RXF1A = GetIndex;$ ]) q' m9 z  P) ?- E8 f
  163.     }
    ' |: h0 T+ N  w- D+ p& w9 |% m
  164.     else /* Rx element is assigned to a dedicated Rx buffer */
    4 t' L8 T+ G, P9 w* R) w
  165.     {
    * H% v$ z& a3 K3 ]2 _; M! g3 j
  166.       /* 清除当前Rx buffer的新数据标志 */
    0 w# I$ p' Y& z0 Z. g  {
  167.       if (RxLocation < FDCAN_RX_BUFFER32)
    9 E2 A: D: o2 s4 Y8 h) u2 J
  168.       {: J. b3 a/ w7 v8 `
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);' d1 p7 }6 n5 z: C* x
  170.       }
    1 f, q9 [. s2 u% f" ?! t
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */) J, i/ N! W3 {, _' n9 ^9 v
  172.       {0 _  f5 A/ y9 E% W+ ~' \8 B
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
    : c3 F* l9 @6 {% i
  174.       }6 P, i5 o1 d$ X# _9 j
  175.     }& P. Y* V9 k& _# J# H  g
  176.   p) t  Y' ?! [* D5 Q
  177.     /* 返回状态 */% P( x8 ]3 d: f2 |, j, Y- b
  178.     return HAL_OK;9 z6 \) u% b4 n- n
  179.   }% w6 v6 X& D/ z" a
  180.   else6 X& O4 g" ~( R3 y# q+ m& b
  181.   {  T# ]/ B9 q1 b: \0 e
  182.     /* 更新错误码 */
    ( \9 V7 d- {" {0 n9 N- p1 Q. S
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;3 f1 l% T& ?( C) ~' O( m

  184. # o! q- j$ i% m& w: W
  185.     return HAL_ERROR;
    + Y; ]6 m4 f2 k5 B% s
  186.   }
    & I5 T* t7 Q1 h5 S! g& R5 g
  187. }
复制代码
: @/ M5 x4 d0 H
函数描述:. F6 L! {/ m2 a0 ~- K5 j! F* P$ r3 @
. y" e2 u& k5 u
此函数主要用于获取接收到的数据。
$ E/ S) J9 |5 A
" ]* O; \/ P5 ^5 X1 T1 w. O函数参数:
$ L* i! Q3 G3 Q/ e
8 S# G7 y, L5 x$ t  O  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
! j# s  x5 H+ ^- D) m. v5 J, ]  第2个参数是读取位置,支持如下几种参数:& q; p; \" F1 v3 Y& X# I
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */' {& v1 ?# j/ n9 y7 ]& B& j! V
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */; W8 e. Z" m' ~! {( A5 _  m
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */  l' g5 t) I( T) T$ O; w
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */
    . g: ~: B% x# U+ N- J1 Z+ P6 o
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */
    & D+ h; C2 ~# y1 i0 D( I/ G
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  *// s( ~9 ^$ b/ i5 y7 D4 `
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */
    ) [) n) l# c  p; q% X0 _1 D
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
    $ b! A1 b8 V# J) x" Q$ W9 }
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */
    ( @; K0 s1 g' D, w& Z5 \
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */# ~1 t- j, p* l# T. |
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */
    8 c$ v7 n( H* F) o3 ~# s
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */+ Y1 q3 Y- J5 \4 |2 H  u$ j9 ~
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */& o& p: p: S- C+ g
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */+ K( b6 e, @: k
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */
    % r6 V, ~, y; e+ c7 Y: N
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */. H- |; c$ E% O2 ?; y
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */" E4 }. n+ C' S+ R& b4 }7 \' n
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */2 P# \1 a& L; |" x! Q
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */
    ) q6 v: e6 F# \, E/ `  X* Z
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */* K) e8 R* z/ x
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */
    : V3 ~) o; S- U0 a6 c( z) H& u
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */' `' S0 I  `( i! S
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */: O) v8 R: b' q; ]# s! }# P
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
    ! ?+ J" W- ?& }8 i: ]
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */
    0 P& J6 c% l: {* f4 L  T& ]+ m& \
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
    7 X! y3 f; g% v5 D
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */; L# p% j: b; s" s4 g: ?* j
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */
    7 r! y- F5 @" Y" }
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
    ( t$ i. U/ [: s) Q% Y
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */: r) N0 ?+ ?( p
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */' M6 a. v/ A! ^
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */  R- Z5 r; n3 [" Y) N
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
    + [3 e; k- g% O: \
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */  o% |! ~% s# b6 z1 V
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */$ w. {3 D- z+ R1 ?1 e' m
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */$ O! [/ c1 z" i, p( G
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */  i5 E7 d/ M* {! C+ u  A9 F8 |
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
    ( t& c$ V8 \9 Z5 m& F
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
    . w" Z3 a: E' K7 S
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    + R9 `+ S: \6 ]$ |% c
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */. z- L$ {) @6 v9 l; }" U- y
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */3 s( Q4 j7 @  E% q( z" w
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */: X0 a" M, N* a! W! {) ?. A+ m
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */: |/ j1 `  Z- Z7 Q
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */" z, H' K4 x- s+ j
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
    # w' c4 _( M- N6 Z
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */( ~% b2 f6 c' }2 ]3 h
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */9 U9 O. v* J' A! q; x% `
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */2 e( b* N# b/ b
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */
    4 ]9 O1 e% W! O" L1 T
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */0 Z- h% Z; ?+ E+ K$ h: t
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */+ {! a' T" f3 b
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */' C& R' e: x% _0 q: m5 D# ?
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    + W7 z6 b1 |: x. ?# D2 A) ]. ]; f
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
    4 j: k& M9 n: U+ D
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */5 E* E4 |, P8 t3 l* a) X/ r+ k" W. B
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */1 m! B6 H  Y. n- R' ~
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */4 t' C) v& T; }
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */" S% H7 C+ {2 V2 K! ]
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */3 S9 H. h/ N! F% w6 l9 l
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
    9 c" i8 m! X8 Y+ _- H1 ]2 o
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */
    5 K. t* w  }/ f6 _
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
    & `7 _9 r6 V+ O2 V/ q, p
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */) v3 j7 |/ m8 g% X' H6 _! _) v- F
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */$ b; ~  I0 r1 w
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码

" J% w  J* a; i& x  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。
& e7 m7 R  [$ C- t/ X+ f* T& M  第4个参数是数据接收缓冲地址。0 v+ k- [8 ]' I+ A/ {$ g0 Z  W
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 H5 t9 a( {9 W5 N5 C
使用举例:
9 [; t( ^+ l" Y" N8 z
, w2 ?1 L3 }1 g1 s! G% r
  1. /*4 K, H! S! A' }* U  S
  2. *********************************************************************************************************
    % _4 i; ^& E) g
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback
    7 k$ F" ]( r2 b9 c
  4. *        功能说明: CAN中断服务程序-回调函数+ ~5 p7 S/ e" b% N1 m$ v4 S- f
  5. *        形    参: hfdcan
    : f7 g+ M- k. F9 _) q+ q" e7 S
  6. *        返 回 值: 无. h0 z& }! [, r: e
  7. *********************************************************************************************************6 J; }* Z+ ?& H# c) }% Z
  8. */
    : U% B6 c( ?3 u1 a4 n4 J, T
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)! z- u; Z: Q2 x! P+ N$ m* y
  10. {
    ! |& o& C. Q5 m' N3 B: Y7 E; X
  11.         if (hfdcan == &hfdcan1)1 O! D9 J& T, M% Q3 ~
  12.         {
    4 s. \6 g- f+ R: f5 V0 d, ^
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
    8 `2 i0 S  A) ^4 o* W8 k$ H
  14.                 {
    # P$ r7 s' y2 f& z! a% N" s
  15.                         /* 从RX FIFO0读取数据 */% H8 G0 E3 q  j3 d7 E' }
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    / A+ x# ?8 k8 d3 [! s4 i6 f
  17. 1 C, O" S! c7 E% v
  18.                         /* 激活Rx FIFO0 watermark notification */
    : T7 E, G8 N; Q* Y  g& N' r
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);  e- A( M" ~0 c
  20.                         2 \: g+ c. u8 a
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)
    ; J# p3 E' C. U3 r
  22.                         {# C4 K* K1 A9 R' N& A  m
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */& B1 [  l  B8 i' @
  24.                         }
    + J" t; V7 Q! k9 m
  25.                 }
    , w& O9 e- T" h  n2 P. k' e- g
  26.         }
    6 l3 e6 n, W8 N# @
  27. }
复制代码
. V! F0 F5 o' W$ L
91.5 总结
3 V( P: F( |8 V& X2 L' U1 T" q本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。
* z' K& U0 B& f# b  j3 L1 n, d. j( R- C  x" [* B% ]8 Z
- r, |0 {' l; T
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

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