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

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

[复制链接]
STMCU小助手 发布时间:2021-11-6 23:50
91.1 初学者重要提示
2 a' Q9 m6 O! A7 K  FDCAN基础知识点可以看第90章,已经进行了详细说明
6 h" q" D! K5 u# D, t  特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接, v3 z: k+ f* Z8 v8 U
91.2 FDCAN基础知识2 W. _# e0 A7 N+ N+ k8 u) b+ e
FDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。3 ]+ L* k6 e  |# h* v
. z7 p7 u+ @- L& O) o* M
91.2.1 CAN FD协议介绍
; M# Z6 \4 l9 i& y( ~3 q! m! USTM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:( k, a7 l& f( H4 @5 S5 g

. d5 H7 I! K4 f# j7 M(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。9 g; M5 K; \' Y% d
2 l8 B: w& ]$ X% b9 b
(2)可访问的10 KB RAM内存,最多可分配2560个字。
& o3 _# b# h' [4 [8 S/ `& b* F, L: G5 ~$ L3 Q5 i; h: u, f
(3)改进了接收过滤。4 K, c8 S2 g" a9 b1 b" B

0 B* U4 F) s9 k4 Z( g) _+ _(4)两个可配置的接收FIFO。
& i: h3 k! R/ `+ i5 Z  k7 ^
' N& w- a. l. b6 B$ k. y(5)多达64个专用接收缓冲区。
) Y! _! U( l7 e. o; z' q8 c- J) B' _9 g+ Y
(6)接收高优先级消息时的单独信令。
5 u6 e- m5 C" I2 }+ r1 z
9 \" }' ^8 Q3 b: F( I- m(7)多达32个专用发送缓冲区。8 v9 g; Y( a: E$ G  R* Q/ v1 P

6 ?8 v; }% }& k2 b1 E# H6 o* x(8)可配置的发送FIFO和发送队列。! L+ E+ v! m/ c5 h9 B" {& M4 R

  r: I5 a, y1 v" P5 y- q(9)可配置的发送事件FIFO。8 _# Y4 r$ S) O$ h9 Z! q& m

3 K/ x! r  i* N4 K# Z* O(10)时钟校准单元。
1 c5 Q3 e1 c: z( b4 }# q8 _+ L& M* x! r+ u  ?% H
(11)收发器延迟补偿。+ r0 N* L1 c7 j3 y1 X6 D7 C/ R
5 ?" y5 r5 Q% T# l1 A& C
下图说明了FDCAN框图。
$ V8 g" |* c. I% }/ y% O' f
: ?5 [2 O6 B  G) S6 u4 S* k3 v( o7 |
f4f1d5cd872648458911e8be8ddfffe0.png

: d' |& L8 ^0 l! x5 ?* E% K( |+ A# i9 W6 m( N2 X

+ ^9 i4 [4 ~) u; v, _通过这个框图要了解到以下信息:
$ J+ j& J, n% W3 d  `+ Y. t/ e5 z# `
7 P3 G5 z2 t# z( R(1)CANFD1和CANFD2共用一个RAM空间。
. P& }8 L! I. {( G# q, ]* c5 j; q# ^0 E7 f2 I3 _
(2)每个CANFD都有自己的内核。  G+ g" t  N% f
! N$ M9 G- x1 G* F
(3)CAN内核实现协议控制和收发移位寄存器。3 L* u/ j8 G  A! ?# B
# \& u4 K" p0 o2 p+ ?4 y
(4)Tx handler控制消息从CAN消息RAM到CAN内核。
0 e7 E: F. G5 U5 g$ ^4 g7 r, q( n7 m+ |" N
(5)Rx handler控制CAN内核到CAN消息RAM。5 S* W/ S: O0 ~( I4 f7 z
/ V" Z4 ^- I9 A( ^9 h# g0 ~
91.2.2 CAN FD特性
9 ~" ]- _" d  y. b$ N# R(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。
+ g3 U8 B. l+ r( C9 Q1 I( F4 o- `3 a0 @# D. ^( g
(2)提升错误检测,支持高达CRC 21位的校验和。
1 B5 b6 o3 C) A# x: V( i$ m" S& h, j% O! ~& Y( D( _9 X
(3)消息优先级。
/ m$ r8 I5 G+ h# ^. x8 ^+ Z+ c7 f; o% Q6 o5 H
(4)保证延迟时间。
3 C, `: Y$ a' c+ F$ _+ J  X, c0 C0 g) \6 l/ U2 }+ s
(5)配置灵活性。
0 r" b- l* F) I/ @. m$ i& \2 {
9 P& V3 t8 `" W# U" k7 y" ^7 u) s+ N(6)具有时间同步的组播接收。
5 F' N" Z- S3 h: q, v  v8 a4 h+ B! x  s+ [6 j% g: V3 U
(7)系统范围内的数据一致性,每条消息最多64个字节。( l( V, E( B# d* `0 y( z
' f/ D' }# m; F7 A/ k
(8)多主机。0 C' }. R$ k' Q) F$ h. n. F( R
7 S7 s) |, F4 \# y% q2 D
(9)错误检测和信号。
/ Z1 u1 ~2 ^$ X( _$ ~
" d" `9 p2 l1 t( }! M( |* @(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。
. G& }3 }3 t0 e! ^+ i. p
  B, X( K# K2 G, v# U) _91.2.3 CAN FD格式
) c$ E, @$ c8 U# Y# l2 f1 L; O! w$ U9 J. `/ F% F
c692adda5a1149b0a6e3d8a30745fd62.png
- O0 ]9 k, M7 o) U, X% T
& K  o* x; e" J1 t
- K) f1 Y$ V9 A6 y6 l
第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:
  |% A" U: d$ T; V
$ v, C1 b0 `( |(1)帧开始(SOF)。
3 y, E4 g& a+ q+ \
% V) v2 Q, e% I$ o2 G(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。
9 r5 I  u& a% w! }8 S2 I3 @% n  ?2 q
数据传输阶段(The data transmission phase)包括:+ \7 k8 R/ X$ K, ?3 a! [

/ E/ O1 h( U% S2 N1 n# P(1)数据长度代码(DLC),指示消息包含多少数据字节。6 U' I9 i, b$ x5 b
& T0 ]3 R, g1 Z9 t7 D, ^9 s. V
(2)用户希望发送的数据。
% S, A! c9 t# x$ z" Y" B8 d8 ~  K
6 M' D, F* Q5 X7 h& l# c3 V8 M( [(3)检查循环冗余序列(CRC)。. d0 f/ d: X) Q

+ z0 v0 H# U' r" L7 [/ S  O(4)显性位。
3 X1 t$ g" m( O7 Y& C
5 d2 H% t5 o8 X0 Z2 v6 M' j第二个仲裁阶段(The second arbitration phase)包含:) b3 Z. w" R( T, W8 ^
4 l- E# m9 w# O) W; q& D
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息), l" }. X- }( t# y$ b# |) T  Y4 F
' F/ t. S+ m& _
(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。
  E( `$ z! O2 r7 q
  W8 L9 G. p5 H6 V- m3 i5 R* V注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
- n7 _1 O* Y- F9 P$ [; R! t# W8 {: ]6 a, r% }* F
91.2.4 CAN FD相比CAN2.0的提升* j5 K/ X1 c; Q  w: O
CAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:
" I9 q, l3 t5 A/ p9 |  j) d; H* ]" V1 @- U& K- S5 f
(1)17级多项式对最大16字节的有效载荷进行CRC。- d) [4 H5 ^9 L1 X
- g: F  p8 @+ e6 F$ z/ N! E# Y
(2)21级多项式对16到64字节之间的有效载荷进行校验。/ b; Z- r$ B9 m% O3 I. i! C

, J0 N( Z6 z( N/ Q3 L/ L标准帧和CAN FD的区别:
+ b3 l, e# M+ K4 t. c$ P
$ X* P; A$ L% \( }3 b8 c
. N& D; M  O3 }! z
050433e4b8fe4f4d91de7eb85d5e6bdd.png
* l" q. G1 P" a* F) x6 `
0 j, U) `- G) @( X

5 [6 p; ~2 p2 w2 w" b( ]标识符后,CAN 2.0和CAN-FD具有不同的作用:
. t. z) z5 c% ~& a8 d5 ~2 H3 C. k9 _
" _% p' N+ w6 P" m( L) u(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。
/ G+ o1 t5 V8 \9 V8 g! x$ T5 p) e5 @: N9 M$ C
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。- H3 [% m' F" b' f
; c5 {) z( L+ @" \
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。
$ i. l2 }+ C! L# S( b# ], @7 p+ a9 z( c
与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:' k# ~5 x$ a9 l2 z8 e
( F2 `6 p  j, `
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。' G9 O# m" K2 m1 E  v. G
8 E& C/ F! y, `$ n/ a
(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
9 t# i5 `  {- `4 C; P& }- o7 S! u
: W6 R" o* f4 h  W* ^(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。
; @& c& \4 ~; n9 n% x4 I1 x- W& q1 `$ k  R5 d; [2 `
控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。4 [4 T8 F6 ^) q- x+ p, \

1 n+ P7 }5 D- S5 D. X1 w3 l9 j# i5 P" {
# h: J, R# i0 I! z
c4fbc9fa3f184422a77784de5280382d.png

% r/ w8 z# j3 w; u: f% ^2 o9 T/ E2 z9 c" z- G+ I
0 X. z$ [' z6 F9 O$ Y( r* k4 O9 E6 G  k
通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
1 Z* h1 ^) w& x% Q9 h( w$ V! Z4 y7 U( Z! g
(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。
: {+ O/ C+ L  Z/ C5 ^/ @9 B! E- B9 M
# v9 t, _) ?; D! d( m& e. a6 g6 H(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。
+ h$ O3 V' D) Y/ G
. X1 N7 @2 Q* y4 H: \另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
  x; `% ?" {" |& w  q+ _; x- u- L' ~% |6 A

0 k, ?* R# \3 [! V) m7 V
a00dca8056bf40dc860b52366afa5197.png
' v* @3 y$ e8 j# s+ l
2 C! y. o# ?6 F

) T) _# t" O# y" _9 D: [91.3 FDCAN总线的HAL库用法
$ _4 _$ Z, p4 v& W0 X91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef
8 K# X- C5 }/ G! i# S! FFD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
: r+ a. J& z) \+ S8 O3 c+ n9 G9 R0 `3 d
  1. typedef struct
    * R' |/ q, F& O" y0 z* }+ `& T
  2. {) T. e. }' ~; ?! {
  3.   __IO uint32_t CREL;   
    3 [* x8 e: |# J: Z1 R6 w
  4.   __IO uint32_t ENDN;        
    9 I! V# j+ p2 I! T' f: X8 Z
  5.   __IO uint32_t RESERVED1;   
    ; s( q3 M8 Q- N) [8 G
  6.   __IO uint32_t DBTP;        
    ) A, g0 j) e6 F) }" A4 t
  7.   __IO uint32_t TEST;        / |  i* ]+ K6 t0 z
  8.   __IO uint32_t RWD;         . [. R1 [# P# o$ E1 E3 |5 o! r
  9.   __IO uint32_t CCCR;         & c" z' N# N4 f
  10.   __IO uint32_t NBTP;         % l' ~  {" I- P% |7 k4 F3 \
  11.   __IO uint32_t TSCC;           u: Z# G+ h6 D7 C
  12.   __IO uint32_t TSCV;         , `0 c5 q1 O# J6 z: u0 l! Y
  13.   __IO uint32_t TOCC;         
    + v( K& E2 i+ @# u& f) }
  14.   __IO uint32_t TOCV;         
    $ D! ^& u% _! I& z+ T, @
  15.   __IO uint32_t RESERVED2[4];8 R3 Z' _! O. f( x1 A0 C
  16.   __IO uint32_t ECR;         
    8 c4 C' V; N/ K
  17.   __IO uint32_t PSR;         
    8 [: `2 P, n+ G  ?
  18.   __IO uint32_t TDCR;         / O' s* G! {2 I
  19.   __IO uint32_t RESERVED3;   
    - I$ Y, s3 D0 }7 W
  20.   __IO uint32_t IR;           + ^9 Y, |! s6 J) r) w6 M. z
  21.   __IO uint32_t IE;           3 r( N* S! G2 H2 x4 {$ b
  22.   __IO uint32_t ILS;         
    8 ?# g" M) N# ?) z- ]
  23.   __IO uint32_t ILE;         
    - |; S. M  ]( O
  24.   __IO uint32_t RESERVED4[8];
    " W- s/ w1 a% ]) Q* e8 M
  25.   __IO uint32_t GFC;         
    7 [* ~) m0 @6 |, j
  26.   __IO uint32_t SIDFC;       7 }+ N: S; w" ^$ y* I
  27.   __IO uint32_t XIDFC;       $ G9 @! ]8 Q* E) S: `1 `
  28.   __IO uint32_t RESERVED5;   1 Z' F: t# L& v  \/ T' l
  29.   __IO uint32_t XIDAM;      
    + D9 O; ^7 l; z4 `
  30.   __IO uint32_t HPMS;        
    $ Y! Y' C2 T2 O3 ^- ^  G: X8 E
  31.   __IO uint32_t NDAT1;       + L. |" z% g2 I- C3 U4 b
  32.   __IO uint32_t NDAT2;      
    5 ]  p2 a( T7 b( I3 L+ I# ]! Z
  33.   __IO uint32_t RXF0C;        2 W+ v- O8 ^( U6 R0 P2 p6 R# d3 h
  34.   __IO uint32_t RXF0S;       ( F9 E1 J: g8 P
  35.   __IO uint32_t RXF0A;       : \  _6 F' r/ e9 s% x% F
  36.   __IO uint32_t RXBC;      
    - {7 x- e6 y7 c& l" o0 C
  37.   __IO uint32_t RXF1C;       8 v7 r0 s5 |! |, L( x
  38.   __IO uint32_t RXF1S;       % E7 B: }9 m9 a+ S8 U* x2 p
  39.   __IO uint32_t RXF1A;      
    ! @+ D: t# _( Z8 m! r% J8 x6 j6 F
  40.   __IO uint32_t RXESC;        
    : B7 Y  N" z4 H
  41.   __IO uint32_t TXBC;           Q+ R$ X* B/ R& @! l
  42.   __IO uint32_t TXFQS;        / {) N  ^4 C8 }
  43.   __IO uint32_t TXESC;        1 J, b3 z5 o. ?6 }  A/ M
  44.   __IO uint32_t TXBRP;        
    , y& P5 D  H! y& y
  45.   __IO uint32_t TXBAR;      
    7 I3 e! P7 p  Z
  46.   __IO uint32_t TXBCR;        5 s  l/ |& f& G4 V0 r( H
  47.   __IO uint32_t TXBTO;        
    ; D' |, h0 s$ @# n: j0 I$ g
  48.   __IO uint32_t TXBCF;      
    * g3 q! O4 ~' q0 Q$ U6 i+ `5 f1 j/ u: _
  49.   __IO uint32_t TXBTIE;      7 @/ m+ ]  u! L& v+ s4 I8 O! X3 D0 l) A
  50.   __IO uint32_t TXBCIE;       . u: L/ x4 G! F# K0 V9 l- [( g: M, b
  51.   __IO uint32_t RESERVED6[2]; " b1 x! B1 Z8 M7 x
  52.   __IO uint32_t TXEFC;        
      {; |3 z: Y1 _* M" P" g7 ]& b
  53.   __IO uint32_t TXEFS;        & S& b8 k: h1 ^0 d5 y. M, p
  54.   __IO uint32_t TXEFA;        
    " M: q9 g+ P5 Y4 T
  55.   __IO uint32_t RESERVED7;   
    $ \4 w6 z+ d  x2 p8 B3 ?
  56. } FDCAN_GlobalTypeDef;
复制代码

: N1 h' p$ m9 T" F' U这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。7 n1 Z; K# v' t+ T2 P% h
6 f8 }3 {) q' @3 C9 t+ e
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
* O8 m/ T7 y2 W% C, @" p. G$ I- B' r8 G' k
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    8 {4 m' i% s3 @
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

' s/ ?* W; u" k2 E3 s下面我们看下FDCAN的定义,在stm32h743xx.h文件。
5 }% }' f- y0 V: \4 W% O6 k+ {
  1. #define PERIPH_BASE           (0x40000000UL) 4 s" w3 c1 i* J- a6 m7 Y- T; S+ j
  2. #define D2_APB1PERIPH_BASE     PERIPH_BASE) q. I8 k. O5 ^& S$ B
  3. 8 U9 A  ^! H' y( n
  4. #define FDCAN1_BASE           (D2_APB1PERIPH_BASE + 0xA000UL)
    / e9 b, j# Q! b, Z
  5. #define FDCAN2_BASE           (D2_APB1PERIPH_BASE + 0xA400UL)" s4 ^. b4 x3 a" ^0 s7 a2 i2 Z
  6. #define FDCAN_CCU_BASE        (D2_APB1PERIPH_BASE + 0xA800UL), c6 s% z) m" }4 l
  7. ' l* |; _, m( L4 X- s1 y
  8. #define FDCAN1       ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A000
    * A3 V  D) B9 @
  9. #define FDCAN2       ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
    8 n7 P# A* d$ R; }1 N' W, c
  10. #define FDCAN_CCU    ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码

+ Z9 A/ i2 G: C* y1 s( T3 P  b我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。& k& d: c! D8 S1 X

0 z6 e5 \5 y" _1 }8 n# d2 |5 _91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef
5 g! ]  i4 `, v, b, [- X4 ^0 F/ i. wFDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
6 A  A5 {) n0 W) F
( l& M& l5 W( G9 s) S# Q' L
  1. typedef struct
    . w" q2 H6 _; r) E0 Q
  2. {
    9 D% [, t+ D( |/ V2 r& ^
  3.   __IO uint32_t TTTMC;          /*!< TT Trigger Memory Configuration register,    Address offset: 0x100 */4 h* f% s7 k. }# E& d$ ~
  4.   __IO uint32_t TTRMC;          /*!< TT Reference Message Configuration register, Address offset: 0x104 */3 |2 r! ~4 E& j8 u, G$ ~9 F
  5.   __IO uint32_t TTOCF;          /*!< TT Operation Configuration register,         Address offset: 0x108 */
    $ W; Q7 }3 G8 S$ R/ H. s3 f
  6.   __IO uint32_t TTMLM;          /*!< TT Matrix Limits register,                   Address offset: 0x10C */6 W2 n# L- X" P( T  Y( M
  7.   __IO uint32_t TURCF;          /*!< TUR Configuration register,                  Address offset: 0x110 */0 B7 i7 |. k" x3 |. I. O
  8.   __IO uint32_t TTOCN;          /*!< TT Operation Control register,               Address offset: 0x114 */
    . t# X# Y7 E5 Q
  9.   __IO uint32_t TTGTP;          /*!< TT Global Time Preset register,              Address offset: 0x118 */
    4 H6 T8 M" u( X' ?( G& P2 z
  10.   __IO uint32_t TTTMK;          /*!< TT Time Mark register,                       Address offset: 0x11C */& o# W/ H) ~: x' @3 W3 H
  11.   __IO uint32_t TTIR;           /*!< TT Interrupt register,                       Address offset: 0x120 */- P2 v6 R6 e% x# ?. ?6 w
  12.   __IO uint32_t TTIE;           /*!< TT Interrupt Enable register,                Address offset: 0x124 */
      `8 l" w- p3 l4 [7 j6 I* G3 Y
  13.   __IO uint32_t TTILS;          /*!< TT Interrupt Line Select register,           Address offset: 0x128 */
    . P: y- u& A" W' q% z& [
  14.   __IO uint32_t TTOST;          /*!< TT Operation Status register,                Address offset: 0x12C */
    * \; |  [2 ~( p: Z$ h# C
  15.   __IO uint32_t TURNA;          /*!< TT TUR Numerator Actual register,            Address offset: 0x130 */
    6 o  \9 V. [# @& a% D* o
  16.   __IO uint32_t TTLGT;          /*!< TT Local and Global Time register,           Address offset: 0x134 */; y* p, a( ^3 ?  ?
  17.   __IO uint32_t TTCTC;          /*!< TT Cycle Time and Count register,            Address offset: 0x138 */
    1 W0 ?# x: U' y4 m7 o
  18.   __IO uint32_t TTCPT;          /*!< TT Capture Time register,                    Address offset: 0x13C */
    ) z, @% q8 s: |* h) S$ Y
  19.   __IO uint32_t TTCSM;          /*!< TT Cycle Sync Mark register,                 Address offset: 0x140 */; U( s# X; |5 k7 |8 h$ A$ o( K% @: p
  20.   __IO uint32_t RESERVED1[111]; /*!< Reserved,                                            0x144 - 0x2FC */
    ) V" c! A+ [* b1 o9 w
  21.   __IO uint32_t TTTS;           /*!< TT Trigger Select register,                  Address offset: 0x300 */$ V& W" Y7 f3 j- B4 X
  22. } TTCAN_TypeDef;
复制代码
, r, L* g& y. H$ s5 v2 T3 o) _: Q
91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef
: ~. B6 h" J, v5 l下面是FDCAN总线的初始化结构体:
% L: Q9 Q6 U# t0 d9 T6 @) t6 |! A# g! m& P7 l8 Q! _( k
  1. typedef struct- S  \2 ]2 @5 p! `/ w% ~
  2. {$ l0 n. y- z9 H
  3.   uint32_t FrameFormat;                  /*!< Specifies the FDCAN frame format.' ~. Z2 b* e; V; Z9 k) a
  4.                                               This parameter can be a value of @ref FDCAN_frame_format     *// a; N3 j& V4 t; F8 d4 n2 z+ V
  5. 9 L0 Y/ g6 D0 O
  6.   uint32_t Mode;                         /*!< Specifies the FDCAN mode.
    ) m7 w6 ~: U! w: _% h. R
  7.                                               This parameter can be a value of @ref FDCAN_operating_mode   */
    6 ?0 [) r" _2 P' ^8 Y

  8. 5 s. z$ \2 [1 s1 P' A
  9.   FunctionalState AutoRetransmission;    /*!< Enable or disable the automatic retransmission mode.. _  [  B6 ~5 t0 K  Q
  10.                                               This parameter can be set to ENABLE or DISABLE               */7 Q1 {3 C9 D  [% M5 N

  11. & z$ @, O: j- M
  12.   FunctionalState TransmitPause;         /*!< Enable or disable the Transmit Pause feature.# K) e1 l2 Y" t( g# ]
  13.                                               This parameter can be set to ENABLE or DISABLE               */$ ]3 E+ M' \: e- J
  14. 3 S9 [5 K  U3 S
  15.   FunctionalState ProtocolException;      /*!< Enable or disable the Protocol Exception Handling.
    0 e; U8 ]- A# H7 V. R1 G" w
  16.                                               This parameter can be set to ENABLE or DISABLE               */; ?: v3 }6 u/ s9 ]4 O
  17. : w8 G/ o/ K" |# @& L4 e
  18.   uint32_t NominalPrescaler;             /*!< Specifies the value by which the oscillator frequency is. o3 I) p1 X: H. e. c; Y
  19.                                               divided for generating the nominal bit time quanta.) q+ u4 T* y2 ?: k- A: D) \
  20.                                               This parameter must be a number between 1 and 512            */
    $ L: b# d; `6 O* M
  21. , n  E5 C% f, T( A) s6 F" m
  22.   uint32_t NominalSyncJumpWidth;         /*!< Specifies the maximum number of time quanta the FDCAN
    - w+ k- l) O3 [5 v' V/ G, Y
  23.                                               hardware is allowed to lengthen or shorten a bit to perform
    . q8 F7 J; ^4 w  C& Q
  24.                                               resynchronization.% m" [* ]" j1 ?
  25.                                               This parameter must be a number between 1 and 128            */) q0 x9 x% E1 j5 Y

  26. 4 F) D, o) I# R% E+ [2 P
  27.   uint32_t NominalTimeSeg1;              /*!< Specifies the number of time quanta in Bit Segment 1.
    ) E" `2 ~: k+ I. g5 L" q
  28.                                               This parameter must be a number between 2 and 256            */8 `7 q6 p8 }+ s( v2 @9 F; O7 R
  29. $ \9 {2 Y* K4 l2 y. h: P$ o7 l7 T
  30.   uint32_t NominalTimeSeg2;              /*!< Specifies the number of time quanta in Bit Segment 2., r/ B5 w# z  C: y6 {' T) A
  31.                                               This parameter must be a number between 2 and 128            */0 I1 ^* x/ a! C& n! Y- J4 }, c& |
  32. & t5 Q& P' h3 H6 \: K' m' ?/ i
  33.   uint32_t DataPrescaler;                /*!< Specifies the value by which the oscillator frequency is
    + a: u" X5 T0 }: r7 M! T3 C# T8 w+ V6 k
  34.                                               divided for generating the data bit time quanta.5 K( a7 l' G: q& L
  35.                                               This parameter must be a number between 1 and 32             */; o4 S. G/ u) a2 D2 x2 P" v
  36. 0 z4 i8 o/ h7 }7 n
  37.   uint32_t DataSyncJumpWidth;            /*!< Specifies the maximum number of time quanta the FDCAN
    4 d# H) N" P  C  w5 I2 ]% m% Q- N( N
  38.                                               hardware is allowed to lengthen or shorten a data bit to
    ( y& I1 `3 Y% _
  39.                                               perform resynchronization.: W% a4 ~% c  C# W
  40.                                               This parameter must be a number between 1 and 16             */
      Z6 a3 O& |! R# `" B
  41. $ `+ u1 c& I$ |
  42.   uint32_t DataTimeSeg1;                 /*!< Specifies the number of time quanta in Data Bit Segment 1.
    4 w  _0 h( X1 O5 |& ^$ S4 o
  43.                                               This parameter must be a number between 1 and 32             */! M) b, j) }& h+ d2 B" E

  44.   j' h: x7 o- X9 s  |& {
  45.   uint32_t DataTimeSeg2;                 /*!< Specifies the number of time quanta in Data Bit Segment 2.
    ' l, a: v' t, b7 R+ z6 W( X
  46.                                               This parameter must be a number between 1 and 16             */
    & l% h5 h7 g7 |% h  m; Q

  47. ' j. n( |* L* x4 l' \0 o
  48.   uint32_t MessageRAMOffset;             /*!< Specifies the message RAM start address.
    % q/ R& v9 T1 H# W
  49.                                               This parameter must be a number between 0 and 2560           */
    ! s2 Q6 V( J# e7 ?2 h* s+ ^$ V

  50. 0 E) q8 T, [* t7 A' c+ b; h
  51.   uint32_t StdFiltersNbr;                /*!< Specifies the number of standard Message ID filters.3 v2 p! _8 G& V% t% x- W
  52.                                               This parameter must be a number between 0 and 128            */3 X# O. H+ w& Z/ p% Q7 ~
  53. - {* n$ Q) h4 k' o2 U( K: n
  54.   uint32_t ExtFiltersNbr;                /*!< Specifies the number of extended Message ID filters.4 W  _; y  O2 J9 g6 y  D9 [
  55.                                               This parameter must be a number between 0 and 64             */* O. H4 M9 o6 J0 s

  56. 1 {; K0 Y1 V- h( R: g6 z  i+ @
  57.   uint32_t RxFifo0ElmtsNbr;              /*!< Specifies the number of Rx FIFO0 Elements.
    6 C3 ^( {3 j  I" c
  58.                                               This parameter must be a number between 0 and 64             */
    ( f$ l% a; }% v7 P. A
  59. 7 H1 [8 G1 x5 _+ Y& n
  60.   uint32_t RxFifo0ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
      `$ H" n8 b* S/ b2 ?
  61.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    * O' v% m8 w: n0 H- K6 P
  62. + ^% K6 f7 d7 n& O3 F6 R3 C/ l
  63.   uint32_t RxFifo1ElmtsNbr;              /*!< Specifies the number of Rx FIFO 1 Elements.) J  e8 E+ ^) h; [" N6 q% M/ G
  64.                                               This parameter must be a number between 0 and 64             */& [# S9 N) @1 A8 K

  65. 0 k# s! [+ @: l% V, |
  66.   uint32_t RxFifo1ElmtSize;              /*!< Specifies the Data Field Size in an Rx FIFO 1 element.
    % V3 ?1 C9 J; N8 z% I! F  q8 S8 l
  67.                                               This parameter can be a value of @ref FDCAN_data_field_size  */! p7 A5 b: R- t$ X5 j% V2 [- k

  68. 7 G" J* [( c$ ?3 q$ D: S
  69.   uint32_t RxBuffersNbr;                 /*!< Specifies the number of Dedicated Rx Buffer elements.
    ) M; R# i  r- `& N) ~' G) e& |
  70.                                               This parameter must be a number between 0 and 64             */1 ~. T! [. }0 R

  71. ! c/ a! S3 u  Z- C
  72.   uint32_t RxBufferSize;                 /*!< Specifies the Data Field Size in an Rx Buffer element.
    / q1 s; V4 A) M' C; |; P1 o
  73.                                               This parameter can be a value of @ref FDCAN_data_field_size  */
    7 W' K6 X1 d& ~" }5 U7 j' n0 d

  74. $ Z. w9 G& @, X/ [) I9 Q) W1 d+ n6 F! @
  75.   uint32_t TxEventsNbr;                  /*!< Specifies the number of Tx Event FIFO elements.2 ]. J  p/ D0 S" b! T
  76.                                               This parameter must be a number between 0 and 32             */
    ) {; A$ d1 n# ^, u" l' V7 H

  77. " f+ K, Q9 K: g( }8 i- b
  78.   uint32_t TxBuffersNbr;                 /*!< Specifies the number of Dedicated Tx Buffers.  p1 i+ X1 x6 B* u  J: Z
  79.                                               This parameter must be a number between 0 and 32             */  @8 W; h" c0 O4 ]' L1 U

  80. # z* d' e! N: s5 x8 i, R7 Q9 i
  81.   uint32_t TxFifoQueueElmtsNbr;          /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.& T5 n0 i/ B  v8 d  N
  82.                                               This parameter must be a number between 0 and 32             */3 X; _$ I& ~( T  O0 n0 j
  83. % t2 }7 D7 k9 Z6 N8 Q. e2 R
  84.   uint32_t TxFifoQueueMode;              /*!< Tx FIFO/Queue Mode selection.
    % }. B; ^9 ?. M3 K
  85.                                               This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
    : r* L9 ~- l4 A" z) ]) n

  86. 3 H  w6 u# q  {/ a
  87.   uint32_t TxElmtSize;                   /*!< Specifies the Data Field Size in a Tx Element.
    & E0 u( ]  o5 L8 m; h* b
  88.                                               This parameter can be a value of @ref FDCAN_data_field_size  */& a; S  ^6 V7 l7 F1 t* A
  89. " C8 [5 s5 }5 ~& P7 e" D
  90. } FDCAN_InitTypeDef;
复制代码
) z. x) j& i  n2 c3 X# B
下面将结构体成员逐一做个说明:
+ y7 v- g4 d9 P" {
8 w, x" Y- l- k) q' @3 X  FrameFormat. n2 J* C2 E& W$ E6 u, r
用于设置CAN帧格式。% a( @  T% C# K. {

1 f) ]% c. D0 b2 _; ^) ]
  1. #define FDCAN_FRAME_CLASSIC   ((uint32_t)0x00000000U)       /* 经典CAN模式 */
    + q8 i( }+ p. U, F+ r& I
  2. #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE)   /* FD CAN不带可变波特率 */6 G: u" c8 ^1 b2 H; x
  3. #define FDCAN_FRAME_FD_BRS    ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码

2 U; R; X# c) N1 h; C: ]9 D2 z  Mode# ^( C; ]$ g: L1 q' t
用于设置CAN操作模式。
; H  G- \% y3 a7 K& E: j  J# p7 j
0 U& _  Q- a% j1 X
  1. #define FDCAN_MODE_NORMAL               ((uint32_t)0x00000000U) /*!< 正常模式                 */& `* T. R$ ]* B6 ?7 k( H6 r
  2. #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式          */
    " J$ n- c3 o$ W( w( `/ ]
  3. #define FDCAN_MODE_BUS_MONITORING       ((uint32_t)0x00000002U) /*!< 总线监测模式              */
    , C- K& H( T1 D! |4 Q- a4 L) g
  4. #define FDCAN_MODE_INTERNAL_LOOPBACK    ((uint32_t)0x00000003U) /*!< 内部环回模式              *// y, w6 g) |2 H# {9 S
  5. #define FDCAN_MODE_EXTERNAL_LOOPBACK    ((uint32_t)0x00000004U) /*!< 外部环回模式             */
复制代码
1 ]* a* i$ D# d5 r/ O: ]5 C
  AutoRetransmission
: X2 |3 d* Q0 _& i' J使能自动重传模式。7 w( }4 `1 B9 a* `7 P7 L% m0 g2 Y
7 C8 _+ S1 f+ Q; A! p
使能ENABLE或者禁止DISABLE。
2 P& x. G  P7 [7 K# u# @! _* x% T+ d: n: e3 _3 Z9 x2 j
  TransmitPause
! f6 B/ f' \& ?  [8 ^; q使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。
& F  |8 U" z4 ^7 v% d# F& q" o7 c
9 k9 P* F4 a6 e2 i% M' E, q. Y$ I  ProtocolException" }% l9 {  ^6 [& Q$ \% T# n- A3 }
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。4 d" @% o; r3 |" G8 M
( J. D& |8 @3 B. l* p; q9 S* P
  NominalPrescaler
/ g" y, B7 i+ i% o/ W用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。
% D4 n- e1 o7 m% _) Z( [' w! E- g1 }6 ]/ l
  NominalSyncJumpWidth" ^" R8 F3 ?, }8 h& ^; E
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。
* {1 K! y9 J- F7 \6 ?: w' S! u. r3 A% T% w5 m) [/ W1 L
  NominalTimeSeg1
/ w4 |3 Q# k) N% r设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。
6 P; M8 W& @5 h0 i+ ?! H# ?7 I2 E% M6 ]- ]2 h" M  n* ]
  NominalTimeSeg2# r0 a9 [1 y" X! g& ^+ O4 t
设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。2 v& Z9 Q4 d2 ~. w; M( ]
* ~4 d* \1 h8 m+ \# _; Z  T
  DataPrescaler5 S) ]6 \9 v' P8 M: e0 R
用于CAN FD数据阶段分频设置,范围1-32。0 h& B' |' ~7 D8 N1 S7 U" N

( L# Z5 e/ }$ p; k: P5 H2 |. p  DataSyncJumpWidth
) {+ ^9 V* C- Q) |- y8 O/ L. ]设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。
/ K1 R# W0 Z0 b; b' x; M( w3 ^
1 B8 z  K" V$ l; \  DataTimeSeg1% U, {9 s) G0 |0 G) }3 f; [/ G+ l
设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。: E1 u3 _8 m4 Y
* P4 ]+ Z. x' j  b
  DataTimeSeg2
0 ~3 ?* {) @0 d) W设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。
: r0 j$ c; O8 T: N7 J' b4 u2 R* g/ d+ |4 R# z
  MessageRAMOffset$ f, w& y/ U$ D$ r2 D4 ^5 d
设置消息RAM起始地址,范围0到2560。0 g5 X9 B: d- h- [

/ }+ s/ q( l2 j  StdFiltersNbr
) ?  Y' y5 j3 M2 D/ U9 p标准ID过滤个数,范围0到128。( ]. j2 S/ L5 C$ i, \

; n' a7 y1 a! O  A: h( R" Q! H  ExtFiltersNbr
8 G, T6 `) D: b- g* T5 I扩展ID过滤个数,范围0到64。* p& t9 o+ @9 I
- N; m  ~2 f* }5 a0 W
  RxFifo0ElmtsNbr$ K+ }$ u' }3 j' p" l$ k
RX FIFO0元素个数,范围0到64。
4 ^/ F9 b0 v1 S  }% |  G  b1 P. O# i2 A. A. X' {' D0 ], o1 [
  RxFifo0ElmtSize3 X& T- n0 \7 ?, O  B$ r
RX FIFO0每个元素中数据大小,支持参数如下:
  O2 M% U7 C* @& E2 i8 L
; p7 o% n7 J3 T* W: r9 n. H
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */5 v; h, D9 i% m0 S" H' j2 H
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */4 x, \! ?" x( K( Q. ]" R
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
    ( @+ g" p' ]! K
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */' y- E/ Y* ~. L. J/ k
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    4 w; t2 l5 y# i' N( v5 W4 g3 y
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */$ O8 [$ q- F1 @2 ~! g
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */- {" k# ?/ g* u! [9 B! `: n) T
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

5 H& k- p2 W) c$ @& `1 Z8 ^  RxFifo1ElmtsNbr; }2 C) f% H# `) p7 ~& l' e2 n- }& v
RX FIFO1个数,范围0到64。/ v- ~0 U8 D7 k) c6 T

) _' C! g5 b, P1 |. P  RxFifo1ElmtSize3 b! B( p8 d( l- k* a9 m
RX FIFO1每个元素中数据大小,支持参数如下:
; d/ P% I5 ?1 ~1 N4 y" L
/ l: J4 M# u* B& L
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    0 U0 z6 `: o( O2 O) U
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
    4 }7 D2 L' C7 w  M
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */( }7 h" C. Z& q* D5 X, j8 B, v) D
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */1 ?0 w! \3 U6 h. Q
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */9 L. i: r7 S9 x5 R
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */: P) r/ N2 F$ C7 g7 k
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
    1 G4 ?$ X  |/ H4 ~* O5 ~# E/ \8 H
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

( w% N8 I2 k4 M: O  RxBuffersNbr
/ |6 ]: |6 g$ l( l* ]设置Rx Buffer元素个数,范围0 - 64:
4 p7 q( f/ y# D) B
) U% J% q; I) T8 \4 z$ F  RxBuffersSize* O/ K# E) O/ H9 f8 \$ ~0 `# m: F7 N  u
设置Rx Buffer元素中每个数据大小,范围0 - 64:
( r. |. `9 M6 `: M: S$ C9 j$ K1 f! L$ B* m
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    * R- C# p1 E1 S) A
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */7 j6 H, P* O1 u/ I4 T8 _* p
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field *// g5 k6 R  _- |
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    2 W% O3 z+ P0 X; a# n
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
    & z$ H0 F. Z! K! T
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */2 |: W/ l5 Y7 K' z1 ?: b. j
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */8 ~! B9 P/ _9 P; O3 X, j* J
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
* ?* y% f* y8 v7 W4 |2 F+ R5 o
  TxEventsNbr  W! [" b+ r! R7 y& X' Z9 [
Tx Event FIFO元素个数,范围0到32。
7 G8 B, Q1 k7 I9 R) e. D$ J& X2 L, W% S& }3 g( M  J0 n
  TxBuffersNbr5 N7 z5 r8 Z! E* x6 Q3 _. _* T
设置专用的Tx Buffer元素个数,范围0到32。
) r! ~' S& o" u
6 |4 q; }6 v( X6 N! Q% b1 P/ X3 K  TxFifoQueueElmtsNbr) u5 u+ C5 T- {9 q% x% L+ n
设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。, n6 l1 H* O. y+ O% T
7 p4 X1 Z2 W5 C2 e) w& @
  TxFifoQueueMode' E( k1 o$ ]2 K8 @9 l
设置FIFO模式或者QUEUE队列模式。; @, @% H) v( g1 c+ c
  b6 ]' L* F9 o' G" ?! K
  1. #define FDCAN_TX_FIFO_OPERATION  ((uint32_t)0x00000000U)     /*!< FIFO mode  */6 B/ ^) T* L) z# D9 Z4 h) A3 |' L
  2. #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
1 V( E5 O# `8 ~
  TxElmtSize; m0 x4 _1 j+ C) u; W/ N; P
设置Tx Element中的数据域大小。支持参数如下:3 }4 K; ]8 Y* W6 i8 W3 N. U& O# n
! h- n5 R2 U. q5 `# E& M
  1. #define FDCAN_DATA_BYTES_8  ((uint32_t)0x00000004U) /*!< 8 bytes data field  */
    9 P& w4 k, E& C5 V
  2. #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */  v6 O5 |! g4 q" P$ |
  3. #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */- t- l# m) F9 o8 ]  ~* A+ O+ S
  4. #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
    & R' w5 Q' r  l% o, x; {* n
  5. #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */( ^0 p. H( X. m& R" B
  6. #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */0 Y7 t& ^9 u8 B
  7. #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */3 H: }' z5 N) Z) E: \: |6 c& e
  8. #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码

$ b& S+ |; i) D8 M( h; U) L91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef: G' a8 L: X# L: O( J
下面是消息RAM结构体:% [+ \' V" e* W1 j

  1. . u/ X& B. \, j* i/ R
  2. typedef struct
    ( Y, s. H( \: M2 I
  3. {
    2 `! h; `3 d' V/ I; a; B4 O
  4.   uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.; `! C6 I+ @8 H$ r& x
  5.                                   This parameter must be a 32-bit word address      */. B9 J' ?2 o" g1 r+ {: F
  6. ) p: }5 V* u% v& P  q+ d
  7.   uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.
    ) W. h) A% j9 o1 {. A
  8.                                   This parameter must be a 32-bit word address      */) Q( l$ R4 m1 [$ l1 O
  9. . ], Q( c1 D% ^) P
  10.   uint32_t RxFIFO0SA;        /*!< Specifies the Rx FIFO 0 Start Address.
    & c. D6 D' H8 |8 a7 y
  11.                                   This parameter must be a 32-bit word address      */
    9 m$ L3 ]  z0 x& D# t, k
  12. 7 ], c% x( Q. o; i
  13.   uint32_t RxFIFO1SA;        /*!< Specifies the Rx FIFO 1 Start Address.
      S% F3 ]3 j: C% n+ Z7 |2 w( @( v7 u
  14.                                   This parameter must be a 32-bit word address      */* X, E. j( o- Q; I
  15. ) F* a9 n1 P5 z  Y( W
  16.   uint32_t RxBufferSA;       /*!< Specifies the Rx Buffer Start Address." f2 d0 \1 f* t
  17.                                   This parameter must be a 32-bit word address      */0 D' T7 [* P1 J  }) g6 Y3 m) {  V

  18. 1 w5 A7 q; W$ N" i1 D; e# @
  19.   uint32_t TxEventFIFOSA;    /*!< Specifies the Tx Event FIFO Start Address.( h% o9 H# v. l0 R! q3 D; c
  20.                                   This parameter must be a 32-bit word address      */6 G1 q$ X$ H9 y1 u. w

  21. 2 \) L* ]' f0 I3 G+ e
  22.   uint32_t TxBufferSA;       /*!< Specifies the Tx Buffers Start Address.7 }7 K, r- d% c/ P& m. A* r
  23.                                   This parameter must be a 32-bit word address      */' E4 G' c9 q& b) x" f
  24. 6 {6 F' }, i8 y/ k0 R
  25.   uint32_t TxFIFOQSA;        /*!< Specifies the Tx FIFO/Queue Start Address.
    % r& e2 E8 {# A- Q
  26.                                   This parameter must be a 32-bit word address      */
    5 o. [" B) O1 V  E- i7 w2 H

  27. % l5 [2 \7 t, s
  28.   uint32_t TTMemorySA;       /*!< Specifies the Trigger Memory Start Address.
    % b" Y  f- E7 l0 i8 a( L+ W
  29.                                   This parameter must be a 32-bit word address      */+ Y5 P$ Q( i4 c; D2 G- i6 W
  30. 8 z# v& `! |* ?' l- ~9 G
  31.   uint32_t EndAddress;       /*!< Specifies the End Address of the allocated RAM.
    ' O& W/ P$ S+ K2 X/ \. C
  32.                                   This parameter must be a 32-bit word address      */
    # I9 ~0 U9 h9 ?- W4 c' Y, D8 L
  33.   m' H/ @+ S" P- e
  34. } FDCAN_MsgRamAddressTypeDef;
复制代码
) W  b3 x% L5 R! F' R5 S: l, O) b
下面将结构体成员逐一做个说明:/ G+ Q0 s1 {5 Q8 R" w0 {( p
& j; `% j  N+ m( N
  StandardFilterSA
" u+ c' J0 T) ^! I$ S: Q设置标准过滤器起始地址,必须是32bit地址。9 o( c/ ~- x1 r7 ]
2 Y1 s- c7 Q2 r% H1 J, S* J2 ^
  ExtendedFilterSA. |4 C/ W$ ~3 k: q" f
设置扩展过滤器起始地址,必须是32bit地址。
# N. \- o% @: P& p! |+ D
* c5 _6 U" E- L5 Q5 P1 N! U  C( s  RxFIFO0SA
+ Y% f' y% F* `" c, {  f设置RX FIFO 0起始地址,必须是32bit地址。
2 i9 ?2 A( k5 a( B# S; U0 d, D9 |+ j' K- O. i
  RxFIFO1SA
) w4 n& ^6 b  `( K8 w! [+ M设置RX FIFO 1起始地址,必须是32bit地址。
4 _5 @) ^/ u5 t6 Q- a' T* l( z
9 h) @: @3 u5 w* \& O% Z  RxBufferSA; a( I4 a" R* m' H& j$ ^5 v5 O
设置RX Buffer起始地址,必须是32bit地址。
% k4 K  e! x) t6 ^6 U" f
3 [  [3 _) N3 u* [2 p) U  TxEventFIFOSA5 ]3 h7 h& O8 T, c
设置Tx Event FIFO起始地址,必须是32bit地址。9 G. ~  J+ D$ e8 u3 a. A2 @
% f' V! b1 R. S" y5 ^
  TTMemorySA
2 l* M) n, S% M设置触发内存起始地址,必须是32bit地址。
2 N( ]1 c8 m' U& z4 D1 E" A, P$ o. A9 |
  EndAddress
9 j' J" Q/ z: L6 {( a$ N设置申请RAM空间的结束地址,必须是32bit地址。
; g6 p  |+ I. L9 N
  t$ j) H" \. N+ s6 o$ b91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef( A/ x/ S' ^4 B7 @2 q  U+ c) K
下面是过滤结构体:. `9 Y# d& J; O# Z2 u9 p
# W; V. S) G3 Q! U$ B0 j+ {, W
  1. typedef struct
    8 [$ [+ @6 C! \8 y( G
  2. {
    2 v) K( F3 d+ Y
  3.   uint32_t IdType;           /*!< Specifies the identifier type.8 Y/ d1 N: f- V. {. y1 q
  4.                                   This parameter can be a value of @ref FDCAN_id_type       */4 a* F& \# K0 w
  5. 9 M& H& L9 ~8 v$ M6 ~
  6.   uint32_t FilterIndex;      /*!< Specifies the filter which will be initialized.2 D9 e* w. f3 }, V
  7.                                   This parameter must be a number between:# u* K( r, S* I9 X! ~
  8.                                    - 0 and 127, if IdType is FDCAN_STANDARD_ID2 e& m9 u: x( F
  9.                                    - 0 and 63, if IdType is FDCAN_EXTENDED_ID               */4 u3 q+ r6 S5 x' {% Q, O  P
  10. , O: @0 U% Q% Q7 Z5 V0 P+ G
  11.   uint32_t FilterType;       /*!< Specifies the filter type.
    8 I  b) d3 ?5 i2 k. ~
  12.                                   This parameter can be a value of @ref FDCAN_filter_type.5 `# A$ ~* u) O( l& V
  13.                                   The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted, y: I0 r5 d7 B: `9 h9 v
  14.                                   only when IdType is FDCAN_EXTENDED_ID.
    " c9 Z3 J6 {5 X4 S( ?0 l5 q
  15.                                   This parameter is ignored if FilterConfig is set to
    $ [  N) \7 V9 t7 F
  16.                                   FDCAN_FILTER_TO_RXBUFFER                                  */7 [% m, [( y% N' A1 O

  17. # M1 a2 L: r, q0 \
  18.   uint32_t FilterConfig;     /*!< Specifies the filter configuration.
    3 i% j8 t9 K1 x6 `0 T
  19.                                   This parameter can be a value of @ref FDCAN_filter_config */
    " z& y( i% b: t$ L7 E4 F. I+ ]; }" L" v

  20. : h& t8 D: q$ {2 i1 k8 Q2 o" r, e
  21.   uint32_t FilterID1;        /*!< Specifies the filter identification 1.
    8 \  }4 K3 Z1 {% H
  22.                                   This parameter must be a number between:8 l: Q' p$ g% D: f& `, Q( o
  23.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    2 x. c8 C6 T& X& F# ^8 X
  24.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */% |+ s0 k7 I4 f# u2 s

  25. 7 c# _% w4 S! b2 _, s5 a
  26.   uint32_t FilterID2;        /*!< Specifies the filter identification 2., E, r0 V4 T9 @" o# a1 @
  27.                                   This parameter is ignored if FilterConfig is set to
    0 y* E: _3 `! t! }' [
  28.                                   FDCAN_FILTER_TO_RXBUFFER.
    % ^$ z" Y: F! I( J, i# L- h
  29.                                   This parameter must be a number between:& S. J5 y& a8 C; X8 Q# d5 G( r
  30.                                    - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID! }1 g  }! a6 ^
  31.                                    - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID       */
    4 G7 |- d/ f/ h: o. v7 K

  32. ; s2 I' |4 u: E; A# i2 c3 e
  33.   uint32_t RxBufferIndex;    /*!< Contains the index of the Rx buffer in which the
      U: D. s8 S2 \  u! y+ r
  34.                                   matching message will be stored.2 ]& S- I& J3 ~9 t! v6 C) \
  35.                                   This parameter must be a number between 0 and 63.
    5 a) y, d: f  S9 j7 m
  36.                                   This parameter is ignored if FilterConfig is different: F# l' U6 Q; q' a; Q
  37.                                   from FDCAN_FILTER_TO_RXBUFFER                             */
    # K$ Z8 h& r- D& @

  38. 9 `! Z5 ~, b: w2 P$ m
  39.   uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for9 M/ N1 F/ E6 n  t$ B
  40.                                   calibration messages./ _0 O, o- s' m0 d1 ^6 L# W0 T
  41.                                   This parameter is ignored if FilterConfig is different" ^7 e( l, n* [% I" k, ^- }& v8 m
  42.                                   from FDCAN_FILTER_TO_RXBUFFER.
    & h) G9 ?; c% v
  43.                                   This parameter can be:% V0 ?" k# `3 V7 b2 i3 P- J6 |3 _
  44.                                    - 0 : ordinary message8 \* M* U4 w* \8 q) J
  45.                                    - 1 : calibration message                                */
    ' N, Q% S7 S" B8 n$ U' q6 O$ D

  46. ' U1 |1 P9 e9 f6 m( K: r
  47. } FDCAN_FilterTypeDef;
复制代码
4 i3 T8 R" H5 f( @( |( d
  IdType1 W. T: K' Z; v" s
用于设置标准ID和扩展ID。
4 y" S3 J! R" K4 q+ t" K) l' _( v" W5 E; i$ s
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */: f7 @" T5 D# J7 G$ ?
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

( B  V6 V" I# v9 a  FilterIndex" V) @8 M" M' U( Q
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。0 w! m: o9 h+ q: K6 K

& q3 \' X3 x2 W- F  FilterType
) U# ?2 j+ v2 k& B用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。
3 [9 h2 {' X# Y' _$ l5 V, c3 V* C/ Y: t" ^
  1. #define FDCAN_FILTER_RANGE  ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2  */  B4 z& P! z! I9 w# n+ w5 L) j, J0 R
  2. #define FDCAN_FILTER_DUAL   ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2  */
    . {, H# k5 k: r, r: @8 O

  3. 4 x7 k' a  V' ~' W/ }$ Y7 X
  4. /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */
    : Y" O8 f: R& ^# H6 e* C
  5. #define FDCAN_FILTER_MASK   ((uint32_t)0x00000002U)
    0 [5 h- t4 L5 w9 O( S

  6. , ?, E/ I, m/ Y0 C
  7. /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */1 L9 ]. S$ R! v3 z; S
  8. #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码

. A' S( s# ?: @! ~# e  FilterConfig
& h' f9 G% ]* h# M用于设置过滤类型。, V6 X% U3 d2 o* ~. A  q
+ u8 H7 u6 K" i
  1. #define FDCAN_FILTER_DISABLE       ((uint32_t)0x00000000U)  禁止过滤
    9 r" w6 N3 i3 q# y
  2. #define FDCAN_FILTER_TO_RXFIFO0    ((uint32_t)0x00000001U)  如果过滤匹配,将数据保存到Rx FIFO 0
    1 |+ m$ x( G4 M/ x( n: i8 e) w; x
  3. #define FDCAN_FILTER_TO_RXFIFO1    ((uint32_t)0x00000002U)  如果过滤匹配,将数据保存到Rx FIFO 16 z/ s, @  r2 q" C) h
  4. #define FDCAN_FILTER_REJECT        ((uint32_t)0x00000003U)  如果过滤匹配,拒绝此ID
    ' f& m) p2 k' E' J7 L  H
  5. #define FDCAN_FILTER_HP            ((uint32_t)0x00000004U)  如果过滤匹配,设置高优先级
    7 `, N. z" X' y# O0 W& q' A
  6. #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U)  如果过滤匹配,设置高优先级并保存到FIFO 0
    2 Y7 Z1 [) J$ v2 z
  7. #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U)  如果过滤匹配,设置高优先级并保存到FIFO 1* }# p( h8 V5 e
  8. #define FDCAN_FILTER_TO_RXBUFFER   ((uint32_t)0x00000007U)  如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码

. }. u' ]; f0 f# k配置9 o# P+ C6 }: `/ [2 s
  FilterID16 [# l2 g4 Y. z
用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。, k6 Q$ h3 N. H1 @3 F! {" F
+ F7 ]) C  o( o8 \: ^  e) a, U# e+ d
  FilterID2$ Q+ c* b+ b. e  D0 E
用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。! Z- ]' a5 n, s  Y+ [/ g

* N: l6 p( Z$ O  RxBufferIndex% a; r% |0 V+ w& [8 h$ z2 }
匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。- y$ l& O* F% J0 ]1 a8 \

' _7 `% ^" Y% j1 `5 n% i4 A  IsCalibrationMsg
$ |6 z+ S3 z# G; M4 u用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
. T4 _: O6 }- j  \0 A) A2 `8 @# G1 O( f7 \5 u! D$ ]/ q3 i+ p
0 : 表示正常消息。' [4 W( w7 l- g8 R1 G

7 F: M" q  R" r2 Y1 : 标志校准消息。
6 l% K1 ^" L# W+ ~3 q$ T3 o/ D3 R
7 S: @& @+ |9 r5 A! O91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef/ I: S- i9 C0 g  c
下面是CAN FD发送消息结构体:6 o. [# v- ?8 u( ^% r
- c/ c1 p1 l5 X& }; s
  1. typedef struct
    4 T" s" Z) p: d4 N$ F$ h
  2. {7 I: d0 M3 q% R$ u& v9 ]
  3.   uint32_t Identifier;          /*!< Specifies the identifier." k1 V0 x# H7 N6 O) F+ a
  4.                                      This parameter must be a number between:
    / J/ v% H% g/ D# S, A( C/ N9 [9 e
  5.                                       - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    ) n/ b# \( M0 A( j' x8 ?' P
  6.                                       - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */- i( I3 X8 |) v0 H8 j: w) y/ d

  7. : J) C2 R9 ~/ y: j
  8.   uint32_t IdType;              /*!< Specifies the identifier type for the message that will be
    ! r6 n# f0 k" ~# @! s7 b
  9.                                      transmitted.# Q. b2 `1 r% x3 d* F0 L1 O! [
  10.                                      This parameter can be a value of @ref FDCAN_id_type               */6 M0 B3 J* t+ m& |2 X
  11. , J. w$ e. h" `% I( @
  12.   uint32_t TxFrameType;         /*!< Specifies the frame type of the message that will be transmitted.' ^. M; R3 M, x$ V7 A' U
  13.                                      This parameter can be a value of @ref FDCAN_frame_type            */. t* ^( e1 x/ P6 s; S# P

  14. ( J0 [! @9 W/ \
  15.   uint32_t DataLength;          /*!< Specifies the length of the frame that will be transmitted.
    - r" [+ g0 F# ^5 w
  16.                                       This parameter can be a value of @ref FDCAN_data_length_code     */
    * D- I) M1 I- o1 E

  17. 6 k6 Y. Y' m0 i# P1 N  w& g
  18.   uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.
    1 ?4 }- |2 s1 P3 h
  19.                                      This parameter can be a value of @ref FDCAN_error_state_indicator */
    , z* \; `$ U- }: J3 r; h' d

  20. 3 I" n+ o% \' B" S. j/ s" A
  21.   uint32_t BitRateSwitch;       /*!< Specifies whether the Tx frame will be transmitted with or without6 f4 h9 ^6 o/ C+ l* T$ |6 Y( j
  22.                                      bit rate switching.: [) |) c" m* \1 Y4 M* i: P
  23.                                      This parameter can be a value of @ref FDCAN_bit_rate_switching    */: r4 ^' S7 g. Y2 f
  24. 8 e6 g4 E: i% f7 e- l/ Y
  25.   uint32_t FDFormat;            /*!< Specifies whether the Tx frame will be transmitted in classic or) B: J3 P7 H  n' I  Y- l
  26.                                      FD format.
    " Y/ ^4 C" I, J: b( p
  27.                                      This parameter can be a value of @ref FDCAN_format                */- s. f7 X  R8 O. C/ L- R) q, ^

  28. # T. b3 P4 L! U
  29.   uint32_t TxEventFifoControl;  /*!< Specifies the event FIFO control.% ]/ D. f6 p& R
  30.                                      This parameter can be a value of @ref FDCAN_EFC                   */
    ' }. O: _, k$ @, b8 H- k
  31. 9 b# a% z6 z# p# V& Y( \5 j0 p
  32.   uint32_t MessageMarker;       /*!< Specifies the message marker to be copied into Tx Event FIFO) }2 i! U: L3 A) I7 u
  33.                                      element for identification of Tx message status.
    1 z" ?9 q5 h  |
  34.                                      This parameter must be a number between 0 and 0xFF                */" |) d) w- `) }5 b. \

  35. 9 V* ?, z" Z9 [/ |' L; D0 ]& y
  36. } FDCAN_TxHeaderTypeDef;
复制代码

0 x3 ~5 i1 l: B/ Z  Identifier+ b: l+ ]5 L: U0 R# u$ n
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。% {' Y+ K0 p0 O+ i$ t6 ^# t# W
9 b: q& g0 {% I4 H$ X, r( d% W
  IdType+ G4 M7 O1 y# f# |$ X4 a3 F9 J
用于设置标准ID或者扩展ID。
( ~1 S2 O8 X" h& U
4 b& V5 P$ K+ q8 r
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */! o  c; k* |8 ]  d( ~
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码

2 e. o3 w# C' z8 M% w- {9 ?  TxFrameType' Z) u6 P' U. }$ l5 g5 k  Z% U
用于设置帧类型,数据帧或遥控帧。: H. \5 V2 w+ T- ~' A0 O
1 ]. N* P7 h1 ?
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    " `7 R/ V& ]% b3 `; b9 N$ X2 a
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

7 d, u$ A- t9 J$ n6 Z1 M  DataLength
7 n6 l& ~+ D+ c) X5 D( h用于设置数据长度。8 H, ~1 G/ _! ?3 x, H5 j4 P

/ z" C6 b$ j" }) s0 c1 Q' M, p
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */
    % N% m: H! P, P3 r# \
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */3 H. c( V( M8 X) ]5 a: G# W
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */) k6 b9 t5 k' G6 N% U1 k- Y' r
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    2 y4 [' D+ m! b0 |0 c
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */% k5 x  l' s: R9 h# q- N# A7 [% L% T
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  */
    & m7 B5 s9 C& [7 Q
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    8 v% Z% E9 y* o& g
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  */
    $ S/ c( R1 k) H! \2 v
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */
    2 _7 W- `7 H: X+ e( D
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
    " h. I6 M- a% n
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
      d( m- H1 }9 p9 a
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */) q% |. m' m  ]3 B: i! F
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */
    $ K' Q# v3 s! D/ x. C0 T
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
    $ F* b9 a4 m  M6 t6 t$ p4 R/ ?. I
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */' Q$ |$ ?" s7 E$ x# A% z
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码

  w. @9 A% b1 s  r  ErrorStateIndicator
7 G7 C! k4 g% |用于设置错误状态指示:! J9 [# T) D5 w4 A' w: A; Y  E

4 F- @. D( X$ o" c5 S. P0 t9 G
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点 error active  */4 l- c. @3 A! Z* L* _
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码

' P' V. ~' K6 H1 F  BitRateSwitch1 J) f3 }9 g' C  ?
用于设置发送是否波特率可变。
$ i0 d5 a: _3 k7 w/ i& `/ l$ j- S" S% D" k4 P+ g
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
    6 |+ `/ e3 X* n8 J! i: f, @# B
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码
( L; {, a- u+ a3 D' I2 A3 r
  FDFormat
! J- @% N* {3 w! m5 ], f3 o用于设置发送帧是经典格式还是CANFD格式。
! L7 L- s, e3 R9 s) @. D
  1. ; [; R' k& w7 f: A- r6 a
  2. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */, x, D3 j$ D" L7 c1 E# v$ `
  3. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码
7 M7 G5 n# b* N
  TxEventFifoControl
% V* _5 V" w7 V7 ~3 M* L用于设置发送事件FIFO控制。
* g/ j) q7 S. S6 |4 s( U0 l, a
; H4 \! N$ a0 P0 F6 ~" e9 K
  1. #define FDCAN_NO_TX_EVENTS    ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
    $ W/ q& v% p2 u+ x
  2. #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events  */
复制代码

9 Q1 M6 E5 G- D) R* Y+ k  b  MessageMarker: o' Y! Q7 v" w
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。
0 ]$ _+ r! O! |# M! }: y4 f, D& C0 ?/ W8 U' T- m
91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef
1 H, S5 R( T% z0 N, W$ |( G( ^" n下面是CAN FD接收消息结构体:
. F$ @( p& t. C5 m2 ?. M" j/ o7 s/ `1 F) o
  1. typedef struct
    7 W, G6 e5 }; T2 y  c% ^
  2. {
    0 ?4 g- r2 q# g  Y0 o+ F
  3.   uint32_t Identifier;            /*!< Specifies the identifier.
    6 g6 L& i& ]( X
  4.                                        This parameter must be a number between:
    0 u5 k5 I8 u2 _
  5.                                         - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
    ' d7 ^& E5 @" r( B
  6.                                         - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID               */
    0 `9 c/ G3 e* E. h1 e

  7. $ h8 w# V$ b& g& D4 \2 c; Y2 r
  8.   uint32_t IdType;                /*!< Specifies the identifier type of the received message.
    ! _  X+ \2 _8 y
  9.                                        This parameter can be a value of @ref FDCAN_id_type               */
    - p& U- v8 U2 b0 Z4 {

  10. & ], }$ T* I  G/ d; O+ r
  11.   uint32_t RxFrameType;           /*!< Specifies the the received message frame type.
    6 Q" b! |! ]: {- i  D( O
  12.                                        This parameter can be a value of @ref FDCAN_frame_type            */% d& x6 }2 c9 K1 j' W
  13. ; K( e, l5 H6 n4 ?$ t
  14.   uint32_t DataLength;            /*!< Specifies the received frame length.3 c5 ^! j7 z- n' @2 Y: u5 E
  15.                                         This parameter can be a value of @ref FDCAN_data_length_code     */
    , w1 L* R, ?0 E* J, X! t
  16. 4 w" d; r' j/ E3 ~4 T  w' m* `
  17.   uint32_t ErrorStateIndicator;   /*!< Specifies the error state indicator.
    * u; s! v( L  M1 r
  18.                                        This parameter can be a value of @ref FDCAN_error_state_indicator */
    . d, d, a* {9 D) ?; t, Q, m, A
  19. : P  S% j( ^8 l! K7 R, V1 \
  20.   uint32_t BitRateSwitch;         /*!< Specifies whether the Rx frame is received with or without bit) s7 c+ o% g5 b& `+ {0 c
  21.                                        rate switching.* k4 e7 b5 g1 w! G4 D
  22.                                        This parameter can be a value of @ref FDCAN_bit_rate_switching    */
    - e; w7 F3 S. J. l: X3 ~
  23. $ U6 _3 ?6 r, o
  24.   uint32_t FDFormat;              /*!< Specifies whether the Rx frame is received in classic or FD
    6 {, O. y' G+ j
  25.                                        format.0 W, l+ U4 I7 n* Z& n" p
  26.                                        This parameter can be a value of @ref FDCAN_format                */
    # b" c; S1 I6 r" v7 D& i
  27. 7 Q7 M# j* v* @) }3 c
  28.   uint32_t RxTimestamp;           /*!< Specifies the timestamp counter value captured on start of frame# k9 [# \' }. s: U& C
  29.                                        reception.
      L* k$ }: @3 v, A& |
  30.                                        This parameter must be a number between 0 and 0xFFFF              */
    $ d+ L% L+ |' L3 H, T

  31. ' F9 q0 ?# }' g7 {& q* v
  32.   uint32_t FilterIndex;           /*!< Specifies the index of matching Rx acceptance filter element.5 |, Q1 h* \6 a. h9 j. K. @* \! s
  33.                                        This parameter must be a number between:
    . T, t! z% W% p6 r1 D
  34.                                         - 0 and 127, if IdType is FDCAN_STANDARD_ID
    & U0 ^7 h" C3 C& p) p- E' L3 u
  35.                                         - 0 and 63, if IdType is FDCAN_EXTENDED_ID                       */
    ' P+ c, O1 I& i5 W9 x: \6 b4 B0 n" l
  36. - N# ~# w# m7 s$ s
  37.   uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.
    * [9 s/ z5 u/ o0 s/ ]% l
  38.                                          Acceptance of non-matching frames may be enabled via2 U! Q3 s# N. F, K5 I' }' G
  39.                                          HAL_FDCAN_ConfigGlobalFilter().
    & I: O% X$ v- {3 l
  40.                                          This parameter can be 0 or 1                                    */$ h; T& w& H5 {3 f* K7 G
  41. 1 ?& Z3 [' T* V' T2 s
  42. } FDCAN_RxHeaderTypeDef;
复制代码

3 [5 {/ ]3 u: ]* Y  Identifier
0 v0 [" c7 x1 E- q. g/ z用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
/ u+ _! ~* a* U. v6 n( B9 v$ [
( C/ W+ o  [2 r. g. f+ |% N  IdType
% x& I1 E) S! |' d5 {用于设置标志ID或者扩展ID。& t& z! C7 G% f3 \

# W* H  l! h( `9 p& d
  1. #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */1 r6 N6 R% Y$ `, n# {  v
  2. #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
: j) @( p9 F1 u. X; w
  RxFrameType
; K1 G0 F7 W, ?/ v. b( w2 E用于设置接收帧类型,数据帧或遥控帧
/ z$ d- N6 y5 _, Z' [4 q9 Y. b: a9 v1 o
  1. #define FDCAN_DATA_FRAME   ((uint32_t)0x00000000U)  /*!< 数据帧 */
    7 [4 e4 \% D/ ^, U2 B
  2. #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U)  /*!< 遥控帧 */
复制代码

: u6 E- U7 |; k2 v& P  DataLength! A$ {+ s3 A+ u+ Z8 \7 |- a* E
用于设置数据长度。$ X. ^' f: V/ d; ~; p% g

( g+ x) O" c- g& F
  1. #define FDCAN_DLC_BYTES_0  ((uint32_t)0x00000000U) /*!< 0 bytes data field  */
    7 c0 W8 z( U, i$ o! {
  2. #define FDCAN_DLC_BYTES_1  ((uint32_t)0x00010000U) /*!< 1 bytes data field  */
    : h7 |& R+ u9 M9 j5 C
  3. #define FDCAN_DLC_BYTES_2  ((uint32_t)0x00020000U) /*!< 2 bytes data field  */
    - o8 V+ z9 T& M+ @5 z; q! Y- Z; L
  4. #define FDCAN_DLC_BYTES_3  ((uint32_t)0x00030000U) /*!< 3 bytes data field  */
    # i, r) Z) f0 E5 V- n/ {
  5. #define FDCAN_DLC_BYTES_4  ((uint32_t)0x00040000U) /*!< 4 bytes data field  */
    & |. j8 m9 x; g8 }$ C  v
  6. #define FDCAN_DLC_BYTES_5  ((uint32_t)0x00050000U) /*!< 5 bytes data field  *// x# D! u9 Q. d9 L* T6 y
  7. #define FDCAN_DLC_BYTES_6  ((uint32_t)0x00060000U) /*!< 6 bytes data field  */
    3 v+ }1 O( b: L, n3 e
  8. #define FDCAN_DLC_BYTES_7  ((uint32_t)0x00070000U) /*!< 7 bytes data field  *// u# F/ e* g5 h, f# U5 e5 c
  9. #define FDCAN_DLC_BYTES_8  ((uint32_t)0x00080000U) /*!< 8 bytes data field  */. M: i2 v6 y( Q3 v# D2 i: z
  10. #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */5 A6 J* I7 n, j
  11. #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */
    , B& m: {: L. k& u$ y4 ~
  12. #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */( L# C1 q4 K. }9 e* M
  13. #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */! k0 u2 E* {* [: M0 l
  14. #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */& ?. w/ Z6 `4 c5 ^! K! r4 x
  15. #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */. t# i( X- @2 B9 D/ ?
  16. #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
    5 r, ~9 F. Y  O! K4 [
  17.   ErrorStateIndicator
复制代码

4 B( w& Y( [2 ~! H' I用于设置错误状态指示:' k1 U9 S) Q: W7 ^8 B& H' v5 I: n
& P: h4 z0 e2 s( x
  1. #define FDCAN_ESI_ACTIVE  ((uint32_t)0x00000000U) /*!< 传输节点error active  */( i- Q& z; U) l" w
  2. #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
+ A/ X, A+ [8 S  F3 u0 b
  BitRateSwitch
' x+ A5 o+ `% ?, V. g用于设置接收是否带波特率切换
4 M" o+ F5 a7 J$ \) Y% k$ V! w  w1 U: G5 n
  1. #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
    ! ~9 |$ K0 d9 X7 M5 q7 F2 p" V
  2. #define FDCAN_BRS_ON  ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码
+ L4 o- Q  ]# C" `, `8 J
  FDFormat2 U% z7 f' C) L5 j& T1 b
用于设置接收帧是经典格式还是CANFD格式
( U6 [0 p; N# j3 @/ W
# c% `, d+ H! g5 Y
  1. #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */
    3 h* `. p2 o6 d% ~/ t* i' q9 x7 z
  2. #define FDCAN_FD_CAN      ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码
5 r) h  n! ^& `3 c
  RxTimestamp
+ q1 C2 ^- ?# R用于设置帧接收时间戳,范围0到0xFFFF。   
2 m$ ?+ Z- M/ q9 |; X- z8 y1 |* z
8 {0 Z- P' m1 @) E; ^2 }  FilterIndex  M' I7 b1 L) L' ^% H  Z# G  W: l
用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。 $ Y: @1 @$ V( v' s) x  K5 o
, z7 t6 e; `7 M: \( C
  IsFilterMatchingFrame
" k  ^, J0 }6 @9 R' F! a9 u用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。
7 p- g3 w! T/ F. U) {6 a& M( z! Y8 G
0:表示不接受。
- z. J7 }. i; `: }; q$ M) V0 Y$ l# b/ u9 M: V4 s3 @
1:表示接收。
# [5 j( V+ G- o5 l+ v, n
* e& a/ ~& J( I$ Y4 u2 n% J91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef1 n  ?8 Z4 x2 Z( b% @9 P
下面是CANFD句柄结构体:2 ?( h% c' v9 N' j$ }6 ^9 G

! I" i- u6 w3 c( t4 k
  1. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1( t/ K0 Z3 C3 u  R  E
  2. typedef struct __FDCAN_HandleTypeDef
    2 S0 O/ ?( K7 a3 d* v
  3. #else
    * r# x; q! l* o* H) u/ Q
  4. typedef struct, ?$ [$ {9 y6 U- Z3 A
  5. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */+ w3 v& {" z+ ~; u
  6. {( i1 R' |: C+ ?0 o! g/ r) l/ t
  7.   FDCAN_GlobalTypeDef         *Instance;        /*!< Register base address     */
    9 o$ M; j5 q$ M  l, Z) B! h

  8. 7 H- F6 n! [4 X$ r5 T2 ~# }
  9.   TTCAN_TypeDef               *ttcan;           /*!< TT register base address  *// A' M! a3 J! D# A

  10.   j2 H0 `9 o( f# W4 v
  11.   FDCAN_InitTypeDef           Init;             /*!< FDCAN required parameters *// f7 v" j8 ~1 `+ h/ u
  12.   K# r- p$ Q5 V
  13.   FDCAN_MsgRamAddressTypeDef  msgRam;           /*!< FDCAN Message RAM blocks  */7 c4 @8 V2 z  B$ F8 X
  14. 4 O: D5 Y2 k+ ]7 K& t# }: T# I
  15.   uint32_t                    LatestTxFifoQRequest; /*!< FDCAN Tx buffer index
    ' O' U! ^1 q% Q1 {5 b
  16.                                                of latest Tx FIFO/Queue request */- e& e2 a0 o! t! ~0 \8 O+ G3 k, u

  17.   |( Y5 @( ^- K# I$ Q) W- k0 C+ C
  18.   __IO HAL_FDCAN_StateTypeDef State;            /*!< FDCAN communication state */' V: t9 L. k" K4 P

  19. 0 g  o6 k3 x2 \1 M
  20.   HAL_LockTypeDef             Lock;             /*!< FDCAN locking object      */
    ; G" F* P$ F6 U2 D5 u
  21. # @/ x$ b: a, F. X, r1 Q+ v$ b3 ^) h
  22.   __IO uint32_t               ErrorCode;        /*!< FDCAN Error code          */
    2 \3 ^  {7 n$ k

  23. 2 d; W  K, k! r6 r" e, V
  24. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
    9 T- z6 ?2 m% H, G
  25.   void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs);         /*!< FDCAN Clock Calibration callback          */
    6 q' ~/ H0 H( @8 ?) |# D) Z2 l8 J
  26.   void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs);                 /*!< FDCAN Tx Event Fifo callback              */
    % ~" q8 }, S+ W5 l  B( G+ Q4 ?5 S
  27.   void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs);                         /*!< FDCAN Rx Fifo 0 callback                  */3 k, V1 o5 K; V5 ?& ~3 ?
  28.   void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs);                         /*!< FDCAN Rx Fifo 1 callback                  */8 {- k. a+ M1 B; j; P
  29.   void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                          /*!< FDCAN Tx Fifo Empty callback              */4 G! R9 R  j2 k
  30.   void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);             /*!< FDCAN Tx Buffer complete callback         */3 a8 i9 x4 \) @
  31.   void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes);                /*!< FDCAN Tx Buffer abort callback            */
    " S# O3 X  I7 ^* e" @8 g' b- A
  32.   void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                   /*!< FDCAN Rx Buffer New Message callback      */
    % H( G% W6 I, n6 W7 t1 q+ j
  33.   void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN High priority message callback      */! q. r& }- f& D; @3 f  H( z
  34.   void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                  /*!< FDCAN Timestamp wraparound callback       */
    8 D# f! ~) {* [
  35.   void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                      /*!< FDCAN Timeout occurred callback           */
    7 M6 N7 Y  {5 S9 }( M; H
  36.   void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                                /*!< FDCAN Error callback                      */
    " E" F) T- J  M' O+ i0 V' u7 A
  37.   void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs);                 /*!< FDCAN Error status callback               */5 Z" Y2 q  s6 f/ r
  38.   void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs);             /*!< FDCAN T Schedule Synchronization callback */
    . t9 t1 m( Z7 K+ U3 O1 X
  39.   void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs);                  /*!< FDCAN TT Time Mark callback               */" Z9 ]# D  J7 W2 K$ m7 a
  40.   void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback              */
    + x* x! e1 ?2 ]1 J: ?
  41.   void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs);                /*!< FDCAN TT Global Time callback             */
    5 B& S1 c; E7 J+ Y1 l

  42. 2 [4 T: ?  P; v- c9 H7 |+ F
  43.   void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                              /*!< FDCAN Msp Init callback                   */
    ! o, X2 o" {' k4 i4 c, e. i! i
  44.   void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan);                                            /*!< FDCAN Msp DeInit callback                 */" w. h& C; ?% |# v7 q, o
  45. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */8 d: F' J) \* k

  46. ! T, r" d' V+ g8 f! q$ A3 Q
  47. } FDCAN_HandleTypeDef;
复制代码
; Y* Q5 l. L  H  d  d
注意事项:
9 x$ U$ F% x9 e4 e
" e: G; ]: ^( V/ @; Y/ V条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
) @4 a. P- i/ O, C1 I% _( f: h
  1. #define   USE_HAL_FDCAN_REGISTER_CALLBACKS   1
复制代码

6 N) H# A! k: E' t  w! ^) n# ]- ?
9 I' d& Y  O+ A' h5 v' l; H5 t函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。+ d% c# x3 q* P0 V
7 u1 Q- Y  ]8 ]$ }( t
这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
$ m8 L6 E" @# E  v. C9 R5 X# d2 [0 g5 g' h5 B
  FDCAN_GlobalTypeDef         *Instance( H. l* v1 ^' M9 t
这个参数是寄存器的例化,方便操作寄存器。
9 ~3 Q" N1 n2 q! l
+ b' |5 V! j7 a4 C: i" ^  TTCAN_TypeDef               *ttcan
+ o- f6 k5 F4 J- c: n8 B8 {1 ]TT CAN时间触发寄存器基地址。
  l$ N( p7 c6 A( ^+ m
- b# k7 t6 g- \! _9 I, b! q  FDCAN_InitTypeDef           Init  v: y6 B( X( U: i) @2 K
FDCAN相关的初始化参数。
- v- r/ n' E  @2 f9 n
* r2 l( ~+ N3 d; }( W$ ^7 s  FDCAN_MsgRamAddressTypeDef  msgRam
0 \% ~; k" E, w( _8 x消息RAM地址。
0 t) z6 o6 l; R7 f2 q4 u% ^; B, H1 G# I# I$ U1 v; b3 j
  uint32_t    LatestTxFifoQRequest
9 h( c; J7 v+ b' X- d8 oTx buffer索引最后一个Tx FIFO/Queue参数。& o$ a- q* r' g! t; I% @

$ [5 d+ J2 s! h% u: B' T. l; k  __IO HAL_FDCAN_StateTypeDef State          ! l7 m7 o. ]; L3 N( ~+ {
HAL_LockTypeDef             Lock         
( [* }$ @1 w! @7 _$ M* [$ h3 c' s9 {8 t( {
__IO uint32_t               ErrorCode( d$ u$ ]) M1 o; d

) n% E8 g  {6 o5 D" i程序内部使用的状态参数。" U* k: {/ c; U; k" m7 A$ A

. }$ b- r$ u0 H2 p# Z7 n1 ~  剩下的都是回调函数% T  g0 P1 ?. ^/ @! l! O
91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
+ U; ^, g0 w  H2 k  n' u# |此文件涉及到的函数较多,这里把几个常用的函数做个说明:" R: `& |  b% I) J! D6 V% M( t
+ J( _# B1 y5 ?6 D: |5 \4 E9 g8 C
91.4.1 函数HAL_FDCAN_Init2 Q% n3 v& U8 G5 u4 z
函数原型:/ h  T7 ^8 ?* Q1 M& F) v4 o

4 e) Y0 v! T& p2 d
  1. HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan); o1 n  U# F" k
  2. {/ q4 i- q# Z% D
  3.   uint32_t tickstart;3 ~$ T; C! I0 L; _
  4.   HAL_StatusTypeDef status;
    3 t; D4 g0 ^8 c1 M
  5.   const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};
    1 p6 q3 b0 Z" T* V

  6. : o- U: Y# V! _1 E# _9 S
  7.   /* 检测FDCAN句柄是否有效 */! e2 p) _) x% [7 j! T
  8.   if (hfdcan == NULL)
    - A5 p4 h& B" N- i
  9.   {, N$ g* ?' A3 T0 _, u# L. h
  10.     return HAL_ERROR;/ A4 g9 Y* u- `9 R
  11.   }
    8 V6 `9 P5 I& y! V4 H: s

  12. 3 I1 a# T8 \8 Q: s" |4 [1 r
  13.   /* 检查FDCAN例化 */5 w0 z2 N% u: V3 P4 R
  14.   if (hfdcan->Instance == FDCAN1)
    ! h% y/ Y4 }' @6 `! }5 T4 M
  15.   {
    ) M4 ?# g6 n9 U9 H
  16.     hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
    # u8 w" C0 Z" G3 n. v, c
  17.   }1 |, ~. p; f5 y1 F! X7 n

  18. 5 D, i* u1 q- e) F
  19.   /* 检查函数参数 */" P; \9 G( t2 z
  20.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));& o% o' `+ s7 n5 ?" k' x
  21.   assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
    5 M  s! S3 o3 }5 ?- r. d
  22.   assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));. I1 L, s7 _$ `/ f! r
  23.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission));# y! J# Q/ H9 u7 r! S
  24.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
    . Z9 H( g$ S6 P- G2 [% C
  25.   assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));* a! G# n0 m: W, G" _
  26.   assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));
    8 u* O3 Q5 `2 ]# }; ~" a
  27.   assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
    1 f7 W& Z+ u$ N% F8 K6 |
  28.   assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));
    % p5 o5 d; M2 `6 X0 V% \, Y
  29.   assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));( h9 `' w! \) J0 L1 ?! R" r
  30.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)( _% B3 x( `% H/ @* n8 t& A9 Q
  31.   {$ ]* F8 n$ W( O
  32.     assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));; R) [" `- Q' G' p& ^
  33.     assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));1 R; m' @. |, @! M
  34.     assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
    " b+ s2 I- V  ?2 [
  35.     assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));
    0 w9 G4 Y5 @  w5 @; y% z
  36.   }# K& F( `! q8 ^6 s; P# m
  37.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));
    2 [) p0 d' D5 U7 m0 y
  38.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));
    ( G7 s% z! T6 b; P1 ~
  39.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
    ! k2 N- o5 u8 H3 ]# `
  40.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)
    & z  z/ J' \; M5 v6 V- @7 k3 q
  41.   {
    * f3 U3 w1 I2 t! M: I5 X4 B
  42.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));
    & f: _7 T" D) v( }; a
  43.   }
    ' _$ P& J, D7 f8 d0 I- u2 B- `
  44.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));: |- l, B  j% }% O+ {
  45.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)5 Y7 t6 u! C6 L$ k: ^2 Z
  46.   {) j, t* J6 ]) _6 L/ d- a
  47.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));% [" z/ P- ~& S* \( u7 O
  48.   }
    ) W) O$ s0 r& L) k. @7 }/ a! B
  49.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));4 N7 t* ?" g1 t, z- }* n9 U- [
  50.   if (hfdcan->Init.RxBuffersNbr > 0U)
    % k6 Q8 G% n" H' I
  51.   {
    8 k6 J, e( ?2 G. H  y! h! g
  52.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));
    ! `2 E5 y  v$ e" i# C. g3 y- {
  53.   }# J9 O/ g- J; a* d0 n# R
  54.   assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));  t  N$ f- P% D: O  V
  55.   assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));8 w5 H# p$ L$ u6 B; |1 m- i
  56.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    & @, ^) ]; F8 Q$ y/ A
  57.   {3 @! n' [! Q( X3 r
  58.     assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));7 e6 ~5 @0 f9 M, t' h
  59.   }$ N& c( L; |+ S  {4 Q# r
  60.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    ) w- n- K  y1 ?  x5 c
  61.   {, e' o4 {! [. L% U
  62.     assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
    " ^! Y5 [# `& Q  B& G
  63.   }, E- q5 F7 U0 q! v3 R$ I
  64. 8 X0 {- V* R9 f2 E/ b& h
  65. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1' x; _2 Q5 |, A( Z8 J! E' S
  66.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)( N9 ?5 I+ j$ |. G. ~, S
  67.   {" {! ?8 j2 t1 K, a5 P
  68.     /* 解锁*/
    . i+ K, f4 y+ c3 ?
  69.     hfdcan->Lock = HAL_UNLOCKED;
    2 }% I- }3 d0 w9 I5 B% d

  70. ; D9 @% B" `; T, ?6 g9 {# l( o, z
  71.     /* 复位设置默认回调 */" K& I; h3 P" H1 P: v
  72.     hfdcan->ClockCalibrationCallback    = HAL_FDCAN_ClockCalibrationCallback;    /* Legacy weak ClockCalibrationCallback    */
    ( }- N0 W; B( K+ I) F
  73.     hfdcan->TxEventFifoCallback         = HAL_FDCAN_TxEventFifoCallback;         /* Legacy weak TxEventFifoCallback         */
    4 f" r' F* [% f, m) V
  74.     hfdcan->RxFifo0Callback             = HAL_FDCAN_RxFifo0Callback;             /* Legacy weak RxFifo0Callback             */
    6 Y# Q7 E- V1 a: M) r
  75.     hfdcan->RxFifo1Callback             = HAL_FDCAN_RxFifo1Callback;             /* Legacy weak RxFifo1Callback             */
    1 H4 F! o3 l$ ~2 k
  76.     hfdcan->TxFifoEmptyCallback         = HAL_FDCAN_TxFifoEmptyCallback;         /* Legacy weak TxFifoEmptyCallback         */$ Q1 x2 q+ L$ a* o' z; t
  77.     hfdcan->TxBufferCompleteCallback    = HAL_FDCAN_TxBufferCompleteCallback;    /* Legacy weak TxBufferCompleteCallback    */, n) M% \" C7 n& q, y5 P
  78.     hfdcan->TxBufferAbortCallback       = HAL_FDCAN_TxBufferAbortCallback;       /* Legacy weak TxBufferAbortCallback       */9 x: g# ~$ Q. l5 f9 q4 c
  79.     hfdcan->RxBufferNewMessageCallback  = HAL_FDCAN_RxBufferNewMessageCallback;  /* Legacy weak RxBufferNewMessageCallback  */4 Q; T% F9 L! T8 r. M! u
  80.     hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */
    ' p8 C7 C" f  C/ ?. M
  81.     hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */1 J! c4 W9 W* _2 `' l& _) F
  82.     hfdcan->TimeoutOccurredCallback     = HAL_FDCAN_TimeoutOccurredCallback;     /* Legacy weak TimeoutOccurredCallback     */4 ?( l) m8 a1 f2 d- a. [
  83.     hfdcan->ErrorCallback               = HAL_FDCAN_ErrorCallback;               /* Legacy weak ErrorCallback               */
    + b- Z% z2 a8 H; h8 ?
  84.     hfdcan->ErrorStatusCallback         = HAL_FDCAN_ErrorStatusCallback;         /* Legacy weak ErrorStatusCallback         */
    # S: n' A! d" [3 h$ Q/ y! a
  85.     hfdcan->TT_ScheduleSyncCallback     = HAL_FDCAN_TT_ScheduleSyncCallback;     /* Legacy weak TT_ScheduleSyncCallback     */+ j: H: `7 u, N( U6 M% }) W
  86.     hfdcan->TT_TimeMarkCallback         = HAL_FDCAN_TT_TimeMarkCallback;         /* Legacy weak TT_TimeMarkCallback         */
    ! y( [/ @% A$ T) {
  87.     hfdcan->TT_StopWatchCallback        = HAL_FDCAN_TT_StopWatchCallback;        /* Legacy weak TT_StopWatchCallback        */6 X) S5 u' p( a1 D4 s; Y
  88.     hfdcan->TT_GlobalTimeCallback       = HAL_FDCAN_TT_GlobalTimeCallback;       /* Legacy weak TT_GlobalTimeCallback       */
    ' `2 |& V; M: T: C* M. t
  89. % |6 {- R) K8 W5 t5 ?
  90.     if (hfdcan->MspInitCallback == NULL)
      H9 E  @( C$ Q; _9 W
  91.     {8 W. x0 D4 m* Y0 |: k3 p
  92.       hfdcan->MspInitCallback = HAL_FDCAN_MspInit;  /* Legacy weak MspInit */  @7 H; \- X7 o8 E: v
  93.     }, u: @! Q5 `# x
  94. 2 A/ _: y( E" i; G7 g( y
  95.     /* 初始化CLOCK和NVIC  */5 m5 U1 O7 Q0 K: O! d! _: c
  96.     hfdcan->MspInitCallback(hfdcan);
    2 V% x3 Q/ V' s  O2 v2 w" u8 v
  97.   }
    / ^+ r2 [; @6 Y" b5 H
  98. #else1 v+ s! R! r8 |4 i/ G' u3 c- y
  99.   if (hfdcan->State == HAL_FDCAN_STATE_RESET)
    / W2 W7 ~$ ?/ T, H- {( l; d
  100.   {
    : ?5 W& N) M# @! h9 }
  101.     /* 解锁 */
    7 }# j4 Q  S8 v  v, k
  102.     hfdcan->Lock = HAL_UNLOCKED;7 O/ s: L' Q; A- f

  103. 9 F0 n# F: y. O3 l
  104.     /* 初始化底层硬件 */
    . w$ F! O% x1 ~( n) e
  105.     HAL_FDCAN_MspInit(hfdcan);
    ' y# ~7 m, K9 K# g
  106.   }" X$ ^3 M3 p4 b
  107. #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */2 p/ ]& w7 N  P' c6 D; M- E

  108. 1 r3 W* X2 E7 a8 |9 t
  109.   /* 退出Sleep  */
    3 j7 s) t1 Z5 p) ^0 n- K* q9 s4 z! M
  110.   CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);
    " ^' E. {: P( C) w
  111. 6 a1 N  A" {: h  n. Y% Q$ [4 Q" ?
  112.   /* 获取时钟 */) u# [  ?* ]. |. b5 h* K
  113.   tickstart = HAL_GetTick();  ~1 F, J( J8 c0 P' T

  114. 4 `+ i, Q0 m& D* P1 `2 i, S
  115.   /* 等待Sleep模式确认 */: j1 T. |; c! v! i
  116.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)8 A$ M/ T4 \( {" @+ b) R2 P
  117.   {! U0 e2 }6 o" k2 U1 `' L. X
  118.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)6 ~+ P) D& W* T0 F3 i  x& k
  119.     {
    6 }9 U" k) q! H+ A: C2 r/ A
  120.       /* 更新错误码 */
    / m- D$ [4 D' {. l
  121.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    " N; J. N; Z7 N9 ~1 h. V& f
  122. % d* k, B  t- I$ @3 v/ z
  123.       /* 改变FDCAN状态 */
    2 L1 T3 A* Y- u7 _! a1 j( ?
  124.       hfdcan->State = HAL_FDCAN_STATE_ERROR;! v' `. k- ]3 |* s# L  O- n0 s
  125. & ]" p' {- e' b- D7 Z+ Z
  126.       return HAL_ERROR;. I+ `& I' W7 ~9 _
  127.     }
    * F% |6 U# Y/ ~( q, p
  128.   }0 i/ t; z' @' R3 H2 ]( M

  129. % ?2 Y7 G0 v+ ?# _% F
  130.   /* 请求初始化 */
    # y6 E1 s6 z. j, s8 U; L2 |" Q
  131.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);) i, y( I7 }9 v( E) k+ b! K/ b

  132. ! S+ }  V/ E# u0 ?0 {8 v0 y
  133.   /* 获取时钟 */2 n7 P2 e0 t/ _- E7 K
  134.   tickstart = HAL_GetTick();0 X1 ^  Z+ A4 |' d6 u

  135. " ]3 g; w$ L0 a, R% g5 q
  136.   /* 等待CCCR寄存器的INIT位 */5 J. G' f6 U; ?! v5 R, y
  137.   while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)( z. ^6 m% R, R
  138.   {
    + J% |9 P/ z. h* [! [& r# Z
  139.     /* 检查溢出时间 */
    ( Z$ j9 ?) D$ g9 \1 `  w
  140.     if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)0 f1 g) y& k0 [6 [' M! L7 O, Z. c
  141.     {
    2 J( ~! J1 e  p& @- }6 h( k8 ?: f5 r
  142.       /* 更新错误码 */% ]5 P/ Y- }$ H7 ~/ f0 T. G' R' J
  143.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
    ' a; j0 \4 ?4 v
  144. 2 A! N: F: q$ b
  145.       /* 设置FDCAN状态 */8 E8 \5 K  w& V! Z: v2 z% h+ c
  146.       hfdcan->State = HAL_FDCAN_STATE_ERROR;& a5 n1 Q. T3 |4 k* {/ p
  147. ) @0 G) g; c* X3 B9 \
  148.       return HAL_ERROR;# r: ~( l: n# V/ F0 K- Z' R
  149.     }
    4 l- i0 c" z/ w5 H! w
  150.   }0 U1 b% v/ R8 H# Q4 C0 n
  151. 0 f1 \* x, u+ X2 P
  152.   /* 使能配置修改 */! Z* j) E5 E* G
  153.   SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
    4 O9 x. L9 H) `5 e8 b

  154. . c+ v* L9 @2 U  o7 q4 T$ d# k# N
  155.   /* 设置是否自动重传 */9 b: z2 T" W& b% C
  156.   if (hfdcan->Init.AutoRetransmission == ENABLE)
    , \* s( L. F" [/ H5 W5 E
  157.   {8 ]* s6 u  M! ?4 z
  158.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);- N2 |3 F  k6 X. l  S3 x: V
  159.   }) H( y2 e  a4 r6 C
  160.   else# R% l" }3 _& G1 k) n# L  L. g
  161.   {
    8 q* t! I( E$ S* i3 z* s
  162.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);) W7 e$ F" P2 W, O: k- h5 [) D
  163.   }
    , N0 H" `1 R& ]0 P$ P
  164. ! z4 L' T3 }3 d1 `  }  [
  165.   /* 设置传输暂停特性 */, R% G  x; W) W) M8 _
  166.   if (hfdcan->Init.TransmitPause == ENABLE)1 O4 u/ Z3 c; D* v3 _. z5 k$ |
  167.   {  A. c& B; R4 e0 Z- r  O3 N0 V
  168.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);  b8 h1 h8 \5 ]  N
  169.   }1 d; W" [1 e1 E
  170.   else
    % n' j6 E( w1 E9 K
  171.   {9 }1 W0 W% E, l& E
  172.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);! R1 K& J* }; n7 E6 \4 H
  173.   }
    0 n. m/ \* K+ [3 G6 K) J; V
  174. ; h8 T6 b" x+ @4 P: r1 I8 Z+ @
  175.   /* 设置协议异常处理 */4 J" F0 u7 }. J6 o( O2 p" l8 Z! n' B9 ]
  176.   if (hfdcan->Init.ProtocolException == ENABLE)2 @& o" g% {1 Y: P4 l; {
  177.   {+ ^# q9 \) u. ^0 K
  178.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    7 @1 f' c4 ^1 d
  179.   }
    7 O0 w8 @4 l1 r' e1 ]" N0 z& {
  180.   else5 a/ E, Q# b: x3 B" B) ~; {6 h
  181.   {
    1 Y. O0 t7 {3 n4 B
  182.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
    0 u) e  z3 y% S
  183.   }# S6 N, d% B$ Q  w* r/ ?

  184. + W: [; D' l% e0 t% S  S- T
  185.   /* 设置FDCAN帧格式 */8 P+ L7 i1 c) b0 @
  186.   MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
    6 U8 O/ C2 u& f3 R. g

  187. 8 \, ~1 Z3 k& d8 e
  188.   /* 复位FDCAN操作模式 */, M4 v; X0 v- O( |. n
  189.   CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));9 v5 ~. `% v8 ?. O: X
  190.   CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);) b! M  y; _0 h# l1 a, ]% g
  191.   P( G2 V1 P$ r+ s1 p/ l! z0 W
  192.   /* 设置FDCAN操作模式:3 s( _+ @9 T; V6 W
  193.                | Normal | Restricted |    Bus     | Internal | External
    1 u- I% W, Z. l/ R
  194.                |        | Operation  | Monitoring | LoopBack | LoopBack
    6 @" D+ L; {1 E; q+ K0 W$ c
  195.      CCCR.TEST |   0    |     0      |     0      |    1     |    1
    " Y1 e$ S  i9 \" C8 {; Z
  196.      CCCR.MON  |   0    |     0      |     1      |    1     |    0
    % M9 H8 R1 O0 R7 \6 r
  197.      TEST.LBCK |   0    |     0      |     0      |    1     |    1
    0 v4 u- Y  ^1 y& w3 f
  198.      CCCR.ASM  |   0    |     1      |     0      |    0     |    0+ e# Z/ k) r3 t; B( o9 [7 g/ O
  199.   */6 b' {0 a+ x; Z/ j
  200.   if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION). R$ l0 Q. e0 b! Z- B
  201.   {
    9 |7 [, o0 `, ]' r( _; k3 a8 S
  202.     /* 使能限制操作模式 */
    " E8 W9 N& N& L- h9 p
  203.     SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
    6 p6 O, M: {5 A& I
  204.   }- L$ v# K6 \2 B
  205.   else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL). a$ ?9 T; A6 I8 I
  206.   {
    6 g5 [) Z8 v7 x( x
  207.     if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)
    ' j7 @' }8 |) Z% z, a
  208.     {+ Y8 k5 S1 l* v/ i; g
  209.       /* TEST寄存器写访问使能 */) l) o: e' Q0 Z9 u
  210.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);
    2 V2 p6 Y8 f5 T) A2 c8 e
  211. # r% A  J. u, |1 G5 ?4 X5 Z+ F7 B
  212.       /* 使能回环模式 */+ A7 J5 a2 r7 n! g3 T9 z' z
  213.       SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
    0 x% G9 m, n$ c; s% H; B+ ?1 X* d7 p
  214. ; v- V/ J" u/ B! Y( S! O7 n/ A) N
  215.       if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)
    ; o! L' Q. }% [
  216.       {
    . C: P4 c9 k+ l( L6 G: M
  217.         SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);# J1 d& R5 W3 E2 s
  218.       }5 a0 i" B4 d& N/ e/ y' H- O! x
  219.     }
    9 g. s4 j5 a+ o* h
  220.     else% N# s1 W4 H1 x0 A9 _: `4 _
  221.     {0 S* \- |5 E+ [$ Z
  222.       /* 使能检测模式 */
    ; k( |' _! a  C; y
  223.       SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);/ D- n# P! l( i! o
  224.     }4 Z' _% ^* R) K8 t. a
  225.   }( X, u7 T' n* ^5 E( ^
  226.   else% M/ T% {5 a8 e  g- P5 v
  227.   {
    2 ?3 d1 S4 Z' t- B: i1 \
  228.     /* Nothing to do: normal mode */
    * f. N/ E/ K, l. X" n
  229.   }- J5 ~# O- @% P* s; t% r0 N

  230. 8 \! ~9 ~9 L; ?
  231.   /* 设置nominal bit timing 寄存器 */
    - g' n1 N! Z8 T, z0 l
  232.   hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \
      \* n: H8 k% w6 h! N! L: _
  233.                             (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos)    | \- B' {. z$ t0 S" w
  234.                             (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos)    | \% m8 t& ?0 K% r( ]2 {; M' ^
  235.                             (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));
    9 |7 {9 O5 b9 f0 G1 k# ^! k

  236.   ?, g" ~  O" a# j/ J# [
  237.   /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/# L6 j! G* R2 q6 Q% n
  238.   if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)3 C/ Y( {# c- f$ j1 [( [; v
  239.   {2 h, w' T! C0 A- ]
  240.     hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \4 _# O/ Q1 Q7 S/ U
  241.                               (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos)    | \2 z9 `" c" X5 ~2 E$ v
  242.                               (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos)    | \3 |6 c% D" k; e" |
  243.                               (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));
    + X, f8 D6 K7 @2 _9 p
  244.   }
    8 |  o! r! ^; e8 x. s! h5 `: \
  245. % ?- l5 _& {2 M/ ]  U
  246.   if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
    6 [5 U% O% x' R1 Q, y, t
  247.   {9 p* j) I& v" s7 e/ I, q
  248.     /* 设置Tx FIFO 或 Tx Queue 操作模式 */! t' a- F) E: h$ ^" [0 N
  249.     SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
    . n2 n4 V8 j2 Y% E
  250.   }5 U4 _3 K6 @# x! o

  251. / c( ~: `  ]/ ]& r; i, {% {! V
  252.   /* 配置Tx element 大小 */+ t0 w; ?& o3 l- A! n) d# w; w
  253.   if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
    ; y  l7 T" e4 V: m- H8 l. I
  254.   {' v0 c" d% d5 W
  255.     MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
    * @8 U0 t) `3 u6 D2 i" S* v
  256.   }
    & z% s9 t( c6 P* ?) e% W
  257. 3 J, V  F8 o: P8 d
  258.   /* 配置Rx FIFO 0 大小 */
    : |2 L. O6 Z& d% |# ^
  259.   if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)" t/ ?$ ]* z8 P! _7 C- l: k* ~
  260.   {, s* U" j2 `" `) {0 [8 x  M
  261.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));
    3 N) u5 {0 D* h8 Z
  262.   }
    ' i; c* v* h1 d& v3 t

  263. , u& @9 x7 c' W
  264.   /* 配置Rx FIFO 1大小 */
    * A, L- r7 A9 `0 m" V7 n
  265.   if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)+ M) h9 q' A  l# _
  266.   {7 j  Q$ u! _; X- m% Y6 X5 d
  267.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));
    4 l6 J, L) T) u9 e$ {; m( a' a
  268.   }
    - x. J0 ~* _2 n; ]" I! M
  269. 7 J/ {0 R4 ]* |2 \. f3 j
  270.   /* 配置 Rx buffer element 大小 */
    4 v  b! H, z1 [4 \' j9 f( S" ~% d$ c" Y
  271.   if (hfdcan->Init.RxBuffersNbr > 0U)& q/ D( R, l, D  K- p8 a" \
  272.   {# T8 B3 Q& e8 y9 g; Q6 `7 {" A
  273.     MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));- Q: t4 o8 X4 c# T) s& m0 _
  274.   }% c; L$ S( I3 d5 A2 U- T+ v" m* R, x: o

  275. , R- H0 ]) @' n" g8 g1 w% h) z8 H
  276.   /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init
    6 X1 t- O: ^* q& g5 `2 W
  277. 后调用HAL_FDCAN_TT_ConfigOperation */, e9 {4 l( V% f7 S- _" N
  278.   if (hfdcan->Instance == FDCAN1)
    & U- A1 c8 @* B
  279.   {
      A' O3 k. v6 t! g
  280.     CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
    : G1 h2 S1 [& [1 Q: H
  281.   }
    $ J4 T) ^; P  @7 u

  282. ' {. n! W9 a. v0 T0 u. \+ z
  283.   /* 初始化Tx FIFO/Queue */
      h" t% k4 {, c- ?9 [- o! s
  284.   hfdcan->LatestTxFifoQRequest = 0U;
    8 x) n+ U5 b4 \$ a' l- }
  285. ; S# e" {* ^5 R& M/ G8 F
  286.   /* 初始化错误码 */
    6 h' z$ X% |, F- [# P. b# g
  287.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    0 p* q, t# q) Z3 B( v6 Q; E  Q% |
  288. , q3 C8 h3 r6 [' w3 h: j. R
  289.   /* 初始化FDCAN状态 */
    4 c- O6 p) q) x" c
  290.   hfdcan->State = HAL_FDCAN_STATE_READY;
    $ \! x# R( |0 P9 \3 ]

  291. 2 U- c5 o7 ?- M4 F, r4 u( ]
  292.   /* 计算每个RAM块地址 */* n7 Z$ E9 ?& J+ E
  293.   status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
    % n& i( t" i5 G0 g4 L; J& h8 Q# `; W
  294.   B$ l* E0 `8 o9 R6 k4 I- q2 {
  295.   /* 返回函数状态 */
    1 e/ t. E% u5 X% S6 w6 u
  296.   return status;7 M- b) _: `6 B6 V
  297. }
复制代码

0 P8 X( Y; S& @, ?函数描述:
. P; f4 _4 J/ q; r% i# L: _0 r+ I9 v$ x6 p  O- c4 ?7 _
此函数用于初始化FDCAN。
" ^2 d* ]0 C- u# x, X+ g. C* ~; {  m# ~
函数参数:
- m9 i/ p. B! l" n, b2 W: ^
. w) ~' P1 h8 x+ x  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
9 Q; j  L7 q8 R  J  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
0 V- A8 c: b9 t注意事项:
( e1 D& h9 o& T* [; C3 b1 U8 h# g2 z' z8 d& d; g
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。
# Q9 T& p2 e( A5 i5 K! S1 J5 M如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。9 v6 L  w7 a: m9 |7 s! e( ?' y
对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET  = 0x00U。
) W: F' y8 G; t+ u4 Z4 |/ S5 c
解决办法有三3 W$ m) o; k& v
/ M, t: }7 S( |0 z- g$ _
方法1:用户自己初始化FDCAN和涉及到的GPIO等。( s6 Y! j0 g& `# x; y) q$ K( Y2 W

5 S. d) [" i% ]6 s# c# x3 B* e7 P方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。" o* D, T! j' `

2 n0 K4 V$ s& X4 E' e. e方法3:下面的方法& @( N) h( w9 C
1 z7 K0 i" g* ~! ?
  1. if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK)4 [! v4 C0 N9 M  `( W7 y4 O
  2. {
    + @/ j/ a+ A# ^+ K6 E- b4 t
  3.     Error_Handler();0 R# A- ]1 G, y! z
  4. }  
    ! C$ P- `: b/ g, [/ M! ?% G- ?
  5. if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)
    : d' r. M. D* j4 H' l, h9 t- N, c
  6. {, I) H. L. d& B' _# E) R3 _
  7.     Error_Handler();! a: m( m" L) B7 E( l9 F! \
  8. }
复制代码

/ K" m0 n. Q. _使用举例:! I) G* J  t7 H
+ U, G3 }, A. _% @0 F+ p+ j: K
  1. FDCAN_HandleTypeDef hfdcan1;
    2 w% g' p! d. A
  2. ) [% T+ V" ]% Y% ]8 _1 K
  3. /*
    3 M* M( Y$ ]1 l7 g  H
  4. *********************************************************************************************************1 O- O9 ^1 K7 W' \& s6 e% F  o  R) r+ W
  5. *        函 数 名: bsp_InitCan1( E& S: |7 s+ O" @3 R& C+ Y/ K
  6. *        功能说明: 初始CAN17 s) U' ~/ p' X  K* T4 {6 B
  7. *        形    参: 无* Q. l9 T; q% X6 q& j
  8. *        返 回 值: 无3 k$ j9 q5 Z/ W
  9. *********************************************************************************************************3 i8 E$ f8 L1 `0 W! k
  10. */% e: g& {# R. @0 V
  11. void bsp_InitCan1(void)
    4 z  v# Q$ ?: o3 {
  12. {         
    * T! r  x& c# X! M# E, W. i+ J+ n
  13.         /*                    位时间特性配置
    & e) h  H- g3 R% w
  14.                 Bit time parameter         | Nominal      |  Data' Z  N, w, P) W0 H4 i+ ^6 t+ n
  15.                 ---------------------------|--------------|----------------
    # k" L7 |- t% _2 s7 s* \. f/ Y, e
  16.                 fdcan_ker_ck               | 20 MHz       | 20 MHz5 h) A- i# l4 ]% x4 h4 e5 O6 v
  17.                 Time_quantum (tq)          | 50 ns        | 50 ns
    6 m  M2 y6 y% m8 k$ N
  18.                 Synchronization_segment    | 1 tq         | 1 tq5 x' U' t1 S9 w1 Q, u, y& ?2 L
  19.                 Propagation_segment        | 23 tq        | 1 tq% w0 _# a& J. I
  20.                 Phase_segment_1            | 8 tq         | 4 tq* J# g7 M4 t6 h6 ?: C& u4 ~
  21.                 Phase_segment_2            | 8 tq         | 4 tq
    0 S. S* R" m( d  T/ X$ ]' B
  22.                 Synchronization_Jump_width | 8 tq         | 4 tq
    " Y6 u6 R! V" r+ I5 K4 r
  23.                 Bit_length                 | 40 tq = 2us  | 10 tq = 0.5us
    ! z; @( Q$ z$ W+ Y  W4 L
  24.                 Bit_rate                   | 0.5 MBit/s   | 2 MBit/s
    " l3 s# ?- }( Y4 m  \
  25.         */1 N8 G: Z+ C- h( z& F" A) ~  t3 Q
  26.         hfdcan1.Instance = FDCAN1;                     /* 配置FDCAN1 */            
    8 p9 v& p& ~2 `! I  I1 z# N
  27.         hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */  ( E1 v& @2 d5 k+ o+ o
  28.         hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;         /* 配置使用正常模式 */
    - P9 D( ]7 j* k" V
  29.         hfdcan1.Init.AutoRetransmission = ENABLE;      /*使能自动重发 */
    $ L( \' d( V8 `3 q% f4 d, q- t
  30.         hfdcan1.Init.TransmitPause = DISABLE;          /* 配置禁止传输暂停特性 */8 Q' B- N4 Y  E3 ^: R# S' M$ z
  31.         hfdcan1.Init.ProtocolException = ENABLE;       /* 协议异常处理使能 */
    ! n6 s0 A9 k& `; K! q# h
  32.         
    ' @9 }3 V8 m8 v8 E
  33.         /*
    & e1 y9 q) J' Z( P. p
  34.                 配置仲裁阶段波特率
    # ?6 |3 s: {! O. T0 w0 M3 h
  35.                 CAN时钟20MHz时,仲裁阶段的波特率就是7 ]. |7 b/ W" a
  36.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps        
    # s; T  K/ w+ y5 u9 K) T
  37.                 ) ~# V9 O% D9 O$ I1 g9 j
  38.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
    / n: F  J3 }& {
  39.         */" B" M; U& C5 _7 _( L3 z0 s
  40. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */* _# I2 `0 X) U( n
  41.         hfdcan1.Init.NominalPrescaler = 0x01;
    / v" A1 Z- ~5 T$ ^+ b9 ^

  42. ( E" v( f$ o+ n7 R; ~: n
  43.         /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */
    1 n1 V  }. Q- Y" u
  44.         hfdcan1.Init.NominalSyncJumpWidth = 0x08;
    / Y$ y- X( E% N4 X1 _

  45. ! l8 y7 j2 M8 ^% A2 `3 v( k9 k
  46. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */3 t0 H  H2 }: Q7 M' n! j4 B
  47.         hfdcan1.Init.NominalTimeSeg1 = 0x1F;          # [0 T# H2 W( v6 {
  48.   i5 c! C# Z1 k* m5 t4 G8 A3 ?
  49. /* 对应位时间特性图的 Phase_Seg2 */& Y9 q' O7 v2 t; O/ j& `2 C
  50.         hfdcan1.Init.NominalTimeSeg2 = 0x08;     
    / s0 @! D3 S2 p: i' l. x4 Z. ]5 m& Y

  51. ' Y: e. r1 `, J& _# `

  52. & W+ u* b; v, o
  53.         /* 7 t5 [* |2 }+ Y% U5 ?
  54.                 配置数据阶段波特率
    6 k/ p9 C# j8 ^5 l0 S
  55.                 CAN时钟20MHz时,数据阶段的波特率就是
    - S- }, k2 C  V1 \2 r: H
  56.                 CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps
    2 ?& h9 t9 j1 Z. j
  57.                
    1 Z# D9 Y5 ~, P) i  S0 ]
  58.                 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2
    4 k7 Q7 r" ?2 T, t9 S9 {7 e
  59.         */
    $ d+ _  s) }7 Z. N) p
  60. /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),4 e2 W0 \6 `% o. k
  61. 范围1-32 */
    : d7 O1 Q% ~7 L1 h
  62.         hfdcan1.Init.DataPrescaler = 0x01; 4 S) a% q9 b% {" Q) @# Y7 D; N
  63. ! g+ J9 b1 _9 u, ~$ _( w& P
  64. /* 用于动态调节  Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */  j+ l" G4 u0 ?  l( T" u7 z1 b: B* \+ n
  65.         hfdcan1.Init.DataSyncJumpWidth = 0x04;  5 u; r3 m% D) i0 K- M* ]$ t: w7 I

  66. 9 |6 `3 |* O! t# b, I2 M8 d8 A
  67. /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */
    0 J% i% h1 `6 @, {4 a
  68.         hfdcan1.Init.DataTimeSeg1 = 0x05;
    ' j3 Z& y2 _! r) `2 ^8 I( I
  69. ; t2 z% b( V! _; A
  70. /* 对应位时间特性图的 Phase_Seg2 */                * ]2 ?- }: K1 o! f5 O
  71.         hfdcan1.Init.DataTimeSeg2 = 0x04;           
    0 v- t8 W+ d4 h  L: n
  72.         
    & I9 Y  P+ t3 o. ~" H1 {. M
  73.         
    / b4 r& z1 ?7 h2 V4 [5 t0 n
  74.         hfdcan1.Init.MessageRAMOffset = 0;      /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */
    , M* s5 ~  ?$ E: u+ Q
  75.         
    ; i! F0 A* I, A# U: ]! }- x
  76.         
    % I% N1 U$ u  F
  77.         hfdcan1.Init.StdFiltersNbr = 1;                                 /* 设置标准ID过滤器个数,范围0-128 */      
    # ?( ]; B1 c* T5 n; `' R7 G' ~
  78.         hfdcan1.Init.ExtFiltersNbr = 0;                                 /* 设置扩展ID过滤器个数,范围0-64 */   
    " l$ v! ?; M9 ~8 w
  79.         hfdcan1.Init.RxFifo0ElmtsNbr = 2;                   /* 设置Rx FIFO0的元素个数,范围0-64 */  3 A. `. Z% [' q: F
  80.         /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */   ( {" y8 {+ y  z0 r2 G
  81. hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8; 1 s0 k/ }( ~- q: O+ d) y
  82.         hfdcan1.Init.RxFifo1ElmtsNbr = 0;                   /* 设置Rx FIFO1的元素个数,范围0-64 */
    ( M9 ?+ u" b" `2 A
  83. * j' @- c5 S7 b
  84. /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */        
    4 J8 g1 y4 d8 A+ M/ l
  85.         hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8; 8 B, O9 Y- i8 i0 h
  86.         hfdcan1.Init.RxBuffersNbr = 0;                      /* 设置Rx Buffer个数,范围0-64 */" B0 q  ?- X8 y8 z* J( }/ n
  87.         
    & i# u; Q/ |. g) V- {
  88. /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */4 M) ~' Q8 l/ D7 H
  89. hfdcan1.Init.RxBufferSize = 0;                             
    / ?. y# W2 W' K. x

  90. ) S/ d* K, r: [& X( @  Z) U

  91. ; m& j+ x# w0 u8 \2 s: _
  92.         hfdcan1.Init.TxEventsNbr = 0;              /* 设置Tx Event FIFO中元素个数,范围0-32 */        / _2 R& y7 b; J4 M2 C, A
  93.         hfdcan1.Init.TxBuffersNbr = 0;                 /* 设置Tx Buffer中元素个数,范围0-32 */
    : v# c+ ]0 j" p& j3 S8 c3 K
  94.         hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */
    7 p0 z8 ]% t( c7 d( a& r- P$ P: {; l
  95.         hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */; M+ N8 |. j5 h/ [& e
  96. * P- k" b( d* R; |4 J' Y8 J
  97. /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */; S! n( S* ?0 `9 A9 M( v
  98.         hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;          ! ~- s: L6 U( D9 B3 b% W) {" h
  99.         HAL_FDCAN_Init(&hfdcan1);2 A' ]- t( g5 U6 o' L
  100. 8 x8 D# j- T' T3 c2 a

  101. # K" n0 O" [; ]  a9 y9 o4 z* R
  102.         //省略未写
    3 [. H( A$ U: L# i
  103. , r( x8 G3 b) D
  104. }
复制代码
! ^3 l- r3 P5 p1 y" a; [
91.4.2 函数HAL_FDCAN_DeInit
, b  \/ m/ e9 B' [/ t函数原型:( i; K4 e7 u+ a; Q1 a
: R/ x7 t# I, @0 o1 K# M2 q
  1. HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)1 F6 _$ ~6 N5 e  y4 c
  2. {! X  v0 j4 J; l) Z
  3.   /* 检测句柄 */
    0 d/ ~+ E1 O* A( m4 M9 h
  4.   if (hfdcan == NULL)
    , S# p2 ^7 H) \; g6 m7 a
  5.   {' A) q8 \# Q- q4 W
  6.     return HAL_ERROR;- B" U9 t: A; u6 q4 g2 E5 D$ W1 u
  7.   }1 u5 K! C- w5 u9 n
  8. 4 S4 r. n. j) n  V( \
  9.   /* 检查函数形参 */
    1 y" F( K; m$ v( O: Z" |3 d
  10.   assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
    " C3 t3 V7 X6 c
  11. 5 K7 l5 l* d% @
  12.   /* 停止FDCAN */3 i& P4 g  g/ N! i1 R- v
  13.   (void)HAL_FDCAN_Stop(hfdcan);
    3 j( X/ ~+ ], [* }* O

  14. 9 }! z* I: v, ^* _
  15.   /* 禁止中断 */
    : y1 A: y. ^- k* Y! M& i. L# T
  16.   CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
    8 }  z! i3 c) D: B& ]5 ^: e

  17. 3 m& k1 Y, f! c0 E- g
  18. #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1+ k) M8 o- ?" Z8 c! H, V( h1 y
  19.   if (hfdcan->MspDeInitCallback == NULL)
    + [+ J3 w) q6 |, o/ W
  20.   {; t' q  R% l# m; |4 X( ?# V6 E+ }
  21.     hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
    % q/ U5 Q0 b* k
  22.   }8 a" Y) z$ j# l' X9 k9 z- r/ ~
  23. ; d; }" w% y7 v$ |% O  ^
  24.   /* 复位底层硬件,如时钟,NVIC等 */" l" ]/ o* F% B( h/ `- i  f6 _/ x
  25.   hfdcan->MspDeInitCallback(hfdcan);
    4 S& T. K: q) E. A$ J4 p  f
  26. #else  K. _5 G8 p0 g! f1 H$ h5 s7 R
  27. /* 复位底层硬件,如时钟,NVIC等 */. z0 L! p' [9 @' Z  N- k  O3 e* s
  28.   HAL_FDCAN_MspDeInit(hfdcan);+ x1 b( @' C# U% `: c
  29. #endif
    $ `3 s- e' Q5 b3 J. s5 Y, e4 x
  30.   m5 a* n3 b" l
  31.   /* 复位错误码 */! y. }% n# y# B  ~& R
  32.   hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;
    * V" q( `6 e) H. j
  33. / Q6 f! x+ c; ^5 l9 i; N1 L
  34.   /* 设置FDCAN状态 */
    ! k( {) h1 L2 E5 F! Z
  35.   hfdcan->State = HAL_FDCAN_STATE_RESET;
    ; A: \) N9 b; c4 P
  36. : {4 {5 }2 G9 i
  37.   /* 返回HAL_OK */) u; B8 K' a9 ]- N. v4 j( p1 D
  38.   return HAL_OK;
    - b3 C! h. [7 W' q, [  h3 T& Y% B
  39. }
复制代码
- Y( R% p) m7 T
函数描述:2 H- p) t) x6 |8 |+ p- ^9 i1 ^
8 i6 u# A3 f* H5 @0 ]
用于复位FDCAN。
* R& x, `; E( B* p$ `, a% `4 L! Y& I& z1 q# ~4 f, Q/ O
函数参数:" \) ^) B' ]2 {" q+ Y

: m( r5 D! n0 L. S! [. @4 q, o  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
" E5 j% J, b% N2 G/ H  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
/ ]9 u# H0 l2 N# D! ?: q91.4.3 函数HAL_FDCAN_ConfigFilter5 x3 z1 D! y3 B' A% q$ Q, v  r3 n5 I
函数原型:; V; f/ J* ]" i% V$ i2 w
, B" b  _! \) t0 ~4 m- r% v
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
    0 h4 M# M" C. B. B) V. q* T0 ^
  2. {
    + V4 i+ g' ~' O, b7 |
  3.   uint32_t FilterElementW1;
    7 G% q( N& r8 j/ ]/ \/ S8 b: d. x
  4.   uint32_t FilterElementW2;: E/ Y" }+ N/ I& R% g: U% d
  5.   uint32_t *FilterAddress;
    ) ?8 ]5 I' S1 i( G5 _% C7 P/ I, [6 Q
  6.   HAL_FDCAN_StateTypeDef state = hfdcan->State;' H! z7 ]6 _# w2 z# q  k3 z

  7. 9 t) g; |" l) a& m
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))' U& E! j( e; N1 G1 j
  9.   {/ }  R& R5 T0 u9 k( X4 S2 M2 w" T* Y/ ]# R
  10.     /* 检测函数参数 */0 u+ d! T: M) i. J4 W" C4 V
  11.     assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
    ' `" `% a; ^, P4 u
  12.     assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
    ! A/ V$ j0 q8 }& a
  13.     if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    4 b. t( g; }4 Q4 |* v
  14.     {( X" U" x5 \& e9 l+ |4 i
  15.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));& m! _' X2 X3 V  G" s5 U
  16.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));, E" f3 I4 T+ g1 }
  17.     }# m9 o9 J, t& {- Y; r0 o
  18. , I- d9 r+ H0 i/ s! K9 K
  19.     /* 标准ID */
    6 b: r7 O  N3 A, i: M! t# X& b
  20.     if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
    2 Z+ r9 Y6 _! V. c
  21.     {
    ) r! @6 D7 |& k- r; g
  22.       /* 检测函数形参 */
    , D; u1 r: h) R: L/ o7 n
  23.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
    . j6 x1 T4 Y/ g2 C
  24.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
    8 ^+ g8 l- Y- I4 w8 t) Z$ ^3 ^1 `
  25.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
    3 [" p. x7 l. O3 B- y. p: a
  26.       {+ o5 p  m# K! B0 C1 [# t
  27.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));" G# Y3 F2 C6 M# j; m( w
  28.         assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));
    $ J8 D5 o1 b6 G2 x  \
  29.       }
    / `8 a, u. w! F( H$ g1 I

  30. & [% H1 M+ R8 O# k
  31.       /* 构建过滤元素 */
    3 w* C% r. L( d, k
  32.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    $ y, N+ k8 V4 m) P/ p  ?9 ^- x
  33.       {
    : }# D# s! B0 B. \; l
  34.         FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U)       |' m1 G- [- D  g# Y
  35.                            (sFilterConfig->FilterID1 << 16U)       |
    5 m4 T6 t* }* M# ?$ ]$ R
  36.                            (sFilterConfig->IsCalibrationMsg << 8U) |  k$ f( L) N% g, B
  37.                            sFilterConfig->RxBufferIndex);
    ; U. {" A$ w6 I8 e+ E  I
  38.       }
    : R+ R% X: u2 b8 R8 P& S- t
  39.       else4 x. H( X4 N/ {# v8 u5 q
  40.       {0 L' F/ |+ F, H6 ]  {
  41.         FilterElementW1 = ((sFilterConfig->FilterType << 30U)   |* ~5 b2 y& S% |* \
  42.                            (sFilterConfig->FilterConfig << 27U) |- l0 h8 ?! @8 N
  43.                            (sFilterConfig->FilterID1 << 16U)    |
    7 H7 K! J8 r& n8 p: s: G9 e
  44.                            sFilterConfig->FilterID2);
    ( P! u9 k4 _4 f. S3 h) I6 T) p5 o
  45.       }
    ' S: J. z$ x0 r4 ?" r

  46. 4 K6 A7 s  G$ f; `* t( `4 _1 m
  47.       /* 计算过滤地址 */
    - l/ z- h' {4 U9 s
  48.       FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));
    ( O+ _$ l' o7 R% Q: Y
  49. 8 s1 _4 R! p/ @4 v, H
  50.       /* 将过滤元素写到消息RAM中 */' P- J2 j6 P+ ]9 o1 n; r( F) d
  51.       *FilterAddress = FilterElementW1;
    5 ^/ C! y) n9 b7 b1 Z
  52. }7 h# X8 U  x: O/ }' T5 o' h) L1 V
  53. /* 扩展ID */0 p. z: i  L, N- M* Z  Z
  54.     else
    ; z; r6 r+ R! V
  55.     {
      l" }& k; ~: T4 u: V: ^' I5 r1 r4 u
  56.       /* 检测函数参数 */
    7 d% G5 W/ E1 g- @3 {/ L9 S
  57.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));$ L+ Y- B5 N) B/ ?' H! O/ \
  58.       assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));* K+ i9 z0 _! {  G* D  y2 C- F; t
  59.       if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)
    7 r7 `0 Y$ J6 K1 f9 @2 C1 j
  60.       {: N9 R) q) ^' l1 x! m/ {6 M9 Y# S
  61.         assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));
    % D, a) G& Z4 `+ A5 H) l
  62.         assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));
    , L; ~  {! @/ M0 _' }7 `1 D# A
  63.       }
    ) T  K3 A5 @0 e

  64. & ]! ]( b  M- v4 w7 T: ^
  65.       /* 构建第1个word的过滤元素 */
      E: \! W" f6 O3 M
  66.       FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);# }3 [9 O' R! S
  67. 8 ^+ l, a4 H) l5 x1 O
  68.       /* 构建第2个word的过滤元素 *// F; T2 I! o3 L# v: n
  69.       if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
    , H* D, B* i$ A6 j
  70.       {
    2 z7 f& E! i( \' Z
  71.         FilterElementW2 = sFilterConfig->RxBufferIndex;
    4 M+ Y: {) x$ w) G# O" e
  72.       }! Q- o( S! H" F
  73.       else
    2 k; |  n' i7 g8 N( T1 \
  74.       {6 |& o- o1 A4 Y# j& H. t( s* m
  75.         FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);0 |  b6 U  Y# Q/ v% R5 T
  76.       }3 ~: _2 A/ o3 c# u# r+ |
  77. # z! `1 {  |- l0 v% ]" |) g) Y
  78.       /* 计算过滤地址 */' ]) e" X  s3 D( i& A& b1 U
  79.       FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));7 g* n" A+ X/ e3 k& h8 Y
  80.   a5 K+ u1 R  H) z* M% P" J
  81.       /* 写过滤元素到消息RAM */
    7 Z+ i/ [" O( s$ b: e; p
  82.       *FilterAddress = FilterElementW1;6 F! C$ f& |/ }7 p
  83.       FilterAddress++;, h; g' C/ ~6 P% G4 P& \7 C
  84.       *FilterAddress = FilterElementW2;7 |9 m/ x: E  D7 J0 @
  85.     }
      B; n) o, a$ N# ]/ S2 r

  86. * L& e4 I. b1 X8 y7 p* X
  87.     return HAL_OK;' T# a' Y, S) S
  88.   }
    ' @7 Y+ H4 ~4 }* J" k! M( w$ p
  89.   else
    ( r' u' C6 N( l; f( D  h- d
  90.   {/ F2 P( R% I: G% O7 Z! M4 P  ^
  91.     /* 更新错误码e */$ A% M: p! E) {, T3 z2 \
  92.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;) X! l% F" C, M9 n4 B1 f& F

  93. + e$ g/ p- H1 p9 N0 T' T
  94.     return HAL_ERROR;% U% G% b9 V! S# c$ i, M8 K
  95.   }
    ! h6 `  y% W" A' {0 |4 ~
  96. }
复制代码

( B7 \% A7 `, T( W8 N函数描述:* J* ^8 ?0 r& f" f
+ ^" ?# G. O' Q" H& Q/ P
此函数主要用于设置FDCAN过滤。7 x; S; Z& n; Z7 f4 ~
1 ~' w. d/ b% n' u: R
函数参数:+ d8 z$ ]5 }, f  w7 B! d
2 l- U( G3 m$ _+ C2 U
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。  X6 {) d$ y6 }& [
  第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。$ p" U! x! A( V' u* ?
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。6 d1 S8 E9 d0 J- B
使用举例:
2 b+ i0 G# `' L1 `0 M/ J& n9 E% m( {, m" U
  1. FDCAN_HandleTypeDef hfdcan1;
    + D9 F% W2 Y: {0 y

  2. 4 r+ Q% V% z5 G! K9 S
  3. /*
    " e9 ^( i; A; x$ v
  4. *********************************************************************************************************
    2 W: {1 D) T) |* a2 i( a" k, C0 W
  5. *        函 数 名: bsp_InitCan1
    * |4 S, q) y7 ^9 E
  6. *        功能说明: 初始CAN1
    7 S8 ~- M6 J  b  b$ _  C2 ]
  7. *        形    参: 无
    7 q0 f, G; m- c1 [% h  y
  8. *        返 回 值: 无; Z* L& ~7 c3 g6 K
  9. *********************************************************************************************************
    ( {1 ^& M3 q: T4 A
  10. */# v* y4 b. k/ [; `6 K
  11. void bsp_InitCan1(void)
    ; x% N7 D3 o  z* m  u7 s
  12. {         
    & j9 f' T* C/ S5 |2 b7 s: t5 m
  13.         
    3 Q; K& D3 q- H" \( E
  14.         /*
    * r4 d+ c3 I; j! @
  15.                 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。9 \' J3 @- s0 m
  16.                 FilterID1 = filter+ I+ s/ K# J4 K" L, o
  17.                 FilterID2 = mask
    # _! q$ u9 D8 T0 E$ D! A, H
  18.                 5 f  J% ~' s! k9 V- t
  19.                 FilterID2的mask每个bit含义
    ) u2 |5 `7 X7 R" L9 V/ `* Y; k
  20.                 0: 不关心,该位不用于比较;  f) d! j1 {- x
  21.                 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。' J% T: O# B% `/ S6 I7 s/ q
  22.                
    - B( Z( ?5 X9 l* l: f
  23.                 举例说明:, {; W+ Z' j9 w- n  b8 }
  24.                 FilterID1 = 0x111
    ' F7 s6 L" y, ?% g: o
  25.                 FilterID2 = 0x7FF
    & n+ A. i+ \2 ?: |" \# L* ^
  26.                 表示仅接收ID为0x111的FDCAN帧。6 p( F% G' W# x' t6 `  m
  27.                 , r+ f- l: K" R2 |3 N; L7 C) ~4 P5 `
  28.         */
    + B; ]& A& ?1 `7 ]
  29.         sFilterConfig1.IdType = FDCAN_STANDARD_ID;              /* 设置标准ID或者扩展ID */- `; W% Q8 g+ I. F0 N# O/ m
  30.         /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
    # n' X$ b, G' [- o/ d6 H
  31. sFilterConfig1.FilterIndex = 0;                                                   4 w8 c1 y# X7 t/ T7 N
  32.         sFilterConfig1.FilterType = FDCAN_FILTER_MASK;          /* 过滤器采样屏蔽位模式 */3 o$ \6 k! O& p$ q  I' I
  33.         sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;  /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
    6 }8 G0 u1 y) I+ B3 W- ~) R
  34.         sFilterConfig1.FilterID1 = 0x111;                       /* 屏蔽位模式下,FilterID1是消息ID */
    $ v) A1 @7 g/ }. u0 ~) @+ [
  35.         sFilterConfig1.FilterID2 = 0x7FF;                                         /* 屏蔽位模式下,FilterID2是消息屏蔽位 */
    ' \. S6 e! ^0 D" \
  36.         HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1);      /* 配置过滤器 */; Z  \2 \( X  u4 o

  37. + F9 ~- e) N+ F+ Q) K: f* k1 f: D
  38. }
复制代码
6 m% b7 J$ T5 B1 o
91.4.4 函数HAL_FDCAN_ConfigFifoWatermark& Y3 x  G2 i# @/ G4 L" F- c5 j
函数原型:
* Z9 g6 D' m6 X0 P' j4 m" j! G# D' A& w& [. S# U, w
  1. HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)' z- f, q2 C0 m4 j! i+ L6 ?3 J
  2. {
    6 y5 Q5 Q( }6 H- f* a8 Q$ l1 L, y& N
  3.   /* 检测参数 */
    / `, z' ^, S. z. _0 s; F- C
  4.   assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));
    ( x& I( t9 M. k! \$ [( f
  5.   if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
    8 x9 c; x1 w9 S. E& R' U
  6.   {4 m! C* S4 }, E" g7 R6 Q
  7.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));
    & M7 @' b6 q/ }' k: z3 _  `
  8.   }
    / L* @6 J, g6 d0 z! j' S
  9.   else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
    , g- l' k/ @1 I! m6 v7 t( g6 e
  10.   {
    ( Q6 Y' H& ?4 ~* o0 Z
  11.     assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));
    ; v2 m- q  y& {. H4 ?  F
  12.   }( b, R$ D1 ~+ f% M; S

  13. 2 |/ z  s! e6 w7 N7 ~
  14.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    # Z6 x1 U7 G9 ^; Y+ `
  15.   {
    $ q% `- L" Q$ \. M: F6 X( H
  16.     /* 设置发送事件FIFO */
    + P+ E7 K1 t9 [% ?" e
  17.     if (FIFO == FDCAN_CFG_TX_EVENT_FIFO); ~6 I! C4 @1 I5 t2 h
  18.     {6 A" S$ F8 s1 I( v3 w
  19.       MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));7 g4 a& R: B- F3 f
  20. }
    ' m3 O3 m5 i4 `2 u5 Z
  21. /* 设置接收FIFO0 */
    5 P6 l) F" P& F" T
  22.     else if (FIFO == FDCAN_CFG_RX_FIFO0)' m9 _' A: r& ~% ]8 h/ H
  23.     {
    / P8 h6 M( z0 ^0 A
  24.       MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));. c1 N3 x$ l& `
  25. }
    - L3 j3 e3 R: k' B, c
  26. /* 设置接收FIFO1 */
    ! P) a! H2 f6 Y8 p1 E+ u2 K
  27.     else # O% }1 A" J! i! }( @  H- L8 G4 i# `
  28.     {% Q% u5 w; }8 P  P6 U
  29.       MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));5 k7 P' N7 @: c: f3 \: l( n
  30.     }" B- Z& m8 O, W( F* C3 ~. B
  31. ( G; h: {* y1 R" }2 E7 A- E
  32.     /* 返回状态 */
    " m2 [! u" _& J$ m
  33.     return HAL_OK;
    & V. e* ^, u3 j
  34.   }8 C# F3 N- B" c4 T, b) O2 x- ~8 f
  35.   else6 G# R$ O. G) S9 {& u/ \
  36.   {+ m  L& `* T8 l& _, y
  37.     /* 更新错误码 */
    ; S9 [( L/ {( V- K& e
  38.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;% {8 I" h. q/ B
  39. ) ]2 R3 _# y0 T( c5 |) z! @
  40.     return HAL_ERROR;( T8 ]6 l; P/ V' d4 N! @4 R% R  E7 o
  41.   }# {  a! Z5 w- F) X/ |1 w9 v
  42. }
复制代码

: i& M% Z0 \4 t" q$ v函数描述:
1 N# ]$ r; s- b, D+ s
2 s8 ^7 q; _$ \此函数主要用于配置FIFO Watermark  ^  S, T# W2 `, J4 o; t2 _
  p+ k9 s; I' @9 L  o
函数参数:5 v" R# e$ I+ K5 V3 J3 e8 o3 L
7 ~3 p, g' R2 D% v
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
/ G+ l( Q) o5 l/ m& O* E  第2个参数是FDCAN FIFO Watermark
# r$ p7 K, q! V4 `
  1. #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */- L% v) h; g* G
  2. #define FDCAN_CFG_RX_FIFO0      ((uint32_t)0x00000001U) /*!< Rx FIFO0      */
    ! p% h+ e$ k2 |! Z, S0 X- U, H' r, k
  3. #define FDCAN_CFG_RX_FIFO1      ((uint32_t)0x00000002U) /*!< Rx FIFO1      */
复制代码

9 v3 C# b/ Z$ X  第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。, I3 i2 V/ p9 r/ y
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 g, _* h2 S  F; L2 S7 K+ @8 ?
使用举例:
% j  R. {3 @1 B  A: e4 ^
4 n& ?) p! ?0 J" k+ |
  1. FDCAN_HandleTypeDef hfdcan1;3 O% e/ _# I/ B7 e
  2. ! H' ]) a% V3 U  t% L
  3. /* 设置Rx FIFO0的wartermark为1 */' P3 ~1 k0 k! R$ d6 F
  4. HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码

4 {! l, m" S8 o& T1 h91.4.5 函数HAL_FDCAN_ActivateNotification+ v" q" Z) L# I, I2 P( W% D$ D; t
函数原型:4 Z1 {% K+ u1 r8 o& o2 A8 `
! a; C  i- f0 M
  1. HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)9 u* P/ `) }" y* I: n1 l
  2. {
    ) c# ^0 z' J2 i. t/ y
  3.   HAL_FDCAN_StateTypeDef state = hfdcan->State;' h0 ~& r4 K9 N7 h! z& E

  4. , _. ?0 h1 Q8 Y1 A* W1 h; @- D5 H( G
  5.   /* 检测函数形参 */
      T" [' O+ d2 N  b, U
  6.   assert_param(IS_FDCAN_IT(ActiveITs));
    ' r7 y+ [! l) z" i/ _

  7. 3 x8 x7 F. S  F0 J
  8.   if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))- n) L& ]2 O( g/ ?: s) \) h
  9.   {8 W/ |! \* i2 X  [" b
  10.     /* 使能中断行 */
    , m9 v- X) {  A9 y1 T- K
  11.     if ((ActiveITs & hfdcan->Instance->ILS) == 0U)4 I( j! g- R  S, G5 G
  12.     {7 k) D0 @* v. `1 l1 V3 h4 V
  13.       /* 使能中断行0 */- \& w+ F. p3 P' V; o; r
  14.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
    8 E+ C2 S0 k6 y% T) s8 Z  f
  15.     }) v$ _2 F7 c1 p; U
  16.     else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs)
    ( Z; @0 k8 c2 G: M. D! L
  17.     {( K% i+ G. h+ l; g7 [
  18.       /* 使能中断行1 */$ c5 l* D6 y+ l. @1 b: K
  19.       SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);5 m# }1 O! D4 p$ }' q: _9 z) c
  20.     }
    ) ?& F/ [% V5 ~
  21.     else
    - A. q" I! f7 q; d3 @0 z
  22.     {
    4 @1 Z4 y# |$ E
  23.       /* 使能中断行0和中断行1 */5 Q6 a& Q. R2 h0 R( [
  24.       hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);$ R: r& M. V# e' S# [! _8 V
  25.     }
    ' m" _7 M# v% I3 Y! ^$ _  _0 d
  26. : S! y; H; L: ]+ S8 r: e- h3 k
  27.     if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)
    . u$ j1 D2 v4 e
  28.     {7 @7 [+ u4 _) `) L% U3 Q
  29.       /* 使能Tx Buffer Transmission 中断 */
    " C, p3 z+ X- `) p! V. S
  30.       SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);; y0 |4 z6 o3 w6 b
  31.     }, m, S) ?: z/ v" b" C( q
  32. 9 N" r0 n& B! A7 L
  33.     if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)
    - X2 P& p. {' |/ ^. R  W7 N
  34.     {3 u# n+ r# j. b. F- ~: r: J
  35.       /* 使能 Tx Buffer Cancellation Finished 中断 */
    + t" [# t% a2 N8 F" ^. N
  36.       SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);
    % p" m- D# v& Z
  37.     }$ a. t# A4 i+ y. b* c

  38. " }9 P# M5 w* c9 Z+ K# U* \! [
  39.     /* 使能选择的中断 */
    . L6 e# a4 w+ S: H- k- g( `) z9 C
  40.     __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);
    ) w( ?( [6 g' f4 i3 @/ B
  41. " c9 i& j% n8 y( l
  42.     /* 返回函数状态 */5 G9 D4 p7 k3 c1 F$ k. o
  43.     return HAL_OK;
    : Q6 Y8 D2 S. F. K: _
  44.   }
      G6 t. c6 k. y6 V5 m4 A1 i
  45.   else' M5 b& A/ J2 t7 F: c4 k
  46.   {, g0 x5 T0 N% Q( G. I& z
  47.     /* 更新错误码 */8 b+ M$ P- B; A9 m
  48.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;% Y$ |! G2 i( p& |3 U8 C% A
  49. ' N6 O5 y  R% |& k( p( n" {
  50.     return HAL_ERROR;5 k% _' B8 P7 c
  51.   }* U7 \- h; Q  S% C* F
  52. }
复制代码
5 A; N" Q6 O- }9 r+ L) u
函数描述:
8 j8 x2 Q5 E- r$ q# B) R; D9 E9 n' c" [1 a; ?" |
此函数主要用于使能中断。
  l( Z2 p. f' y2 ]3 l: ^
1 H1 I5 q' L0 N函数参数:
$ b! i/ u1 c6 \6 l# o4 J& p1 e7 R1 S: [
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
, I0 r2 p$ B$ A4 L  第2个参数用于设置要使能的中断,支持的参数如下:" w! M4 ?2 r1 l
  1. #define FDCAN_IT_TX_COMPLETE         FDCAN_IE_TCE   /*!< Transmission Completed  ; C" l7 z# r6 N
  2. #define FDCAN_IT_TX_ABORT_COMPLETE   FDCAN_IE_TCFE  /*!< Transmission Cancellation Finished       */6 I0 D! O( s& T$ j
  3. #define FDCAN_IT_TX_FIFO_EMPTY       FDCAN_IE_TFEE  /*!< Tx FIFO Empty                                         . _, W. H3 P' d# R( \$ M
  4. #define FDCAN_IT_RX_HIGH_PRIORITY_MSG  FDCAN_IE_HPME  /*!< High priority message received       */
    $ A& P! w+ s3 Y
  5. #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE  /*!< At least one received message stored into a Rx Buffer 4 H6 H# Q/ H( o6 s$ O5 g
  6. #define FDCAN_IT_TIMESTAMP_WRAPAROUND  FDCAN_IE_TSWE  /*!< Timestamp counter wrapped around     */" z# u: H5 A" y4 }8 b
  7. #define FDCAN_IT_TIMEOUT_OCCURRED      FDCAN_IE_TOOE  /*!< Timeout reached                 */
    % ?/ ^0 w& L8 Z% h
  8. . \: U8 b' S/ g# }( I9 ]
  9. #define FDCAN_IT_CALIB_STATE_CHANGED  (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed    */
    1 @+ F6 Z/ e, e- ~" X2 B7 O9 z
  10. #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred 4 d6 b1 ~9 c+ `; @
  11. #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST  FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost                 */( ~1 ~9 Z( f# e4 B  \
  12. #define FDCAN_IT_TX_EVT_FIFO_FULL      FDCAN_IE_TEFFE /*!< Tx Event FIFO full                         */# l1 E5 M+ o0 c0 B
  13. #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */
    7 n7 {1 E( j4 ?! {9 `  Q9 X' H; }
  14. #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA  FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element     */
    8 G8 H/ V" k& _

  15. $ q& B  k2 k& t+ ]" N6 p$ D
  16. #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost                 */; b6 r- X4 }6 [1 b
  17. #define FDCAN_IT_RX_FIFO0_FULL         FDCAN_IE_RF0FE /*!< Rx FIFO 0 full                         */* R  B; i5 p+ A- H
  18. #define FDCAN_IT_RX_FIFO0_WATERMARK    FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */& T0 Y$ q# O! t" e* O$ @
  19. #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE  FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0       */9 R! @4 g" C: Y( O
  20. 3 W% n6 T$ X. U
  21. #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost                 */( ^% E# ]8 H1 m( s
  22. #define FDCAN_IT_RX_FIFO1_FULL         FDCAN_IE_RF1FE /*!< Rx FIFO 1 full                         */! R4 V$ m9 F% F; }- h
  23. #define FDCAN_IT_RX_FIFO1_WATERMARK    FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */
    6 A4 x/ s" H4 d# u9 D" ?8 }5 _
  24. #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE  FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1       */; e$ N9 H0 }" T8 Y9 z( B
  25. 2 w! o+ ^4 l' N. `
  26. #define FDCAN_IT_RAM_ACCESS_FAILURE      FDCAN_IE_MRAFE /*!< Message RAM access failure occurred              * T3 g8 F. v( U  `
  27. #define FDCAN_IT_ERROR_LOGGING_OVERFLOW  FDCAN_IE_ELOE  /*!< Overflow of FDCAN Error Logging Counter occurred
    8 \2 {& s8 V! n0 G$ ?& b! Z% @# G
  28. #define FDCAN_IT_RAM_WATCHDOG            FDCAN_IE_WDIE  /*!< Message RAM Watchdog event due to missing READY  
    ( D2 F' f% {$ k5 S$ n% C
  29. #define FDCAN_IT_ARB_PROTOCOL_ERROR      FDCAN_IE_PEAE  /*!< Protocol error in arbitration phase detected     ' O9 L9 S0 n+ X$ U' I$ \
  30. #define FDCAN_IT_DATA_PROTOCOL_ERROR     FDCAN_IE_PEDE  /*!< Protocol error in data phase detected            + `' y" ~1 _9 ^1 V
  31. #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE  /*!< Access to reserved address occurred              # N% |4 Q1 ^, M8 `: J& D
  32. #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */5 c0 @, h) n$ x! f* h: i
  33. #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */" D& M' _" c/ p- n/ V4 Q' I: I
  34. #define FDCAN_IT_BUS_OFF       FDCAN_IE_BOE /*!< Bus_Off status changed       */
复制代码
8 O# Z. v$ L- H- r) ~
  第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:
# Y1 b5 U& L- n8 j
  1. #define FDCAN_TX_BUFFER0  ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0  */! f5 a$ d- i) P4 L- G
  2. #define FDCAN_TX_BUFFER1  ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1  */3 B0 @; @% [/ y" i. T
  3. #define FDCAN_TX_BUFFER2  ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2  */
    . `7 X$ a2 _$ ~2 s9 a
  4. #define FDCAN_TX_BUFFER3  ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3  */
    3 Z0 c' n$ S/ ]# C8 N$ r
  5. #define FDCAN_TX_BUFFER4  ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4  */. f1 _9 i( K# @% k5 x+ f1 m; l
  6. #define FDCAN_TX_BUFFER5  ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5  */
    6 y# \$ W3 a# ]- w/ b' W8 z1 _6 U
  7. #define FDCAN_TX_BUFFER6  ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6  */
    ! Z, h/ w2 r  Y& l4 [' j
  8. #define FDCAN_TX_BUFFER7  ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7  */4 ~2 U; F: |$ ~3 C+ W
  9. #define FDCAN_TX_BUFFER8  ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8  */
    % G$ }1 _( e/ c3 w" I! L: A. L1 Q
  10. #define FDCAN_TX_BUFFER9  ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9  */
    , G  E- x# O7 f
  11. #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */1 z# [& Z# N7 E  h; f8 S
  12. #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */: C4 ?1 Q! x% n9 m1 u
  13. #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
    ; j, ]. z( t- O8 V+ i$ e( B3 r
  14. #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */  P' p! Z: }4 a2 U; G+ v; [
  15. #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */
    1 b( F& w3 }6 F7 L
  16. #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */
      F9 F" I2 n0 }6 P( K
  17. #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
    2 C4 w- j/ V* I
  18. #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */) S( t0 i/ s' n5 U6 Z
  19. #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */
    1 x: c2 H3 ^! `( m
  20. #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */
    ; d7 B( l( z% x
  21. #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
    8 f! [" V4 M  F4 C7 R
  22. #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */
    - ~0 Q8 v8 b2 Z# p
  23. #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */3 q0 Z+ P5 M2 `
  24. #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */
    9 E6 A# T3 A2 P, Q. ]+ R* x
  25. #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
    5 q  P* D& {1 t
  26. #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */- k7 w; n$ C) [$ o+ O7 y
  27. #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */1 Y" n& I1 d! p# J' q
  28. #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */. @  @0 u& y: D" n# [: p
  29. #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */1 t! _/ K  |+ J" V- T* r
  30. #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */
    2 _! c; g0 p: K$ T3 V3 X# O, t# d  a9 G
  31. #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */  }. E. X7 r  A# P  |! B& v( }
  32. #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码
% O: X+ k! G. A% S, i, S% b
如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。
$ c8 k7 t: F4 @$ T7 h( t2 M
) e; w8 ^7 |9 Y& X/ V" _, n5 }* ^  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
9 b% Y% G0 M4 P+ v" V, D; z使用举例:, r+ ^8 p$ b/ Y8 N

% g  j# L% N3 i4 `" DFDCAN_HandleTypeDef hfdcan1;
8 l9 p6 I0 a/ O3 |% q4 W$ |- `0 _+ x
/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/) n/ O" N) p; t% s6 }& E% U
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
& H* j& Y) J  D8 a( X/ U91.4.6 函数HAL_FDCAN_Start( e' \- r8 V' [4 ?3 Y( t/ F4 e+ R
函数原型:
& s; P* ~8 z, S$ ~& o9 w4 q7 t0 O7 E
  1. HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)1 p# A, q. V: }$ A
  2. {
    $ W% N& s" M% M/ m3 Y
  3.   if (hfdcan->State == HAL_FDCAN_STATE_READY)
    9 Y3 ^+ N+ X  v
  4.   {
    1 g; s+ P$ r6 r' s9 n3 j; q# \7 A: N
  5.     /* 设置FDCAN外设状态 */& l8 k0 k# n/ K2 ~5 ~# U4 I
  6.     hfdcan->State = HAL_FDCAN_STATE_BUSY;
    4 @6 |& E# p8 k

  7. - a  V' |* N5 f  ^/ |; h, }# g
  8.     /* 请求离开初始化状态 */
    / v- r( P- K" Z4 }% z" h6 W0 X4 L* [
  9.     CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);  E" f" {1 @6 Y1 A: Q, V: U. r
  10. 7 J% q) S5 R* ]' y) J. d
  11.     /* 设置错误码 */
    ( Z! \: c4 L% n* |, ]# `& S
  12.     hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;2 }6 b5 N8 q, o/ _8 ~# {
  13. 6 }+ L/ Z6 q4 n
  14.     return HAL_OK;+ k% m, T8 ]. K2 E5 g4 B# G. \" i+ m
  15.   }7 I' t9 z  G* m" }1 G$ m
  16.   else) x1 T* g! Z; \7 m# z) I
  17.   {" g* T, q, U/ d' \# V6 `) x" ^
  18.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;8 @6 o  o* g1 `  ?; k# Q
  19. + I* |1 |; j, D" [( o! s; w  {
  20.     return HAL_ERROR;1 L: v! t- ~- g& l3 M
  21.   }
    0 o+ d7 v$ ~. z4 L0 G+ J) s8 I
  22. }
复制代码
7 o2 }  g$ {! N0 @) ^; p0 w9 i* `
函数描述:$ g$ D% X+ N4 l/ e
  g4 @/ v$ v, a) }+ s/ X; w2 F. n
此函数主要用于启动FDCAN。, A. \4 u: W2 I

2 @7 i* }4 T' o4 a7 i函数参数:# ]; B- p+ `+ q" ^( \8 U/ ?

0 T" I: t5 p8 m2 Q' B, `& \  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
$ v+ o4 R5 y9 ?1 N  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。! s8 }' C3 n3 K. l/ X% u" S
使用举例:
3 L# v. s- k% @$ c" m; l8 x; a( V+ f, |1 I# S
  1. /**
    5 Y% F# j7 G; A3 i
  2. * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
    7 b5 s* ]+ a$ a
  3. * @param  pData: Pointer to the buffer that will contain the data to transmit# [8 T" o- X5 l) h
  4. * @param  WriteAddr: Address from where data is to be written
    2 @2 x% C0 d3 r, _+ J+ [- p
  5. * @param  NumOfBlocks: Number of SD blocks to write
    / c0 p6 F/ ^- V% A& A* k
  6. * @retval SD status/ y9 ~7 K% j3 [' `
  7. */9 L2 m& y6 u# w+ v( S# }4 i  m
  8. uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks)
    ; y- H; m; L7 R* X/ P& {
  9. {
    ( p+ H; Q) b; J: _

  10. ( B: V# f' O/ i. ]/ P7 f) {
  11.   if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)
    , q6 J! A! H' |: T
  12.   {
    , }8 j7 b' k" k% e8 D( ~
  13.     return MSD_OK;' l7 x% V+ C2 e) e; K" \5 t
  14.   }! \  T5 R' \9 O* ]
  15.   else$ h6 [; \# W4 l
  16.   {
    , U* y; p8 L6 R, Q; Z( x5 Z
  17.     return MSD_ERROR;) l/ o; t( p% A
  18.   }
    . Z' O) q$ u. V  i$ {( c8 G
  19. }
复制代码
7 n+ C, Q  v3 c7 B
91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
: _6 ]. y. I2 M% i* U函数原型:+ Q, }- d+ ^& T; Y- q! n

; U# M4 u/ w3 Q# V4 r2 P
  1. HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)
    " ~( I8 f6 N. h  _
  2. {$ M% S. @( T* e' ^% D" f' J
  3.   uint32_t PutIndex;0 h$ p# [+ o5 C! w. b

  4. . R/ L, B! w* B: P4 V
  5.   /* 检查函数形参 */6 h! H  I: s# \/ I
  6.   assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));! ]" ]3 [5 J2 \
  7.   if (pTxHeader->IdType == FDCAN_STANDARD_ID)
    9 f. I, y  w& _" d
  8.   {
      }& ]9 d  C" ]9 n' s; L; B
  9.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));* ]4 ^! V4 |6 b! d; H+ q9 Y6 J
  10.   }
    & C2 u% y4 _6 v4 Y; q/ K
  11.   else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */. V/ ~3 E+ K$ `* w' j; C$ X
  12.   {2 F5 _4 S7 e6 n1 T+ E) Y) n
  13.     assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));3 |5 K( D7 L- j- E' C& ^
  14.   }
    : w" x% Y6 N" c5 D, `  x, t* g% T
  15.   assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));5 \, b; g. \1 r+ X" F
  16.   assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
    ' |4 {( D: @: i. T1 ?5 o# f# i- _% d
  17.   assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));
    & E/ {: i2 L, f: u9 e* Q
  18.   assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));
    ) N$ l- C2 m& K: T2 R
  19.   assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));
    & ^: b* G- T2 X3 B" P
  20.   assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));$ Z! B' N$ s# ?' u, _" v
  21.   assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));6 \; x  `' S1 o7 Y3 s& H( h: `
  22. ) ~- N3 P7 I8 m2 n) _
  23.   if (hfdcan->State == HAL_FDCAN_STATE_BUSY)  m  q$ A. B' W: _" k' T6 \% \) V+ n- E. P
  24.   {
    + B2 ]  A' N$ S+ s- {/ H+ L5 K/ F
  25.     /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */
    0 i9 v) u) x7 w7 s9 z& X
  26.     if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)
    , L9 A9 Y; J) a: B
  27.     {
    0 z" u3 [# W" b/ n% `) t
  28.       /* 更新错误码 */
    " R8 }9 v9 [0 N' v# r
  29.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;- l" L+ ~. g0 `$ ~3 P

  30. ) j' X0 i! y, Q7 P
  31.       return HAL_ERROR;) V- X2 O& d3 _: j2 P7 C4 W
  32.     }
    * Y' M4 t2 O" V! r

  33. 9 d2 k5 O0 d! w3 p4 i
  34.     /* 检查Tx FIFO/Queue 是否满 */
    + G6 v3 G+ ?' }$ E& Z% j; R
  35.     if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)
    8 j0 ?2 v9 a, K" D8 A2 Z  x
  36.     {; J9 p6 g1 s, R4 d
  37.        /* 更新错误码 */
    # K- y- @% @) s' Y7 h, Z& y
  38.       hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;! e; B% |" U; ~* s; ?- k# ^: D. \4 m
  39. 4 w' a3 Q  @& \. F+ o
  40.       return HAL_ERROR;; F& g9 Z2 o- P- f, A
  41.     }
    2 \; D6 B4 v( I0 c( L* m9 m# P
  42.     else' l* w) S+ C  e" w- p0 a% h
  43.     {- q0 x6 F2 Y4 J% [
  44.       /* 获取Tx FIFO PutIndex */
    3 H3 {5 Z+ _3 R( W
  45.       PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);
      |8 G; h9 L3 S/ Z4 |1 |

  46. + G- _* \1 j. s+ v- t
  47.       /* 添加消息到Tx FIFO/Queue */  d0 o  r: d, w3 ?) F
  48.       FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);
    4 e- s) x; y# K4 ]& h, Z
  49. 6 X  A* u! k5 G0 z
  50.       /* 激活相应的传输请求 */- m/ I! V9 i$ G& p
  51.       hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);/ o6 V0 ^8 N9 j2 D
  52. 9 D1 }: M7 H6 M( U0 ^9 H+ i
  53.       /* 存储最近的Tx FIFO/Queue Request Buffer Index */. W; S9 k( z8 K5 E5 ~3 ^1 F
  54.       hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
    5 J4 l; B+ J$ `) e
  55.     }
    9 d1 J6 s9 \; V" ?0 {$ N- o- b
  56. : V0 A0 s& r. A5 s( j: V0 q- h
  57.     /* 返回错误状态 */
    ' k8 [4 A( u8 i  l
  58.     return HAL_OK;& A9 d0 v: a8 O. x! {
  59.   }, Z2 q: z' |2 q# i
  60.   else, m/ Z/ v6 G: f7 ~7 _
  61.   {
    & h; X7 c! b7 f4 {
  62.      /* 更新错误码 */7 m; F$ }+ u3 K
  63.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;. Y  `' v6 o, L1 Z  x! s+ B

  64. & M: }4 C: m2 o4 V; K# K
  65.     return HAL_ERROR;
    " [" f7 r5 F2 U- r  J+ `! d
  66.   }
      M) n, f6 ^" [3 G3 g+ x( F2 L
  67. }
复制代码

6 ~0 b& s5 X% N+ _函数描述:" j& `) b9 c( F( w
$ q' V/ ?. Z% f. s! C/ V% o- d  n  B
此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。2 y5 z$ r+ M, b# `' ]2 q& G
7 b, J' r: P& R2 [$ G
函数参数:. C1 M  V) S$ ^* f& _, z" _

9 ]* V1 r, j( t, u8 V( m  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。* j  [+ Y9 U" t9 U' X# _
  第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
. `/ l5 y5 c5 I9 v  第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。& g3 m! {0 @% L: y5 ^: K5 ~
  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
/ P5 ]2 e$ U6 U1 M/ h6 g4 k使用举例:: o; H& l# E! }: P- C9 d

0 z9 V6 Q: E" K
  1. /*
    # S# G* m  l' v: A% G5 G
  2. *********************************************************************************************************
    , u. Q& Z9 x+ k, ]2 _( j
  3. *        函 数 名: can1_SendPacket1 ~. R. o5 A1 \# x! [/ S
  4. *        功能说明: 发送一包数据* {, w/ j" J. j+ y6 b4 D- M
  5. *        形    参:_DataBuf 数据缓冲区
      h" }# U& C0 x- \5 S
  6. *                          _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节0 R- X+ h. z) V( A5 r3 V) q7 @
  7. *        返 回 值: 无# V. C% u. [# f- I: _# l
  8. *********************************************************************************************************
    ; o& Q' l" q# c
  9. */; K9 n: a- K' {; b2 u
  10. void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)3 X( Y7 F; T7 X0 l* W2 b! q3 H
  11. {                - M0 N5 b) v# S4 b; o
  12.         FDCAN_TxHeaderTypeDef TxHeader = {0};
    ( j! n/ V0 a! Z5 }& r1 c" X; i
  13.         
    + u* P! q, f- P4 s8 ^" D; r
  14.         /* 配置发送参数 */
    7 _1 J& f0 |: X% q
  15.         TxHeader.Identifier = 0x222;                              /* 设置接收帧消息的ID */
    : O: o/ ]( |8 W: D' i: c
  16.         TxHeader.IdType = FDCAN_STANDARD_ID;                      /* 标准ID */
    : a+ w! h- s6 i; L
  17.         TxHeader.TxFrameType = FDCAN_DATA_FRAME;                 /* 数据帧 */
    9 M& n+ s$ _; ^- T* L
  18.         TxHeader.DataLength = (uint32_t)_Len << 16;      /* 发送数据长度 */# U9 @) Z  j6 Q. M
  19.         TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
    4 t% Y" X2 g. B$ K6 J' O! O
  20.         TxHeader.BitRateSwitch = FDCAN_BRS_ON;           /* 开启可变波特率 */
    , h4 s' i+ _$ Y' c' T
  21.         TxHeader.FDFormat = FDCAN_FD_CAN;                /* FDCAN格式 */
    - j9 ~" o0 {( y7 m/ L+ B" a9 o
  22.         TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */9 b/ B, [0 @" e" `* A
  23.         TxHeader.MessageMarker = 0;     /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */0 k, p# F3 k8 X# ?  W" @
  24.         1 z9 z& R6 H6 }1 H; S
  25.     /* 添加数据到TX FIFO */: j2 R8 o& ^& H/ G" t
  26.     HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);% m  \7 a0 M4 [/ b% J; u4 @
  27. }
复制代码
1 w4 `* N, N' n. Y' l. r
91.4.8 函数HAL_FDCAN_GetRxMessage
! D+ r) _6 Z' Z3 L% U函数原型:
8 F3 x6 j5 w1 k  u  e# R! s9 j0 k, [  x8 j* U  s( r+ |$ v" e% s" Q
  1. HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)3 F6 G- a, A; F
  2. {$ m5 p4 o+ `2 H3 m' l* l, J
  3.   uint32_t *RxAddress;
    ) Q- @, u" h% Z/ C4 d& g
  4.   uint8_t  *pData;
    + r8 y% w3 T* ^, b& Q. G$ y. {
  5.   uint32_t ByteCounter;/ X& f  V5 `1 l, L( t9 ?
  6.   uint32_t GetIndex = 0;
    % ~& [0 r0 [; S) i7 S  _7 f6 @
  7.   HAL_FDCAN_StateTypeDef state = hfdcan->State;- \4 X' w' S1 c8 a

  8. 5 A" ?1 ^: r4 p6 t& a6 ^
  9.   if (state == HAL_FDCAN_STATE_BUSY), q4 K- I5 n0 I% F2 T
  10.   {
    : i& ~1 o' t. V! o
  11.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */
    , m9 z& A; v) q0 z" q9 |! o
  12.     {2 ~$ p7 u& Z2 Q! a0 o* |5 Z) ~5 a6 ?
  13.       /* 检查Rx FIFO 0 分配了RAM空间  */
    1 ]* z- R( B1 A6 J0 ^7 ~. E
  14.       if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
    4 ]  z8 J  S3 `( T( f
  15.       {
    : N) R; b* L' q+ G3 V
  16.         /* 更新错误码*/9 |/ F* h( ^( T2 e% |7 c: a( _
  17.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;- U: X- a' {$ K0 w! D; f8 V" @6 y

  18. ( i& w# _) L, K, j0 J/ L
  19.         return HAL_ERROR;! b3 P8 L) B4 G6 S
  20.       }
    : g9 U- d4 U, L9 `6 ]# A
  21. , N" O. F0 s$ _6 I+ ^
  22.       /* 检查Rx FIFO 0 非空 */
    . k  X. d* D* X1 Y
  23.       if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
    / F% x. s: R) \" J% y5 X# h3 J' G
  24.       {
    ' f( w4 Q( G# |/ Y! y0 E" i
  25.         /* 更新错误码*/6 q2 H7 K' ~5 u* l8 o' M
  26.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;3 o2 I/ L0 ]; n0 @  z9 \. q) ?

  27. 7 b' [. A# p) \
  28.         return HAL_ERROR;7 C- j! k6 x, j1 B& \5 s
  29.       }' r' U6 ^, j' R3 H
  30.       else
    ) O/ L. h8 H4 v( T- c* h
  31.       {  m1 I7 l0 M# O% }3 ~
  32.         /* 检查Rx FIFO 0 满且开了覆盖模式 */
    1 K/ p9 q3 V6 i( I
  33.         if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
    : e0 d4 c) {+ c3 i0 w! g% r
  34.         {
    % a5 a/ `4 y2 }
  35.           if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)
    ) A. T" a) [8 w' ?
  36.           {
    3 ^/ J3 d: C0 _
  37.             /* 开启了覆盖模式,丢弃第1个数据 *// B: E9 V# J4 |
  38.             GetIndex = 1U;
    " r% |' d3 j# E- c. C7 m
  39.           }0 [) _' @/ W0 p% U
  40.         }# X- A! h7 ^- ]1 S2 ^
  41. - c" E5 B. P) ?% r) L& D3 ]( F
  42.         /* 计算Rx FIFO 0 element 索引 */
    , s- T( ?' {0 V" M
  43.         GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
      I; }& }9 m0 I2 V# ~+ F

  44. - Z( b! U- t, [
  45.         /* 计算 Rx FIFO 0 element 地址  */( J' j, ]. g; W4 d- F$ i
  46.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));! k( U& }/ a2 {& Y2 W4 M" \) K
  47.       }
    : M& b. x$ x% M1 b; E6 X
  48.     }
    ( }) L% X9 n. h0 C  N; a3 [
  49.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */  F7 U5 }$ |7 z% v& u
  50.     {+ _5 I$ |2 q9 l6 o
  51.        /* 检查Rx FIFO 1 分配了RAM空间  */
    1 v+ O6 l9 a. t  a3 [4 q7 r
  52.       if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)
    2 h8 J% c3 I  z) {" y* t( {
  53.       {
    * P5 P! s; s) P2 @9 H, I
  54.         /* 更新错误码 */$ v( d) |3 D6 q: }) e! `+ }
  55.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;& U: T7 n' {8 }0 x1 d4 A

  56. " I+ T8 X, l; v; t8 {
  57.         return HAL_ERROR;
    . V1 [+ u7 v1 R1 c# O' ~& h& @" D+ @
  58.       }
    9 r7 p3 `) U+ T. J' {

  59. " m, }5 k+ r6 j+ m: _0 A* \
  60.       /* 检查 Rx FIFO 0 非空 */
    + J9 L% T3 j' Z  t2 ]/ i7 B
  61.       if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)
    2 Q( J" d; I& w- f# n2 E
  62.       {# y9 |* S" k# `8 u0 v9 r3 J
  63.        /* 更新错误码 */- ~/ d6 K5 a/ q, Z( C/ T% c
  64.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;
    & R8 f* T' v' h( a
  65. 8 K9 C/ ^4 P8 a' i7 g1 H7 \
  66.         return HAL_ERROR;0 \, C: F% e: Q* `1 j" f
  67.       }5 E3 C9 ~1 c& |" E6 B+ z% m
  68.       else
    ) f& g3 y7 u0 ]8 u
  69.       {# D# B+ X9 f# @# i# t
  70.          /* 检查Rx FIFO 1 满且开了覆盖模式 */
    " a/ u- D) V% r
  71.         if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)1 j8 S! V; H) f7 d: Y$ n3 I9 t
  72.         {% i6 w" a, r- ^# {
  73.           if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE); V: P0 Q% u: L/ P/ U4 Z
  74.           {
    # `. ?$ `8 p2 L
  75.             /* 开启了覆盖模式,丢弃第1个数据 */
    * O7 Y- z; \- K2 R' p$ Z
  76.             GetIndex = 1U;% p$ I* c3 |8 Y3 R/ x7 [( c
  77.           }
    " F2 A, f# J8 H
  78.         }
    . I0 i" ^6 S/ o( r6 G; S% j3 U
  79.   N5 v5 e2 x' U' R3 s
  80.         /* 计算  Rx FIFO 1 element 索引 */
    * r* a8 t2 N& J0 b( }% @
  81.         GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);- Q4 K) W4 k$ G( a: C3 ~
  82. 7 y' I; D2 V" X0 i$ Y4 K
  83.         /* 计算 Rx FIFO 1 element 地址 */
    - f' A. s  a+ Z2 e' d# G
  84.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
    # l( ?8 u! s1 c& H2 Q& f
  85.       }
    * Z# c1 h2 o3 S1 w) {
  86.     }
    8 w# |! J. i" G# |0 f% U3 I
  87.     else /* Rx element 分配了专用 Rx buffer */2 P1 Q) C" F& f+ T& I
  88.     {8 h9 z. ^9 y! F7 |
  89.       /* 检查选择的buffer分配了RAM空间 */; p- M) P( R7 g' p
  90.       if (RxLocation >= hfdcan->Init.RxBuffersNbr)
    0 T! y: M8 R- X6 o: V$ n
  91.       {4 C1 ?7 [- d) o
  92.         /* 更新错误码 */
    + \8 m4 d! F8 Y- Y( @: i! R' K0 H0 [
  93.         hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
    8 h: ~7 ?" V, D* ]; G5 \( m1 E& M

  94. & Z3 h' G9 s1 Q# \- H* a- R1 J
  95.         return HAL_ERROR;0 Q5 n9 \  u5 [  Q; L
  96.       }" G- D4 J4 U) t0 @0 v8 x8 F- w
  97.       else
    3 |8 E6 K, C! J% b4 y/ p3 R
  98.       {- [  G# k1 [/ L. a! V. F! Y
  99.         /* 计算Rx buffer 地址 */
    ; g( U  Z2 l+ F9 {; M) ]
  100.         RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));
    9 `- n$ }' U9 \* `; Z1 _3 h9 m
  101.       }. ?& M+ W. C  x
  102.     }
    1 N: @! p5 b  y1 J4 C+ o" }

  103. % F  w9 I, n' N2 X7 s
  104.     /* 接收IdType */
    : v' x- }; N2 M3 Q6 ^' W
  105.     pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;
    2 k# e0 ]/ D) m5 ~
  106. / i4 W( _" S; q1 t, s
  107.     /* 接收Identifier */
    5 X* }- f8 w  y. h, P, B
  108.     if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */6 l9 n7 b. @1 x4 v
  109.     {
    ) l: h, m" A+ F' B! i2 e2 r
  110.       pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);
    1 X$ O2 d1 A: }3 C9 s1 k
  111.     }
    ; e5 }; D9 b0 o6 M
  112.     else /* Extended ID element */' O- l- p: a, M' `; R" T) y
  113.     {
    ) w" l8 n4 r9 I2 j9 ]8 e( \
  114.       pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID);
    9 J: p3 i* ]+ Z
  115.     }
    ; F/ ^$ A3 T/ h/ R! _  B
  116. % V! d: @1 I9 v+ D* N1 {
  117.     /* 接收RxFrameType */6 {8 u: u- r. \& ~
  118.     pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);' [" a9 @. T2 d2 Z3 F2 ]

  119. 7 J& K, ]- `" P: G- L* ?
  120.     /* 接收ErrorStateIndicator */; x5 _# L1 x: f
  121.     pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);& P" |8 K" T9 I
  122. / k, D0 n4 z* H; M" m& p* S1 O
  123.     /* Increment RxAddress pointer to second word of Rx FIFO element *// R! r& `8 E7 s
  124.     RxAddress++;
    6 Q5 t+ s& y$ {5 T% O% o

  125. 9 O. P% }# {: F) ^$ j' m
  126.     /* 接收RxTimestamp */
    " [6 T& S6 |& U& d" y7 o: r2 ^
  127.     pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);0 U. `7 j( Z3 Y+ B  b) K$ M
  128. ! e9 r* D# W3 O* Z4 w* D
  129.     /* 接收DataLength */* Y' e( t# ]3 h1 y, `- _
  130.     pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);6 b$ G8 l' k" y* b' M$ Z0 v
  131. : ^. r  x- V+ q$ ~. j  e
  132.     /* 接收BitRateSwitch */
    1 {! h* J) }& p) T) a
  133.     pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);5 c! ]  r( x/ r

  134. # e. L7 e* z" m4 G1 m, ~8 W4 a
  135.     /* 接收FDFormat */; j. s1 n4 }( V4 h* i4 K9 L5 ^
  136.     pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);; t8 M& r( E5 _/ _, Q. g$ }& y

  137. 1 ?" M7 R& c8 L! b/ W5 j1 U3 p% @  O
  138.     /* 接收FilterIndex */
    - W/ z# K. g2 S/ K# @) f* _
  139.     pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);
    ( m4 K3 J, v& p1 w$ E2 b
  140. 1 Q, N6 _- g0 l$ G
  141.     /* 接收NonMatchingFrame */
    , U8 p) \, k( P/ o0 d2 b% o) Q2 L
  142.     pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);$ @& y* |7 Z) T/ O! B% _8 Q
  143. ( D7 ^, ]) P" b: T; m8 x
  144.     /* 增加地址,指向Rx FIFO element的payload */
    2 r0 |( w1 k- B
  145.     RxAddress++;
    4 A7 `* Z% W* S  ?/ }
  146. + o+ f2 e! W  t# F/ Y: [
  147.     /* 接收 Rx payload */
    1 q  Z, O* o1 M; `% Y- J- A
  148.     pData = (uint8_t *)RxAddress;7 t; t8 n' J* C  w
  149.     for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
    " e" [# G6 h7 _* n' D5 w
  150.     {; S! M! O- b4 p
  151.       pRxData[ByteCounter] = pData[ByteCounter];
    ! O6 d$ B& I& I8 w3 O  `* s% q
  152.     }% y. x8 f4 P, X4 p5 a
  153. + ?3 m& l8 W& \/ v; H( [. Z
  154.     if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */7 ^- M  n2 P/ S& h/ m
  155.     {/ X! X; U5 L1 b4 c" p: C! w0 l8 U
  156.       /* 确认Rx FIFO 0先进的数据已经读出 */
    7 h( E' L# w* E) n5 ]$ G
  157.       hfdcan->Instance->RXF0A = GetIndex;- R9 ~0 r! }* K# F
  158.     }5 j9 L, {( a$ V/ _8 g0 B; ?, I+ t
  159.     else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */' @, k. V9 L/ C* n- ^
  160.     {
    5 i0 K/ S  T& A
  161.      /* 确认Rx FIFO 1先进的数据已经读出 */6 Q  Q$ u0 F- _3 s7 L
  162.       hfdcan->Instance->RXF1A = GetIndex;
    ( Q' y/ t( ~9 c$ l
  163.     }
    9 U1 e7 t" k# P% h9 q0 Y9 e* o5 |
  164.     else /* Rx element is assigned to a dedicated Rx buffer */
    ; U# L) Y5 E0 j" x& r
  165.     {5 i- E/ w; y% L/ \
  166.       /* 清除当前Rx buffer的新数据标志 */
    : X( N/ g. B" D/ |) N8 a5 r
  167.       if (RxLocation < FDCAN_RX_BUFFER32)) U' n# _( x2 X# @8 {/ V: {
  168.       {1 h" v- y' x4 X+ C5 ^3 O
  169.         hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);6 B2 K/ s/ a5 Q
  170.       }
    & A1 O3 l# G6 \
  171.       else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */0 c. t2 |7 P8 w' Z8 B
  172.       {5 z9 D1 U1 w+ ?9 b* v% s/ e
  173.         hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
    ; |. s6 z' X5 p4 l
  174.       }5 f* v5 i0 {( U( R) B. d6 g
  175.     }. }3 m+ z- U& u/ ^7 M* ]* M
  176. $ ]" n. y$ H' T5 V2 d$ C2 Z, G
  177.     /* 返回状态 */$ Z# Q) k. ]0 X4 x+ ~
  178.     return HAL_OK;
    - M- |9 `5 k3 G8 W1 p  i
  179.   }* D/ p& D/ E6 s9 u5 v3 R
  180.   else% l- l$ ]& }, R5 n3 T
  181.   {; L1 B1 x0 C' l+ G; w& ^
  182.     /* 更新错误码 */$ X. l- d# @( ^' t" U: x, x
  183.     hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;
    $ X; R6 d4 `. l5 x7 E4 `; j
  184. 0 j3 @: ^3 U0 G5 f+ q
  185.     return HAL_ERROR;* u4 t$ J& j' K/ W; J
  186.   }# m, K8 n( b5 L
  187. }
复制代码

( |- r- e' ~* F8 f/ `- T3 p! M3 F函数描述:
* k/ r/ e8 a5 d" @, }
2 V* }- W  P4 R此函数主要用于获取接收到的数据。4 Q) h* |- x6 D+ D6 E, _/ ]
: V2 n  t, Y; t5 g
函数参数:
9 G" U% u' E' d! }# b, o4 D/ f: }8 ?# r7 o; R9 g
  第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
  m+ |' y1 m- {9 n  第2个参数是读取位置,支持如下几种参数:
8 D; P/ U2 X% H, c! t, b, ?
  1. #define FDCAN_RX_FIFO0    ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0    */
    2 L: }- S1 t, ^2 m& y- u
  2. #define FDCAN_RX_FIFO1    ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1    */
    / M9 M( O# N% @
  3. #define FDCAN_RX_BUFFER0  ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0  */
    : I5 s& v  D4 [! w
  4. #define FDCAN_RX_BUFFER1  ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1  */* F. B' Z6 b4 P" N6 A  x# {9 m
  5. #define FDCAN_RX_BUFFER2  ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2  */+ B; z- `# h# v* Z6 b* d
  6. #define FDCAN_RX_BUFFER3  ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3  */' Y8 O. c0 b$ _  b8 M- ^
  7. #define FDCAN_RX_BUFFER4  ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4  */  ?; q$ K2 d8 E, I. a$ O1 H/ E
  8. #define FDCAN_RX_BUFFER5  ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5  */
    3 g: `4 _7 x/ z! }, ]5 P8 m& r0 x
  9. #define FDCAN_RX_BUFFER6  ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6  */' H/ G% o- b' n1 n
  10. #define FDCAN_RX_BUFFER7  ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7  */
    1 q3 n7 K8 k2 Z2 w
  11. #define FDCAN_RX_BUFFER8  ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8  */& x- k- `' ~) Q; ?8 E+ X' V. s2 J! ?% Y
  12. #define FDCAN_RX_BUFFER9  ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9  */
    * N" Z: Q; l3 O/ J
  13. #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */3 C- Z) u4 L1 J: O
  14. #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */
    " G1 o$ }9 D+ j
  15. #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */$ t+ M9 x+ Y' K: y
  16. #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */% t. @# V0 U0 @! u
  17. #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */, p" Z/ _, R: ^5 g2 ]6 t/ p; V! l: t
  18. #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */
    4 u( z/ r3 U- \4 X
  19. #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 *// S7 W* ~7 J6 `1 z. v1 v
  20. #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */3 h" z3 |) j) m) O2 J
  21. #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */9 Y) g6 f8 V, O
  22. #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */: y2 e5 X7 l' w2 q
  23. #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */
    0 h! S/ P) f! B, |* n' R' Z- @
  24. #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
      M* w6 b6 Z" \' }3 D2 v! G
  25. #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 */4 b; p6 f" g3 [" O$ {! X2 K
  26. #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
    , A. s2 B- G! H& _" h0 Z
  27. #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */9 ~1 S: b8 f0 T) n) K6 u6 y/ Z
  28. #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */8 t9 I/ m; o- m
  29. #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
    $ d# |% J8 R) x) |7 a0 F: h
  30. #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
    2 N8 T% e1 o- ~/ h* j0 e& ?
  31. #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */2 c2 \# v% a6 ?& z0 h- q3 @/ z
  32. #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */7 g! u  z; U, X) L
  33. #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */* j9 w6 h7 }, R
  34. #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */% J, \, d* T4 p/ a% e) }4 M
  35. #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
      Y0 _# g: W/ f# \
  36. #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */. D9 q) ~/ H$ }# ~
  37. #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
      a' B2 }! V: y
  38. #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */
    : C, o0 V: ^' O7 s/ h
  39. #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */
    0 i  x8 B; o  a2 d& Y, U- y
  40. #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
    1 e$ G( u- f2 c3 Z, v1 J
  41. #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */
    & M' K2 T( ?/ h) g/ Q, A* t# Q: Z* E
  42. #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */
    8 d' A/ j; [- F& h1 B0 I5 i
  43. #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */4 C$ F: l* {9 m% X& Y  z
  44. #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
    & j9 h% Y+ L1 M; Q% h
  45. #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */- Q5 I! X$ f2 t7 t# [3 }8 k8 g
  46. #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */0 t1 H7 Q% r6 Y0 Q/ @" L
  47. #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */
      X+ Z3 {8 U- u( }3 k
  48. #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */+ ~6 d8 k, v3 F3 b) s# V
  49. #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */; v+ l6 [, L# g1 @0 c3 _8 v# |
  50. #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */
    ! A2 V2 b; a8 v6 f7 Y3 P$ S& c
  51. #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */* \% n) S0 _0 E9 P0 c  b$ R: z  o
  52. #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */7 \; v6 {* j% _  u9 I
  53. #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */
    8 i  Y2 H7 L& |2 h  |1 A
  54. #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
    ! a& u# d& Z. d, {
  55. #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */5 \. }) \% M: m8 d0 L4 f# @) m! |
  56. #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */
    + w/ V1 N2 i  w5 o; Y, O
  57. #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */# R4 T, B2 x7 K* X
  58. #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */5 ]4 |5 B( {1 y0 z  q* T0 W
  59. #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */
    , T6 L" [0 M6 u! L7 s
  60. #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */# K6 K! r9 \, J5 g+ D5 S1 X5 S3 Y4 x
  61. #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */
      i' m+ \9 E2 s6 G, c; j& ~
  62. #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */) w+ q% k: M2 o( e# d4 C& ?7 @" x
  63. #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */! ?! q1 A) P9 }0 E5 B' w
  64. #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */
    : t' Y- K& W6 s& r
  65. #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */) T/ N4 ^$ b+ V- u8 m
  66. #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码

* B( ~7 D) {7 l4 {5 n5 A+ k  第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。& c: y/ K; K2 @; [0 @5 t) E) R
  第4个参数是数据接收缓冲地址。
; \& y. k2 @% L+ E, L  返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
+ x& z8 e9 L8 u, x3 h+ l2 x使用举例:) f9 l# q! S. q# t. @# C0 o& i

7 Q, R3 O8 j0 {5 v  j, j" m2 g
  1. /*( F* I1 I0 p% H' ]; V9 o
  2. *********************************************************************************************************
    8 v2 J. b3 C! @% i2 v4 T: T* L
  3. *        函 数 名: HAL_FDCAN_RxFifo0Callback8 g5 u" y! u% }' N# t' W- ]
  4. *        功能说明: CAN中断服务程序-回调函数
    5 `7 |) k% }0 y8 E
  5. *        形    参: hfdcan( d8 N2 f" p' z/ h" X
  6. *        返 回 值: 无
    / y; A* P$ Q2 t6 y; v
  7. *********************************************************************************************************. r# C! {0 ]! w5 s# @) c
  8. */
      a3 V' a; s" `/ v) H7 {
  9. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    / E, M" X) ?; L4 V. Q" b' D. K
  10. {
    4 r# e# V# `! @& @+ `6 s
  11.         if (hfdcan == &hfdcan1)
    / ^" K  Y7 f0 Z- ^
  12.         {( T# s% b, B% U" K7 `' A, W
  13.                 if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)2 m1 {' N( g6 {+ ~# Y1 Z2 h. C2 @
  14.                 {
    , Z* i9 R7 M/ z6 Q4 i  |( z( n+ c
  15.                         /* 从RX FIFO0读取数据 */4 y: |4 T1 U# q1 z. N* l2 M. b; G4 |
  16.                         HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
    & \! W5 h5 A" z0 d- J

  17. 8 y* x3 k6 |& M6 @) m6 L1 e; X
  18.                         /* 激活Rx FIFO0 watermark notification */
    : b  g/ p, f$ E; B8 A7 x8 y: G; |
  19.                         HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
    6 |) V! g3 l9 m8 }7 H( p
  20.                         
    ) s& h2 T6 Q& I
  21.                         if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID): C- a. Z+ J" r; j7 U
  22.                         {
    + F9 }! [8 v  r, g4 U6 Q
  23.                                 bsp_PutMsg(MSG_CAN1_RX, 0);        /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */7 D3 F# N, C) [8 a) v% a+ y1 l
  24.                         }
    # F- c1 F5 q' j
  25.                 }
    , Q. `0 H' D% B) _' @* Z3 x
  26.         }
    * z% W; {( `5 P4 L/ z+ A5 W: T7 c2 |2 s
  27. }
复制代码
7 g- N& n2 p8 }6 b- H* u+ G9 ]
91.5 总结
% C9 G4 i' R  Q# R5 g6 _, F! r5 N& Y本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。2 L0 A: J5 F# [9 ~+ x" S% }
% r$ L* n, E- }

& C+ v9 K4 G. B# I2 U7 Y! B& n
收藏 评论0 发布时间:2021-11-6 23:50

举报

0个回答

所属标签

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