91.1 初学者重要提示3 ~% Z, x( _' r. Z, M, @' J
FDCAN基础知识点可以看第90章,已经进行了详细说明
% r; ?7 z* Q5 }: n 特别推荐瑞萨的CAN入门中英文手册,做的非常好:地址链接
3 [$ I, v" w6 V; J% h91.2 FDCAN基础知识
- G0 C6 f) y9 W' I0 |7 TFDCAN的基础知识在本教程的第90章进行了非常详细的说明。我们这里将本章用到的几个知识点再做个说明,详情推荐看第90章。2 Z n4 Z7 g- x6 l
3 h! G. T/ o7 |6 A. D& x91.2.1 CAN FD协议介绍
& O; O a8 v& SSTM32H7的CAN FD符合ISO 11898-12015标准。STM32器件上的FDCAN的功能如下所示:
; _3 U7 T7 h4 J2 [' C& ~% X1 Z2 R! G' U; Z) f
(1)符合CAN协议2.0版A,B和ISO 11898-1:2015,-4。
3 ?- _+ w) }+ `( ~5 {. `
, [- N5 _" A9 }# ~(2)可访问的10 KB RAM内存,最多可分配2560个字。. w9 i6 i4 ?+ h/ G, W5 o
) u- i" i0 x1 J(3)改进了接收过滤。( n3 z& m/ G5 ?& A! X, X, v
, o4 L9 \- l* Q(4)两个可配置的接收FIFO。; h3 B \8 R' b" I% W$ m1 J
: p' b0 Z' W; h/ J
(5)多达64个专用接收缓冲区。
7 D' M7 p% C% o. o J% I5 g5 x) i! v; H# x3 n( {) `
(6)接收高优先级消息时的单独信令。0 K* _# Y8 z6 U# [
! q& L9 p4 t. O2 H(7)多达32个专用发送缓冲区。
1 g9 K: E) R. E& S
: |4 ~4 Z. S* ]) V3 k(8)可配置的发送FIFO和发送队列。
1 _5 J$ w: O9 G/ K
: Y" R0 O) g$ F; b4 q8 M3 ]3 h(9)可配置的发送事件FIFO。
" A- y; ^. n8 n5 `- r* n! v! t" i; |8 w2 m; g+ o
(10)时钟校准单元。
; g" O/ R1 D- r) Z- z: y# W+ Q3 C4 p* g( P! \6 e* j$ j' K6 Y
(11)收发器延迟补偿。6 u7 u7 U) t& d. O% b. G: A2 N& ]
! i4 |: Q% q. o/ Y. N7 v( @' ^" C下图说明了FDCAN框图。! D M3 R0 U9 [4 V
1 f, l4 {, @, h' h7 W5 P* ^
( o& r( T# g3 `9 _4 [
0 }' G/ i2 e" u0 m) R* Q ~' p. L/ y/ H7 f% N+ Q, D
|- p; r; s( o% ]' i通过这个框图要了解到以下信息:
; I1 S+ k! Z, N# x9 d8 ^+ M4 C' c! Q$ q
(1)CANFD1和CANFD2共用一个RAM空间。" o M$ A0 ^, i- R
2 b5 u/ L0 `; W' B8 z
(2)每个CANFD都有自己的内核。2 m$ U8 ^; L d! ?+ { |
: D9 }& ~, W+ A% |9 b. O9 d- E
(3)CAN内核实现协议控制和收发移位寄存器。
3 ?& I3 o% g, T5 V, k
$ ~2 P% s; b" n" V(4)Tx handler控制消息从CAN消息RAM到CAN内核。9 S9 ]3 r$ S3 Y* S& G0 F+ d
& C0 _+ e3 O+ y! P+ l7 m
(5)Rx handler控制CAN内核到CAN消息RAM。
; j0 W( x( v; \2 Q2 [ J' j( q" h3 h/ g1 _
91.2.2 CAN FD特性
& D! R' o1 O# l(1)兼容经典CAN,可以遵循ISO 11898-1做数据收发。
1 q/ r5 Q M+ A U/ _; ^* J. z& [ U7 f2 d' O
(2)提升错误检测,支持高达CRC 21位的校验和。$ \7 }5 k* B! ]" I: p
9 y, W0 \- c( K2 [: w
(3)消息优先级。7 U5 c$ V p7 r. w' T
. V6 a' {9 U1 Z4 R/ G8 m(4)保证延迟时间。$ Y. \$ [$ q* g" C: j6 |) W w
3 ?4 O3 p* o; T ^* P ?7 C1 }(5)配置灵活性。7 \/ R: ~) Y) b% x6 `# ^/ H5 u
& ^9 _3 B1 l* {3 O+ ?
(6)具有时间同步的组播接收。1 g+ Q9 _7 v# Y+ K6 f
6 k2 N1 ?& t$ M(7)系统范围内的数据一致性,每条消息最多64个字节。
, u) }8 m- k1 m( v, K
6 E) h: L% g4 Z) O X6 J) f(8)多主机。
& `! D- C, H8 w' \8 d9 o
; L# L/ `# o& A9 s8 r(9)错误检测和信号。
% u4 R- x: k1 m; d/ x- o! e- z6 S; P9 P9 A! P, \/ q9 Z
(10)区分节点的临时错误和永久性故障以及自动关闭缺陷节点。( x' l! y( c1 w( g. b
0 q1 u! }0 t6 g# p; q3 ]91.2.3 CAN FD格式6 G& x# S. r3 F( I
& ~% a' o) J D& N$ A8 B2 b0 L% z/ c) d F; ~ x
- V, o! `0 j) `, i. t' i( A
* H( C- J7 R" R8 T T; m( S5 A第一个仲裁阶段(The first arbitration phase)是一条消息,其中包含:' Z8 [! ?, h: k$ j3 @% H
4 v5 J# w! v1 ]1 s, j9 R }2 P7 V
(1)帧开始(SOF)。
$ r z. S& Y! _. a2 T. r4 s% l/ A+ ^9 E# ~9 r* ~
(2)ID号和其他位,指示消息的目的(提供或请求数据),以及速度和格式配置(CAN或CAN-FD)。( B( L1 B% z2 B( I1 G. M- h7 A* F3 t
. c; [3 w9 x y5 @) W数据传输阶段(The data transmission phase)包括:
8 Z# d6 W- K) S" c K9 r: Z( K) P7 g& S* H2 e/ B6 M+ G
(1)数据长度代码(DLC),指示消息包含多少数据字节。
9 Y1 k7 |3 V# r5 c
1 t* U" L& R. E/ ^% Y* W(2)用户希望发送的数据。
$ s1 O3 j _# X9 U% ?# N
6 H5 E6 ~! Z, u$ x7 {' m8 h(3)检查循环冗余序列(CRC)。
: C% R6 |6 \) _% K5 l0 x* ]/ I& C1 Q) [$ h+ |- |5 u
(4)显性位。
! Y9 }* [2 j) j4 C" h& s: Z$ }# o9 L: t( a" t7 Z
第二个仲裁阶段(The second arbitration phase)包含:
# q- @2 X9 `5 v2 O# |3 z4 G- l- q, ?1 U9 G9 M) A" A9 q! e' W5 S
(1)总线上其他节点发送的确认(ACK)的接收器(如果至少有一个接收器成功收到消息)
4 Z9 j. {8 S- F% d, a
5 m; I6 S7 e) u' N(2)帧尾(EOF),在IFS期间不传输任何消息:目标是将当前帧与下一帧分开。7 {! M( g9 H1 H4 R- c( G' h
8 A3 N% L0 ^; V+ s5 x$ k1 H( K4 S
注意:对于29bit标识符帧,当添加18bit标识到第1个仲裁阶段的IDE bit之后与标准CAN FD是类似的。
, X! D, }' \; {! _: j, ]
+ v' }" K# r# N$ t7 ~91.2.4 CAN FD相比CAN2.0的提升
E6 n) Q; i( Y2 h3 X! a* yCAN-FD的开发可以满足需要更高带宽的通信网络需求。每帧最多具有64个字节的CAN-FD以及将比特率提高到最大的可能性,使数据阶段要快8倍,在第二个仲裁阶段要恢复到正常的比特率。通过以下方式确保数据传输的完整性:
+ e* C- K* y$ [% n' G% ]0 p9 E/ S) m8 X- o" U4 n
(1)17级多项式对最大16字节的有效载荷进行CRC。0 {8 x1 p+ {- K2 K0 e
' o( [1 a/ Z; n/ a% |; E0 ^
(2)21级多项式对16到64字节之间的有效载荷进行校验。$ n0 e, ]2 `. u! H0 \2 M
8 V: P$ _8 ]8 G) U标准帧和CAN FD的区别:0 F! m1 D; X! k+ }2 M
4 S) i5 a, B+ ]
( y# s8 Z* J8 w0 f- o
* p0 |6 w) u- Y9 \6 p: O+ R1 N9 r( J& P# b: D* L
, n: E& @; L1 j# j标识符后,CAN 2.0和CAN-FD具有不同的作用:
. Q6 k# G1 E. G( T, c) L, j. J; n1 \/ b
(1)CAN 2.0发送RTR位以精确确定帧类型:数据帧(RTR为主要)或远程帧(RTR)是隐性的)。 U6 b! r. i" t0 t& D
$ v7 K$ J+ g: Y8 _( ]0 F+ c
(2)由于CAN-FD仅支持数据帧,因此始终发送占优势的RRS(保留)。
, E0 P% U3 M' A' e: n5 X; d1 _3 T9 s+ t/ m
IDE位保持在相同位置,并以相同的动作来区分基本格式(11位标识符)。请注意,在扩展格式的情况下,IDE位以显性或隐性方式传输(29位标识符)。( q( j" Q* t6 l* N3 v& |4 c& s
% M( v$ v, u9 D) Q与CAN 2.0相比,在CAN-FD帧中,在控制字段中添加了三个新位:
- \0 d5 Q+ j9 D- M7 o, T; t. o: F. x X- |# s) u* a. k! f
(1)扩展数据长度(EDL)位:隐性表示帧为CAN-FD,否则该位为显性(称为R0)在CAN 2.0帧中。
+ O1 A7 [+ `1 d1 c
" F, k; V' F M: W M, C8 w(2)比特率切换(BRS):指示是否启用两个比特率(例如,当数据阶段位以不同的比特率传输到仲裁阶段)。
# K9 V! L5 {% p$ C
; z" z5 w, i+ ^/ W, E) A(3)错误状态指示器(ESI):指示节点处于错误活动模式还是错误被动模式。% \4 }9 z3 K6 y7 j9 p
% C, _0 B: E' _. }& f. b, b
控制字段的最后一部分是数据长度代码(DLC),它具有相同的位置和相同的长度(4位),用于CAN 2.0和CAN-FD。 DLC功能在CAN-FD和CAN 2.0中相同,但CAN-FD有很小变化(下表中的详细信息)。 CAN-FD扩展帧允许单个消息中发送64个数据字节,而CAN 2.0有效负载数据最多可以发送8个字节。% Z0 o9 s1 F! Y; V6 T
7 }2 s7 I6 C. \8 B9 c' b. S, d: C5 G+ T7 k* H8 S( d
. V) z5 {5 @3 u0 s
( |7 [- y0 n2 r# l5 L) F, r( i
/ j( r/ t9 u) ]+ ^1 x通过增加有效载荷数据的数据字段来改善网络带宽,因为需要更少的包处理。 同时,通过为CRC添加更多位来增强消息完整性:
, p. C/ x- G | ~3 N: G& U2 E+ B( b
& V7 G3 ~6 |; Z' e0 T4 h' R(1)如果有效载荷数据最多为16个字节,则CRC以17位编码。
9 \8 ]0 s8 P* i j* p( f3 k8 u# |' W$ V3 i) A* T
(2)如果有效载荷数据大于20(16)个字节,则CRC以21位编码。: b/ M& m9 u) Y; ~+ _
: }' W9 B1 j2 r% O8 J' j" b
另外,为了确保CAN-FD帧的鲁棒性,填充位机制支持CRC字段。下表总结了CAN-FD和CAN 2.0之间的主要区别。 提供的主要功能与CAN 2.0相比,CAN FD的改进之处在于数据有效负载的增加和速度的提高由CAN-FD中可用的BRS,EDL和ESI位来确保。
5 u# z" e' s3 G, F' G0 ~
: L7 j2 V' K1 Y/ z8 y3 l. P- j& s0 q) y% K/ F: R, @( D0 U
: `4 X6 [1 v& S+ ^, ^7 k" |. m. _0 c" ~! J
' Q; t$ a; y3 r1 K J91.3 FDCAN总线的HAL库用法# C! d3 j: O8 _$ ?
91.3.1 FDCAN总线结构体FDCAN_GlobalTypeDef8 \( F, [/ e' G9 o) U' ]3 q
FD CAN总线相关的寄存器是通过HAL库中的结构体FDCAN_GlobalTypeDef定义,在stm32h743xx.h中可以找到这个类型定义:
0 V: \; t. |8 x- g
" C( n2 d! @# L+ |5 H9 A8 z# q- typedef struct
8 X- e- n1 ]1 f0 k" c* n% s - {( H2 _4 p) s2 {
- __IO uint32_t CREL;
3 R) s. F8 F/ o- U, Z' {7 m - __IO uint32_t ENDN; . c& F0 W) o% u% V! {4 o
- __IO uint32_t RESERVED1; 2 h) z' s- t1 k+ ]8 x! i# G
- __IO uint32_t DBTP; + }4 S3 S; g U! W1 C
- __IO uint32_t TEST; 2 c7 e; x5 z6 s4 O J! q. g
- __IO uint32_t RWD;
4 k- p* ]6 `) \; ~* ?0 ?5 K" ? - __IO uint32_t CCCR;
6 I8 o `- w& t7 v8 F - __IO uint32_t NBTP;
) j$ R0 N5 t6 M" a7 @: C! w - __IO uint32_t TSCC;
3 `6 `8 y3 H" u' b) f# B# V2 {8 r/ P - __IO uint32_t TSCV; 1 t7 C7 e4 m. N5 _( ?/ u s
- __IO uint32_t TOCC; + O3 _2 G) E9 H4 o5 O( F7 U
- __IO uint32_t TOCV; + ?% J+ J# E& P6 A" P) _
- __IO uint32_t RESERVED2[4];+ B( n$ l- l: w$ }
- __IO uint32_t ECR; , f r& z/ \8 T
- __IO uint32_t PSR;
^2 R* Q ?+ |* J ]& ^' ]0 K" ~ - __IO uint32_t TDCR;
, z& U |# J% h - __IO uint32_t RESERVED3; * `& m8 M' w! ^2 S8 m
- __IO uint32_t IR;
6 ~ e- E9 T5 g - __IO uint32_t IE;
" y" z" K+ f4 e, G8 }5 b* s - __IO uint32_t ILS; # n4 _1 f6 W2 ~, O2 e' f
- __IO uint32_t ILE; 2 O6 w8 Z( i8 E$ F' t1 \) G( x
- __IO uint32_t RESERVED4[8];9 _2 d/ r- m7 z
- __IO uint32_t GFC; + Z+ J/ u8 F+ n9 q/ b: w
- __IO uint32_t SIDFC;
; w* F: w ^8 I, E - __IO uint32_t XIDFC;
9 g M& g' @; ?8 \& }: \) q - __IO uint32_t RESERVED5;
9 I# G1 M$ g# O5 T( m* F - __IO uint32_t XIDAM;
) G0 v$ e; |. _ - __IO uint32_t HPMS; ; Q/ w4 I! M7 Y+ h$ N
- __IO uint32_t NDAT1; 8 {+ [! ^1 W- M& T7 `5 C/ b$ ` h
- __IO uint32_t NDAT2; 5 |4 B$ |. G4 a& b
- __IO uint32_t RXF0C;
5 l: B6 P: V' `% r! O" Q - __IO uint32_t RXF0S; ' _9 ?; P$ _) ]2 H. @8 e
- __IO uint32_t RXF0A;
; g" [: f+ }$ [ - __IO uint32_t RXBC; 7 D/ u I. I' l' z& N) O0 C5 T
- __IO uint32_t RXF1C;
, W5 ]1 M, b2 c1 c - __IO uint32_t RXF1S; 9 u8 o4 b! W3 ~ D4 \1 P
- __IO uint32_t RXF1A; 5 |; R* i5 F* W3 l. d- Q% T
- __IO uint32_t RXESC;
' X1 S6 c6 Y2 j# B- z7 _! D0 x, A - __IO uint32_t TXBC;
* O3 h& p! ?" @/ p- ?' M; x/ E4 w - __IO uint32_t TXFQS; . F/ P% u: f0 v' i; Z" g! _
- __IO uint32_t TXESC;
7 g1 n2 [9 y# ]4 [* d* c - __IO uint32_t TXBRP; & W2 B# p: i. k/ n5 v. d
- __IO uint32_t TXBAR;
- b5 o( e* {" t" [. c - __IO uint32_t TXBCR;
0 ?: m% `( L% ~ - __IO uint32_t TXBTO; $ n# t8 e2 o1 ~" W
- __IO uint32_t TXBCF; 6 {! b3 ^" C( Q- Y6 D5 j4 D4 l$ _
- __IO uint32_t TXBTIE;
1 g: O+ |/ i3 C7 B8 L8 n - __IO uint32_t TXBCIE; : I2 a* D4 u$ w6 z; j1 [/ l0 Y
- __IO uint32_t RESERVED6[2]; 5 z, \! O# g( }2 T
- __IO uint32_t TXEFC;
& V! [) R# O8 T' Y. w - __IO uint32_t TXEFS; ! G, U+ M. J0 |) l! }
- __IO uint32_t TXEFA;
/ |: B9 K6 ?( g - __IO uint32_t RESERVED7;
- Y9 g) l7 @/ i }5 D- Q) S - } FDCAN_GlobalTypeDef;
复制代码 : y" v& B3 D- c. S
这个结构体的成员名称和排列次序和CPU的寄存器是一 一对应的。
+ I. W$ t3 j/ [5 c1 l) q2 ~( P8 ?3 a& P) c N- V
__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:$ A/ O; Z2 U8 U5 O! W# S5 d. f
1 b$ ]! C/ [6 g5 M( W# Q6 L
- #define __O volatile /*!< Defines 'write only' permissions */
4 v6 @$ s5 T* ] k4 Q - #define __IO volatile /*!< Defines 'read / write' permissions */
复制代码 5 B# b) w* w! b" K3 s. h' e+ P
下面我们看下FDCAN的定义,在stm32h743xx.h文件。
7 k, y3 y; v" C" T$ E
4 Q+ o$ g; [/ U- #define PERIPH_BASE (0x40000000UL) ! `/ }( v4 u( t' b' _
- #define D2_APB1PERIPH_BASE PERIPH_BASE
* F5 F2 ^5 J" G0 m" _ - / c3 T8 U+ E$ g* P% v7 c
- #define FDCAN1_BASE (D2_APB1PERIPH_BASE + 0xA000UL)6 B ~ J; W2 g# X4 n
- #define FDCAN2_BASE (D2_APB1PERIPH_BASE + 0xA400UL)2 p) w' A1 g3 \4 Q! _0 x& t
- #define FDCAN_CCU_BASE (D2_APB1PERIPH_BASE + 0xA800UL)
. C% B& o) x! m! Y' M* H - ( T8 y1 n7 E2 p6 i
- #define FDCAN1 ((FDCAN_GlobalTypeDef *) FDCAN1_BASE) <----- 展开这个宏,(FDCAN_GlobalTypeDef *)0x4000A0009 ]9 v( \' L% I6 E1 a
- #define FDCAN2 ((FDCAN_GlobalTypeDef *) FDCAN2_BASE)
6 }8 K1 H( ?3 y/ E. X - #define FDCAN_CCU ((FDCAN_ClockCalibrationUnit_TypeDef *) FDCAN_CCU_BASE)
复制代码 # ? l6 H, d, g u- N" {# u
我们访问FDCAN1的CCCR寄存器可以采用这种形式:FDCAN1->CCCR = 0。( o# u% b: V) L! Y& ~0 \# h- T
7 Q9 Y/ b# u2 ? V6 X. E6 O- l/ A
91.3.2 FDCAN总线时间触发结构体TTCAN_TypeDef
8 Q8 F8 W2 X4 CFDCAN总线时间触发相关的寄存器是通过HAL库中的结构体TTCAN_TypeDef定义,在stm32h743xx.h中可以找到这个类型定义:! b+ o% \) |% m% }4 H0 c
4 p# u# T6 [, `0 f, H8 }
- typedef struct; T5 n% A1 G& o4 F
- {) y, r# R0 a4 F) i& W( B- D+ r2 F4 _
- __IO uint32_t TTTMC; /*!< TT Trigger Memory Configuration register, Address offset: 0x100 */
3 l$ b6 }; m. l1 A+ w - __IO uint32_t TTRMC; /*!< TT Reference Message Configuration register, Address offset: 0x104 */
6 i0 k! C7 B0 @ - __IO uint32_t TTOCF; /*!< TT Operation Configuration register, Address offset: 0x108 */$ I! d$ K2 |0 U5 \0 X3 W9 x* T
- __IO uint32_t TTMLM; /*!< TT Matrix Limits register, Address offset: 0x10C */9 E% H+ Z. |9 Z% ]- u! O- j
- __IO uint32_t TURCF; /*!< TUR Configuration register, Address offset: 0x110 */7 e8 m- F5 `. q2 U) w0 ^; H( B
- __IO uint32_t TTOCN; /*!< TT Operation Control register, Address offset: 0x114 */% n( y' F* ^# e' o7 y4 P& S5 p
- __IO uint32_t TTGTP; /*!< TT Global Time Preset register, Address offset: 0x118 */
. v8 a9 l( C' y. X; B! g - __IO uint32_t TTTMK; /*!< TT Time Mark register, Address offset: 0x11C */
, @5 W! @0 R# K( H- L# C - __IO uint32_t TTIR; /*!< TT Interrupt register, Address offset: 0x120 */
% p9 n* ~. n+ z+ w" y# s% N - __IO uint32_t TTIE; /*!< TT Interrupt Enable register, Address offset: 0x124 */
. Q$ x% k7 O: \8 |4 Z - __IO uint32_t TTILS; /*!< TT Interrupt Line Select register, Address offset: 0x128 */( `; o4 E0 }5 ?8 F. |3 |
- __IO uint32_t TTOST; /*!< TT Operation Status register, Address offset: 0x12C */6 h4 a( `2 k/ [" X
- __IO uint32_t TURNA; /*!< TT TUR Numerator Actual register, Address offset: 0x130 */& r5 Q6 |+ D2 Q3 E" R. d `
- __IO uint32_t TTLGT; /*!< TT Local and Global Time register, Address offset: 0x134 */
3 X1 a$ P6 w- j; C - __IO uint32_t TTCTC; /*!< TT Cycle Time and Count register, Address offset: 0x138 */- B6 m) \4 d2 [$ s( G3 T
- __IO uint32_t TTCPT; /*!< TT Capture Time register, Address offset: 0x13C */
; P; s+ h1 B6 ^+ T, E& V" L - __IO uint32_t TTCSM; /*!< TT Cycle Sync Mark register, Address offset: 0x140 */4 ?( t/ a3 O* [4 V5 R
- __IO uint32_t RESERVED1[111]; /*!< Reserved, 0x144 - 0x2FC */
, X* V! }% U9 W2 f - __IO uint32_t TTTS; /*!< TT Trigger Select register, Address offset: 0x300 */' R# h% n3 H0 `6 I% S% W
- } TTCAN_TypeDef;
复制代码
9 z1 d6 h, F( G. v; D91.3.3 FDCAN总线初始化结构体FDCAN_InitTypeDef: x1 ]3 {+ _9 D! `$ j
下面是FDCAN总线的初始化结构体:
0 k7 p+ V* q* r( y& P0 {
1 j6 Z/ L! n* Q1 d) H7 X9 W S- typedef struct
& p; `9 T1 X1 c# [% `1 k9 h$ X+ q - {
$ C1 K3 P% e( x- U2 p - uint32_t FrameFormat; /*!< Specifies the FDCAN frame format.( k% h2 {- B: b X# O* H
- This parameter can be a value of @ref FDCAN_frame_format */4 h8 M+ W7 [8 d6 C
6 S6 z4 }$ B8 ^7 b- uint32_t Mode; /*!< Specifies the FDCAN mode.5 A; P* I% t5 r1 i9 R. Q N
- This parameter can be a value of @ref FDCAN_operating_mode */6 z. B1 X& M! A4 W4 P! ]
- 9 A X( @) U1 f9 ]6 k' z$ D
- FunctionalState AutoRetransmission; /*!< Enable or disable the automatic retransmission mode.# X5 M8 V5 A1 H& k
- This parameter can be set to ENABLE or DISABLE */
* W( Y$ }0 F/ h) g - + Y) W" ]% l! s! U- T) w* h6 X2 u
- FunctionalState TransmitPause; /*!< Enable or disable the Transmit Pause feature.! h' W y' u0 c9 p
- This parameter can be set to ENABLE or DISABLE */
9 z( E. T5 L) P# a3 I
* J4 e" c) d& R |; e# O- FunctionalState ProtocolException; /*!< Enable or disable the Protocol Exception Handling.$ F( N1 J5 F- W3 U
- This parameter can be set to ENABLE or DISABLE */, d1 ^9 v' l( F2 d Z. x
- ; ^) M& L6 r# j. b7 q
- uint32_t NominalPrescaler; /*!< Specifies the value by which the oscillator frequency is
6 g7 n; E) D$ O d L8 Q4 g0 i - divided for generating the nominal bit time quanta.
! R* p6 R! Q/ g0 w+ @# d' @3 L - This parameter must be a number between 1 and 512 */
, D [* A; P3 z! A8 x
$ ]% A7 G0 W& p! M& B- uint32_t NominalSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN
, H- w' a8 X. ?; k" K2 f) F - hardware is allowed to lengthen or shorten a bit to perform
' d5 [( y/ C( \( C) T - resynchronization.# m' y# v# z/ H% `( Q' e
- This parameter must be a number between 1 and 128 */
8 V' L! n+ s+ _( ?. D8 H - 8 n7 r- G" X7 h
- uint32_t NominalTimeSeg1; /*!< Specifies the number of time quanta in Bit Segment 1.9 Y8 L) H. V/ b: w% p1 |4 N* G7 _
- This parameter must be a number between 2 and 256 */
$ ]+ ] n* E3 K/ Z6 J+ y - , e) C& H4 s! n
- uint32_t NominalTimeSeg2; /*!< Specifies the number of time quanta in Bit Segment 2.! w+ y; n w5 H8 V7 G6 }
- This parameter must be a number between 2 and 128 */
0 Y6 R2 V+ e; @9 ` - . ]3 s# f+ m# ^
- uint32_t DataPrescaler; /*!< Specifies the value by which the oscillator frequency is2 K9 H0 }* I+ ?, y/ x
- divided for generating the data bit time quanta.+ c# C8 `- _; K
- This parameter must be a number between 1 and 32 */2 m4 \* V2 H+ F: g2 g3 w
- " A) ^& D( B/ _; h
- uint32_t DataSyncJumpWidth; /*!< Specifies the maximum number of time quanta the FDCAN% v0 F5 M9 B' O# Q$ R
- hardware is allowed to lengthen or shorten a data bit to F7 n |7 w0 A' U5 w
- perform resynchronization.
. _3 h8 `) S; v7 k) a0 d' Z - This parameter must be a number between 1 and 16 */7 j9 M- p! l5 z! S+ z
- 1 z: B; i1 f/ s5 X8 Z
- uint32_t DataTimeSeg1; /*!< Specifies the number of time quanta in Data Bit Segment 1.
8 x" x3 O' T0 Y2 F+ Z/ _ - This parameter must be a number between 1 and 32 */- }! B3 k# G* h
- + R' U# B! r6 }
- uint32_t DataTimeSeg2; /*!< Specifies the number of time quanta in Data Bit Segment 2.* l8 u/ m" l1 d0 E% o+ p/ W$ u3 p* }
- This parameter must be a number between 1 and 16 */
- @' @- K% @# \3 T* K - , k" B3 E3 z5 j" `5 N. ?1 Q Y' m( K
- uint32_t MessageRAMOffset; /*!< Specifies the message RAM start address.
8 P% a6 t( @, p3 \9 d - This parameter must be a number between 0 and 2560 */
+ D ~ @# \+ z0 ^5 T - - [+ A( {6 S8 F5 S' E
- uint32_t StdFiltersNbr; /*!< Specifies the number of standard Message ID filters." V6 \; k8 E- M# j& P" W$ U) A
- This parameter must be a number between 0 and 128 */. a1 f9 \! s0 p7 W/ s' _3 X
/ F1 {* K+ R9 V8 g1 H* {, u) y# ]- uint32_t ExtFiltersNbr; /*!< Specifies the number of extended Message ID filters.
' u, b; o- V7 f0 v' f! ^6 d# \ - This parameter must be a number between 0 and 64 */
! d: c6 k, m6 T) | - ' o; x( O; {( }6 v
- uint32_t RxFifo0ElmtsNbr; /*!< Specifies the number of Rx FIFO0 Elements.
/ z- D% C9 Q3 x, @ - This parameter must be a number between 0 and 64 */- Z2 M# M3 R3 K" X% u; g! ^
8 ^! \) q2 q. c* \% W w- uint32_t RxFifo0ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 0 element.
% Y/ P ?% L( z$ M, ^ - This parameter can be a value of @ref FDCAN_data_field_size */
# k" p+ b( L9 ~9 D% v: h - & F. t; Y3 E' R2 z) I7 ~
- uint32_t RxFifo1ElmtsNbr; /*!< Specifies the number of Rx FIFO 1 Elements.
+ F# b; @- M7 U- d4 { - This parameter must be a number between 0 and 64 */: n* p" l* f$ t' Z! O. q
- + P- G! h/ w* W( x( m5 H
- uint32_t RxFifo1ElmtSize; /*!< Specifies the Data Field Size in an Rx FIFO 1 element.. l4 ~" |* M7 o, k1 R
- This parameter can be a value of @ref FDCAN_data_field_size */
! m' } p% A6 |, o" B1 w2 B* V2 @
- q3 j* w4 h8 S) }: [( T2 Y1 @- uint32_t RxBuffersNbr; /*!< Specifies the number of Dedicated Rx Buffer elements.
, [! Y2 R% e% k# M3 D& q! L - This parameter must be a number between 0 and 64 */
: R; D- L2 \3 y4 [' J0 u
. Y+ q$ _. s7 W+ ^0 I+ O8 z- uint32_t RxBufferSize; /*!< Specifies the Data Field Size in an Rx Buffer element.
6 u( X8 Q( h( @9 ~4 h1 v - This parameter can be a value of @ref FDCAN_data_field_size */
- s5 S4 L+ |3 u
- r" u: p% D7 h# @0 ^5 q6 d$ ]- uint32_t TxEventsNbr; /*!< Specifies the number of Tx Event FIFO elements.7 O4 C' L9 \4 M" B2 H
- This parameter must be a number between 0 and 32 */
0 W# n0 Q5 i. u( B9 p
& v7 M2 A8 X0 Z# w& B& m- uint32_t TxBuffersNbr; /*!< Specifies the number of Dedicated Tx Buffers.4 ?2 j( s# w/ f( ]; e/ F& Q0 K
- This parameter must be a number between 0 and 32 */# Q0 ^) o5 A9 \" v
! s. h/ _0 q$ c' r S3 L- uint32_t TxFifoQueueElmtsNbr; /*!< Specifies the number of Tx Buffers used for Tx FIFO/Queue.- U/ J8 T1 u; T
- This parameter must be a number between 0 and 32 */! g8 Z& S* s# c+ m Z0 d
- 9 S* Q0 z, h4 C. T
- uint32_t TxFifoQueueMode; /*!< Tx FIFO/Queue Mode selection.
0 q# {+ G& q k+ U1 d - This parameter can be a value of @ref FDCAN_txFifoQueue_Mode */
1 l. ]6 r4 d2 a X$ y( s# c
) f( _; `; F8 }' R2 f- uint32_t TxElmtSize; /*!< Specifies the Data Field Size in a Tx Element.3 s5 _$ B" I6 j& ]
- This parameter can be a value of @ref FDCAN_data_field_size */! V5 m% y; |- D3 K" J U
- ! K/ h/ z- ?- k1 t$ n0 |0 M! F+ g
- } FDCAN_InitTypeDef;
复制代码 ( K+ C+ ?. \7 q# B
下面将结构体成员逐一做个说明:
* N3 X ~! y0 o8 ~: w6 l- N7 |1 t+ E( s) c9 U' O8 e" k
FrameFormat
, U' |! U4 P3 y用于设置CAN帧格式。' z) d: o/ ~5 L! j4 T$ D$ ^
7 ]3 J) l- j, M& _% ^- #define FDCAN_FRAME_CLASSIC ((uint32_t)0x00000000U) /* 经典CAN模式 */% E. l. C4 P9 [+ M, c. q0 \/ `
- #define FDCAN_FRAME_FD_NO_BRS ((uint32_t)FDCAN_CCCR_FDOE) /* FD CAN不带可变波特率 */+ p& H' |# z' X' Y. t
- #define FDCAN_FRAME_FD_BRS ((uint32_t)(FDCAN_CCCR_FDOE | FDCAN_CCCR_BRSE)) /* FD CAN带可变波特率 */
复制代码 8 e6 H) ^! \, B7 e
Mode
, \" K0 D8 C; Z0 T8 }- j用于设置CAN操作模式。
0 q& z& d7 x" z9 i; ?/ K' n2 h M( L9 }5 D
- #define FDCAN_MODE_NORMAL ((uint32_t)0x00000000U) /*!< 正常模式 */
$ W, p( v* H2 D, | W- j5 } F - #define FDCAN_MODE_RESTRICTED_OPERATION ((uint32_t)0x00000001U) /*!< 有限制的操作模式 */4 B* @9 z$ k# M: I8 d
- #define FDCAN_MODE_BUS_MONITORING ((uint32_t)0x00000002U) /*!< 总线监测模式 */
3 b7 R: G8 x, P" Z+ ^. { - #define FDCAN_MODE_INTERNAL_LOOPBACK ((uint32_t)0x00000003U) /*!< 内部环回模式 */4 Q! g3 m8 c: s9 w& y h4 C6 z& X5 S
- #define FDCAN_MODE_EXTERNAL_LOOPBACK ((uint32_t)0x00000004U) /*!< 外部环回模式 */
复制代码
6 t# J* g2 x" ~* b6 c5 t2 r) C. T G AutoRetransmission
: ]7 A9 Y$ p) {9 [. b0 _使能自动重传模式。! b, I% T: n% @ O4 u, R2 @6 g
2 o& m; u }( u$ {4 a# G/ i, I使能ENABLE或者禁止DISABLE。9 `8 U0 Q2 x2 P
' f; n# O& D3 L/ x. C& [ TransmitPause
1 e0 m0 v) N- W0 g使能或者禁止传输暂停特性。ENABLE使能或者DISABLE禁止。* j+ `& w- x8 m* g$ ^ A3 n
4 c. f7 O: |; B7 f$ D
ProtocolException. l: S/ k% j6 T
使能或者禁止协议异常管理。ENABLE表示使能,DISABLE表示禁止。
8 n; p# \8 p& w; m
% q' {3 @- ~! Y9 U NominalPrescaler
- P Q: Y; K; f: s% F: ^用于CAN FD仲裁阶段分频设置,产生标称位时间量,参数范围1-512。8 ~9 R: o0 h( F3 V7 Y( Q/ ^
! B4 p, v1 }' i: v NominalSyncJumpWidth' P* D3 H! z0 i$ N9 D7 r
设置FD CAN仲裁阶段最大支持的时间量来加长或者缩短一个bit来实现再同步,参数范围1-128。( J2 C! p' l2 p/ X: j
0 Q$ [, b4 g( Y
NominalTimeSeg1
1 L( j' B/ ~. i9 D设置仲裁阶段Bit Segment 1的时间量,范围2 – 256。. a! y6 c6 u# Z. r0 e0 N
! y. |5 u) V% I4 {7 P
NominalTimeSeg2% C$ y+ o2 W0 p. d
设置仲裁阶段Bit Segment 2的时间量,范围2 – 128。. T% d: @( \3 ?3 s# Z3 a1 Q+ m1 g
5 K$ s2 F. q. J+ w7 M9 v/ h2 ~7 Y) }
DataPrescaler
3 t1 J. \/ C: o! p8 F# B用于CAN FD数据阶段分频设置,范围1-32。
0 f& z6 e* W5 c
% J3 G8 m( G5 @9 y4 K2 f DataSyncJumpWidth& N$ t T* V- `% Z* @" ]
设置FD CAN数据阶段最大支持的时间量来加长或者缩短一个bit来实现数据再同步,参数范围1-16。( {9 B$ g, Q/ w- {0 }8 j1 i
7 V/ B/ p% R% X* \
DataTimeSeg1
( d9 L- ~+ E2 G, S4 a设置数据阶段Data Bit Segment 1的时间量,范围1 – 32。! |+ ]/ J6 V: S9 c u4 I
! x4 b/ ?: _' a+ C2 n DataTimeSeg2( }! _+ _! G+ X( ]4 H- G
设置数据阶段Data Bit Segment 2的时间量,范围1 – 16。
; L% E! [3 I4 p& c: t# g
5 A7 a/ k( _2 S# J( J MessageRAMOffset% C# R/ U$ c- e( d
设置消息RAM起始地址,范围0到2560。9 m3 { m+ Q6 k8 G$ @$ f3 {: s
5 w" S- y# q* a8 v7 A StdFiltersNbr
6 ~. H8 |* ~. Q4 C) U标准ID过滤个数,范围0到128。
/ |; X7 F* s0 x; b3 X0 `
; e: E4 y: G: h$ O ExtFiltersNbr
( } O T8 V5 H/ [. Y1 l1 _6 H扩展ID过滤个数,范围0到64。" u. ~' x% f# H
$ j; c. d p1 y/ r- r" A# n; D RxFifo0ElmtsNbr, j2 P( ^6 m# N$ Z! a: N b, Q0 [& }
RX FIFO0元素个数,范围0到64。& b | V) u$ X5 r
' _- f4 C/ A' K. c$ o$ E: L RxFifo0ElmtSize# O8 X# k8 X1 y- h
RX FIFO0每个元素中数据大小,支持参数如下:
# i7 D8 r8 |4 ? }% U" N* n! q0 k! C8 ]: ~
- #define FDCAN_DATA_BYTES_8 ((uint32_t)0x00000004U) /*!< 8 bytes data field */
# q% n4 I! l" Z0 V2 l - #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */, H2 G# N9 { H, E' M+ M
- #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
3 h/ I: S; r7 m. i- ]+ h - #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */ w$ i# h4 v% s% E# [' l1 _) C
- #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
1 ]$ R1 u) F5 m' b( d - #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
6 \: P: |1 `2 K( w4 c9 l - #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */- L- O, w( T4 Y4 D( M9 P3 F) i
- #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码
" Q. ?/ y# O2 G% p) | ? RxFifo1ElmtsNbr. i; ?2 Z+ c9 t. V' I' e: D
RX FIFO1个数,范围0到64。 H7 j$ _4 n/ u2 i8 U6 m+ F1 L
* Y8 {' I2 J0 s! h6 f3 l; e- S& a RxFifo1ElmtSize
$ G" q$ ]) w3 ]' y% f% B! w5 ZRX FIFO1每个元素中数据大小,支持参数如下:
7 z* t$ i @' q2 y. ~3 Z5 ^6 [* R0 k n4 y! Y6 _
- #define FDCAN_DATA_BYTES_8 ((uint32_t)0x00000004U) /*!< 8 bytes data field */
" q# O* ^3 H1 l - #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */) D9 H5 L3 a0 Q7 c/ T
- #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */: G8 n# r7 x9 R1 h# a* k: p
- #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */1 g$ }3 ]3 u K5 S8 Z1 q- d5 s
- #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
) j3 E. I0 V! i! O - #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */; N6 [( w, S0 l" \! K9 d, o& g
- #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
3 b) \7 K( L* e/ i( | [( w. ]( r9 I - #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码 . X7 t1 T8 G" ~* X
RxBuffersNbr
8 ~, [8 X5 I- E5 Z3 U设置Rx Buffer元素个数,范围0 - 64:1 O/ _! C2 {, a$ N; w* ^
c: I1 Z% O: i
RxBuffersSize
* y% d7 ?* N) R设置Rx Buffer元素中每个数据大小,范围0 - 64:
% ]+ b* r& H* K, t9 u' A7 g9 ?4 I) K2 U8 ^, _# s( P, K
- #define FDCAN_DATA_BYTES_8 ((uint32_t)0x00000004U) /*!< 8 bytes data field */) e/ f- ~ r1 V; { M
- #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field */
7 I; z9 G% y$ g, E8 [6 q8 J - #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */
) @4 Y8 t9 d) v9 V) f7 D5 {5 _+ b - #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */
* ~: h) {& {; W7 o - #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
h, u$ A a3 V5 z - #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
$ m* A' H; l# q9 [& P' H$ \: G* _ - #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
0 B! G/ E4 D0 ?# F2 `: V1 @4 I - #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码 3 R+ o! F6 i, O2 t0 W* Z7 l6 R
TxEventsNbr6 D4 a" o" l4 H) w8 ^7 `& R h' i
Tx Event FIFO元素个数,范围0到32。( l9 I* O0 {1 Q6 a# a
9 W! r, D; a6 Y! y7 A7 O A TxBuffersNbr6 L- p2 f# K1 a# E0 k' D
设置专用的Tx Buffer元素个数,范围0到32。5 z5 ^/ \& C: q
* L6 r/ e% e! ~: E! U3 B6 q TxFifoQueueElmtsNbr( H' S# L3 p, t
设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32。
7 C O: A: R1 J4 U4 q- f5 \$ P& t. o; Q4 [# ^
TxFifoQueueMode
' z: @! x* `" v) V5 G设置FIFO模式或者QUEUE队列模式。. m1 T) Q% W2 P$ x: a6 L
* f9 ?' m' b6 `0 }* g5 j5 A- h9 Q3 ?% l
- #define FDCAN_TX_FIFO_OPERATION ((uint32_t)0x00000000U) /*!< FIFO mode */
2 q f- d, y) N$ F1 `# j; @, u( s - #define FDCAN_TX_QUEUE_OPERATION ((uint32_t)FDCAN_TXBC_TFQM) /*!< Queue mode */
复制代码
3 t& U' f% t, t" ~& H+ t- n0 U TxElmtSize. e, H. v; j! @% X$ E5 N
设置Tx Element中的数据域大小。支持参数如下:: ?- _7 e' n0 O n5 d- O' z. x
3 w4 z9 E+ ~/ u
- #define FDCAN_DATA_BYTES_8 ((uint32_t)0x00000004U) /*!< 8 bytes data field */0 J. Z& J4 i- ~* ?
- #define FDCAN_DATA_BYTES_12 ((uint32_t)0x00000005U) /*!< 12 bytes data field *// E2 ~/ R9 l; i2 G
- #define FDCAN_DATA_BYTES_16 ((uint32_t)0x00000006U) /*!< 16 bytes data field */& }& S3 b0 l! v# d
- #define FDCAN_DATA_BYTES_20 ((uint32_t)0x00000007U) /*!< 20 bytes data field */2 E: z' r8 ]7 x
- #define FDCAN_DATA_BYTES_24 ((uint32_t)0x00000008U) /*!< 24 bytes data field */
; d- j2 e; k/ P2 I- w+ _ - #define FDCAN_DATA_BYTES_32 ((uint32_t)0x0000000AU) /*!< 32 bytes data field */
0 T* ?6 u/ ~$ H$ p9 f, j - #define FDCAN_DATA_BYTES_48 ((uint32_t)0x0000000EU) /*!< 48 bytes data field */
5 D7 E) ] _ m4 o# L9 M! } - #define FDCAN_DATA_BYTES_64 ((uint32_t)0x00000012U) /*!< 64 bytes data field */
复制代码 0 T4 x! l- X1 t' _
91.3.4 FDCAN总线消息RAM地址FDCAN_MsgRamAddressTypeDef
) d6 R8 h" r6 Y3 G9 t下面是消息RAM结构体:. k9 \! |2 x+ |; P) k
- 4 r2 P7 b) w5 N/ L1 x# q# I
- typedef struct3 Y" Y# ^8 s6 Y' A; d } z, K
- {& a9 n: W; @9 N$ x3 q) u
- uint32_t StandardFilterSA; /*!< Specifies the Standard Filter List Start Address.
. m7 h8 M7 K1 p7 g1 B7 e$ w0 w - This parameter must be a 32-bit word address */
/ k P6 Z7 w) g2 z8 q - . B; n3 d: O* R* ~9 X
- uint32_t ExtendedFilterSA; /*!< Specifies the Extended Filter List Start Address.9 t5 x. _! ~0 C( T' f- T0 m
- This parameter must be a 32-bit word address */$ o' y! i8 l5 g- H8 j+ M; g/ t0 V
) P6 U- B6 j) r* O' Q- uint32_t RxFIFO0SA; /*!< Specifies the Rx FIFO 0 Start Address.; ?0 c L" t& P% D5 [% o, A
- This parameter must be a 32-bit word address */
7 o4 B/ K6 ?& I- K: Q7 N
/ |5 I4 j6 v ~) C- Q4 f! }: V- uint32_t RxFIFO1SA; /*!< Specifies the Rx FIFO 1 Start Address.
1 y* z6 ]7 R7 w ~ - This parameter must be a 32-bit word address */# q2 L0 O6 Z \. H! m* z
- . |0 I8 Z# F- o$ Z; f: S
- uint32_t RxBufferSA; /*!< Specifies the Rx Buffer Start Address.
7 w! x" `0 `, l* g! n0 j - This parameter must be a 32-bit word address */0 F, P& q2 \! v# J& O
- $ x2 M1 U- a/ G5 H F; o
- uint32_t TxEventFIFOSA; /*!< Specifies the Tx Event FIFO Start Address.
1 o! ]* {0 ~" C% e4 ^. p - This parameter must be a 32-bit word address */0 ^; g4 C1 F: s0 M& }( n% w
( v( j2 K4 D6 P' E6 V; Y8 E; t- uint32_t TxBufferSA; /*!< Specifies the Tx Buffers Start Address.
; N/ F' Q5 k7 ^2 H" U) L3 @ - This parameter must be a 32-bit word address */2 \, D N/ v) K9 ^- `+ w. @
* Y) \ Z% V1 b- uint32_t TxFIFOQSA; /*!< Specifies the Tx FIFO/Queue Start Address.: X: V; H) N: x% K0 g
- This parameter must be a 32-bit word address */
5 s7 E% X/ ?& l% n h' _$ ~' a' \ - . M7 x) Q1 s6 L
- uint32_t TTMemorySA; /*!< Specifies the Trigger Memory Start Address.
2 ?$ j) a. C" W7 X' q - This parameter must be a 32-bit word address */
; c% v$ c4 _0 m" F% |5 n3 b
! s* A' v1 j; ` P9 y- uint32_t EndAddress; /*!< Specifies the End Address of the allocated RAM.
% O' K! l' _2 y0 ~) n) ] - This parameter must be a 32-bit word address */
: x, P. T6 z7 s8 `6 a
6 Z7 z+ d4 Q4 ]! i- j) H- } FDCAN_MsgRamAddressTypeDef;
复制代码 ' I8 O* O; h& c
下面将结构体成员逐一做个说明:! d. V3 e" o+ v/ f
( H5 h* C" f' [' G/ k0 ] StandardFilterSA1 _( v! L8 @3 f" \7 |
设置标准过滤器起始地址,必须是32bit地址。$ N" w6 X6 I+ f6 l0 ~9 ?; k, b* e3 M0 x
1 s. E* X4 ^7 {/ ]$ [ ExtendedFilterSA9 {# F( T3 Q$ T& I; E
设置扩展过滤器起始地址,必须是32bit地址。$ Q& Q+ z/ s3 }% h% l7 U
( m' F3 y8 ]5 @' m! J
RxFIFO0SA
) a: s6 q/ `9 g/ R7 J7 t设置RX FIFO 0起始地址,必须是32bit地址。 [4 ], Y/ m. L1 W. g* {0 L
% W, E/ F* Z) q3 q; r, g RxFIFO1SA N3 s, H, j3 |/ J+ q1 a: e
设置RX FIFO 1起始地址,必须是32bit地址。/ }0 G; l3 `* P6 l7 d+ J5 s& Y
' a A4 B1 \( q) q) H$ G3 z
RxBufferSA/ D9 V- [8 k" X* d9 f0 a
设置RX Buffer起始地址,必须是32bit地址。. q% J- W) s; I( _ i$ H# c! n
, l1 I) F: Q/ i4 m, a, j" x
TxEventFIFOSA
/ D9 }+ [- Y# Z0 U. _% X U+ B' T设置Tx Event FIFO起始地址,必须是32bit地址。: @$ n& k+ l; w: j2 z- F& J# z
. x7 T& a v0 ~/ W A% `" B$ h# e& x6 @ TTMemorySA
5 D4 c* [8 c% y! V( c设置触发内存起始地址,必须是32bit地址。% N' r# _+ |0 n1 e6 W
! L# A. h6 ]( \' V
EndAddress
i1 g- P( O5 r; I设置申请RAM空间的结束地址,必须是32bit地址。
) J( `8 D8 ~ s& w) N
% z8 c Z0 |3 L4 |% c& s/ X) I( j91.3.5 FDCAN总线过滤结构体FDCAN_FilterTypeDef3 f. u3 J, V! m4 l0 r# P
下面是过滤结构体:2 { |: i C5 n! M/ G' P1 v
3 O+ }1 n; ?3 w/ _, X* J$ L9 L
- typedef struct" N9 h1 ]1 c" d, i8 y
- {
. M3 ~7 S8 i, b' @ @! K, U. Q - uint32_t IdType; /*!< Specifies the identifier type.1 f6 v# H U# p& D) n, C9 S
- This parameter can be a value of @ref FDCAN_id_type */" n$ n6 u- A$ x d4 L2 f6 a
- $ _5 A( Z) H+ J/ G' w( u3 l
- uint32_t FilterIndex; /*!< Specifies the filter which will be initialized.
& h9 e4 H& `; J/ M8 y. s - This parameter must be a number between:+ x: D# l/ \" t4 n
- - 0 and 127, if IdType is FDCAN_STANDARD_ID
3 V3 P+ Q1 y/ J# W) w! R - - 0 and 63, if IdType is FDCAN_EXTENDED_ID */* A# Y% p9 N1 u0 R* i2 E
- / x9 b( l5 Q: |- N5 \( H
- uint32_t FilterType; /*!< Specifies the filter type.
x: Y9 h# p8 B8 I" K - This parameter can be a value of @ref FDCAN_filter_type.4 e7 ?0 H1 E, I5 T( G) R
- The value FDCAN_EXT_FILTER_RANGE_NO_EIDM is permitted1 {) i N. F0 K5 g- l+ G
- only when IdType is FDCAN_EXTENDED_ID.0 b3 |7 Z# p( |2 f' N. G! y
- This parameter is ignored if FilterConfig is set to
- p6 h3 f. J) L - FDCAN_FILTER_TO_RXBUFFER */
9 }5 G& b% o. h
5 {9 [6 W, i2 K* B1 o" I- uint32_t FilterConfig; /*!< Specifies the filter configuration.: x0 m( J( T* h/ A% J! A5 N0 ~
- This parameter can be a value of @ref FDCAN_filter_config */+ O& x& z: {9 s9 Y3 V) C! O# A4 M
- % Q& B/ N9 l( @* M' k" j% A4 [
- uint32_t FilterID1; /*!< Specifies the filter identification 1.
8 Q, ]* p0 p: v3 I9 F% _2 r - This parameter must be a number between:- B5 K6 H( x- ]# N4 P
- - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID) ?5 m) Q0 [/ `, A+ N
- - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */0 u! z) e$ Y9 F# A7 e
- & j7 W g% T$ f I0 t: V" `
- uint32_t FilterID2; /*!< Specifies the filter identification 2.) C( t9 t u" T2 i: m. @
- This parameter is ignored if FilterConfig is set to
1 n1 x7 n: a6 D( O& y - FDCAN_FILTER_TO_RXBUFFER.
3 B2 |7 m7 U6 f2 C0 p& B& U& C" e, s - This parameter must be a number between:* Y" b6 f) q/ Q6 }/ u- ?/ l( `8 t
- - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID/ J5 A# C7 G6 q5 r! \ D
- - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */
* d. f/ Z+ e% U# Q" p
* i P. ^) h. J* h5 ^- uint32_t RxBufferIndex; /*!< Contains the index of the Rx buffer in which the
6 h" x/ q2 L" W3 A, q5 o. D - matching message will be stored.
3 U( _( S/ ]. | - This parameter must be a number between 0 and 63./ e5 c O/ b- U
- This parameter is ignored if FilterConfig is different
$ u" y) R. {7 Y; M# | - from FDCAN_FILTER_TO_RXBUFFER */
" F7 ~: U- u) V% J% u$ S/ B
4 L" |& W1 ~: `6 M* F. y& a- uint32_t IsCalibrationMsg; /*!< Specifies whether the filter is configured for3 K) T7 S% l; L A5 i- A% h3 n' v
- calibration messages.
* _- H2 {9 f5 Q) d1 J3 R - This parameter is ignored if FilterConfig is different d7 u9 f# c3 A. L( E4 d6 J$ b
- from FDCAN_FILTER_TO_RXBUFFER.# J/ y& r3 ] \7 i- e
- This parameter can be:9 H! W8 h o6 J6 [, i/ ~* e) i# x
- - 0 : ordinary message
3 P: o3 w3 C3 L" [9 W {/ } - - 1 : calibration message */
: I: Q8 H2 T% Q/ Q9 X; j% B+ y& }
9 G2 ?: u2 {3 ~% M( ^' {2 u9 Q- } FDCAN_FilterTypeDef;
复制代码
% y) Q% b% N' N. r' l IdType; g+ r3 T5 g# c1 Q+ C- h l
用于设置标准ID和扩展ID。
( X' O0 A, N3 B5 ~& s
0 l, l0 P& t k! {; P) M- #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */( F4 z9 [9 Q, F; ~, c3 Y
- #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码 3 `) V- y) e- y0 }9 u0 _5 Y, c
FilterIndex2 e" `0 ~" G; m, q- c }
用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64。
, E7 `; T1 e0 _8 j2 h; U: e
5 o3 l' o, a' M) \ FilterType `& p: L8 F( A
用于设置过滤类型。如果成员FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,本参数将不起作用。' v. t( A8 u8 O2 Q
8 O! y( ?3 k8 d; F& H d
- #define FDCAN_FILTER_RANGE ((uint32_t)0x00000000U) /*!< 范围过滤从FilterID1 到 FilterID2 */- v& f R8 W5 J. K8 n
- #define FDCAN_FILTER_DUAL ((uint32_t)0x00000001U) /*!< 专用ID过滤,FilterID1 或者FilterID2 */
2 [4 S5 d. x ^- W, U8 j7 [% ^
+ L* s" u, ]% P- d- /*!< 精度屏蔽过滤,FilterID1 = filter, FilterID2 = mask */ R3 Y/ Z) A* C! {( ?: {( I
- #define FDCAN_FILTER_MASK ((uint32_t)0x00000002U)
, m+ D; ^' [1 U* b% J1 R - 6 [7 [* P3 j3 q4 u9 m
- /*!< 仅ID扩展模式支持此参数,范围从FilterID1 到 FilterID2, EIDM mask not applied */# ~+ H4 U V4 _0 W, Y4 k. u; v8 B
- #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U)
复制代码 5 y9 c3 h2 {9 d
FilterConfig
( i) ^6 P! s6 ~$ ^- _/ L用于设置过滤类型。
1 V _" |; y4 \: z$ `# J; J6 q
, v6 x3 j1 h3 v5 J' \- #define FDCAN_FILTER_DISABLE ((uint32_t)0x00000000U) 禁止过滤
* O1 M1 ?* Z/ N - #define FDCAN_FILTER_TO_RXFIFO0 ((uint32_t)0x00000001U) 如果过滤匹配,将数据保存到Rx FIFO 0
" E7 ~+ T. t* s2 K* j. g, s6 B - #define FDCAN_FILTER_TO_RXFIFO1 ((uint32_t)0x00000002U) 如果过滤匹配,将数据保存到Rx FIFO 1
8 c1 Y0 U' P& a9 K: x- y6 _/ [: l' A - #define FDCAN_FILTER_REJECT ((uint32_t)0x00000003U) 如果过滤匹配,拒绝此ID
1 t1 E+ s5 a/ y: `3 W; ~" {) p% h - #define FDCAN_FILTER_HP ((uint32_t)0x00000004U) 如果过滤匹配,设置高优先级, x2 J2 W) P4 S4 g
- #define FDCAN_FILTER_TO_RXFIFO0_HP ((uint32_t)0x00000005U) 如果过滤匹配,设置高优先级并保存到FIFO 0
: X& T! @7 K5 q6 e( Z1 N - #define FDCAN_FILTER_TO_RXFIFO1_HP ((uint32_t)0x00000006U) 如果过滤匹配,设置高优先级并保存到FIFO 1& p( U& R; F; Y& J
- #define FDCAN_FILTER_TO_RXBUFFER ((uint32_t)0x00000007U) 如果过滤匹配,保存到Rx Buffer,并忽略FilterType
复制代码 ! j& {' z3 _! `( L8 Q: |( d6 R5 w
配置
% Y4 I- m3 W2 O, }7 d FilterID1
( ~7 l o7 J* s/ q& z用于设置过滤ID1。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。( c4 I% e9 b1 M8 f9 b7 H1 [
& `2 L" X# _ G4 t/ a/ ^+ x FilterID2
~" Y/ l5 P- e3 K! [用于设置过滤ID2。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。如果ID类型是FDCAN_STANDARD_ID,范围0到0x7FF。如果ID类型是FDCAN_EXTENDED_ID,范围是0 到0x1FFFFFFF。4 ?) v- t# V7 K4 M
: K) z* n% V' o8 t RxBufferIndex
1 c8 k/ ^( ~/ j匹配消息存储到Rx buffer中的索引。参数范围0到63。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。0 ~, E1 ^! Y G* L1 k$ w0 H+ _
- I* D s: b" T% X5 L( y" m" |
IsCalibrationMsg
1 n1 @7 z& S" |' \) l* [) @用于设置是否配置校准消息。如果FilterConfig设置为FDCAN_FILTER_TO_RXBUFFER,此参数不起作用。
+ z C Q5 ?/ V6 l |) e1 w6 G+ \+ B. h
0 : 表示正常消息。
) `- E/ g3 J' e9 l* V' O7 D( N7 e! J# A& q; |
1 : 标志校准消息。
' I7 r& X6 X# h+ F: p9 S- e1 b6 @3 v3 [* }
91.3.6 FDCAN总线消息发送结构体FDCAN_TxHeaderTypeDef
$ d# I, m; T4 {! u/ `下面是CAN FD发送消息结构体:
% N) ?! u& q) J( x/ Q
+ p* v5 z1 V: X8 ?) K- typedef struct5 q! n& t' x6 k/ x: \1 M, J( _6 I
- {4 H3 X) G. J2 q+ i; E" Q
- uint32_t Identifier; /*!< Specifies the identifier.1 s- Z' C" r% r: W- T7 Z. A
- This parameter must be a number between:: C2 P. e! C5 c) u
- - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID# j- b! x( [( v, n
- - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */
( W+ b w3 F u# \: ]/ Q- G - ' o9 [, |2 T" l& C# H
- uint32_t IdType; /*!< Specifies the identifier type for the message that will be
4 K* W& s% ^7 T W& O3 c - transmitted.9 S' @$ F& c: x- f
- This parameter can be a value of @ref FDCAN_id_type */
- h$ }) e8 W' I6 c
5 \5 Y2 }8 J9 |2 h5 T. N- uint32_t TxFrameType; /*!< Specifies the frame type of the message that will be transmitted.% l3 g2 L# S" V
- This parameter can be a value of @ref FDCAN_frame_type */
2 `3 E5 m( E/ ^! n1 ^ - * B2 G8 B9 w o# _
- uint32_t DataLength; /*!< Specifies the length of the frame that will be transmitted.
$ ]/ f8 X4 O8 q$ X - This parameter can be a value of @ref FDCAN_data_length_code */4 S s) a- q3 \$ u
- # x9 R1 @) K" R
- uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator. r( K+ N5 G1 S) g- K: ?" u1 n
- This parameter can be a value of @ref FDCAN_error_state_indicator */# K( @6 c7 U1 L# l$ a+ g
8 c2 ^% V# G0 l3 p O- uint32_t BitRateSwitch; /*!< Specifies whether the Tx frame will be transmitted with or without
& s) ?2 a# [- Q2 H7 ] - bit rate switching.
) [0 h, y" G* v! _+ ^3 Z - This parameter can be a value of @ref FDCAN_bit_rate_switching */
: ~2 {' i9 W. I. _ }% u7 s9 x- y - # @( }% D' U+ b8 q9 I8 V4 o
- uint32_t FDFormat; /*!< Specifies whether the Tx frame will be transmitted in classic or g: i2 B! o; {% {" _7 D
- FD format.
% j# K6 X$ D7 D B3 { - This parameter can be a value of @ref FDCAN_format */
p7 z5 a; u9 d0 x' x7 X l - . B' }: G$ H% H' B
- uint32_t TxEventFifoControl; /*!< Specifies the event FIFO control.- P* I- N3 ?" ]
- This parameter can be a value of @ref FDCAN_EFC */
" w* K! |/ @! M0 [+ r# ~
8 j) P+ q) h! @% i( j/ }- uint32_t MessageMarker; /*!< Specifies the message marker to be copied into Tx Event FIFO0 A# a+ D/ a w1 |7 r
- element for identification of Tx message status.8 h. X" k) ~/ H4 j2 j* h+ ~
- This parameter must be a number between 0 and 0xFF */
: s2 f$ ?7 x4 T2 E% W" v# `- I - * ~; P. b/ Q; H5 H1 [7 n
- } FDCAN_TxHeaderTypeDef;
复制代码
) D3 C. E, {% M( @9 T. N Identifier b; A d }( r+ C
用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
5 \, N, Y0 J1 v& v( I6 F9 U/ g' Q7 A, I
IdType
3 w9 _7 t+ @$ P# B+ L7 ^用于设置标准ID或者扩展ID。; ^7 r+ f j, q6 f! |) [* \. ?
# q7 G1 O" C. L1 x$ y$ G7 j- #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
$ |7 d; `0 }6 j& L- I D2 P7 S1 b. S - #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码 % C5 H( k! f R- G& r
TxFrameType- D J# l' L- W; U( E0 n
用于设置帧类型,数据帧或遥控帧。
0 H$ h' t/ M, k' a# l$ Z9 A3 d
# j; ]- \4 x! G6 w- #define FDCAN_DATA_FRAME ((uint32_t)0x00000000U) /*!< 数据帧 */
. j( B& m% s/ b- d5 a7 Y4 J - #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U) /*!< 遥控帧 */
复制代码
9 y3 `. b3 _* P$ E1 y% K0 F DataLength; }. k5 j% K* E6 b
用于设置数据长度。4 u; o( T, Z c$ _2 o( C h7 |
8 s* A" U2 [* [/ n1 J2 H/ `- #define FDCAN_DLC_BYTES_0 ((uint32_t)0x00000000U) /*!< 0 bytes data field */* r- A( ]2 d, z$ g
- #define FDCAN_DLC_BYTES_1 ((uint32_t)0x00010000U) /*!< 1 bytes data field */
5 J- E( R `" a" n - #define FDCAN_DLC_BYTES_2 ((uint32_t)0x00020000U) /*!< 2 bytes data field */
0 n6 _2 r+ I7 H% J. d. V( g - #define FDCAN_DLC_BYTES_3 ((uint32_t)0x00030000U) /*!< 3 bytes data field */1 j- T& G% j) V- R1 ~+ `. |* Y: N" D
- #define FDCAN_DLC_BYTES_4 ((uint32_t)0x00040000U) /*!< 4 bytes data field */1 }. c c3 N+ z1 v
- #define FDCAN_DLC_BYTES_5 ((uint32_t)0x00050000U) /*!< 5 bytes data field */) d8 o* }/ h$ l1 T8 X1 I
- #define FDCAN_DLC_BYTES_6 ((uint32_t)0x00060000U) /*!< 6 bytes data field */5 C: e+ Q5 p# t, w
- #define FDCAN_DLC_BYTES_7 ((uint32_t)0x00070000U) /*!< 7 bytes data field */- L+ V& S0 l+ H
- #define FDCAN_DLC_BYTES_8 ((uint32_t)0x00080000U) /*!< 8 bytes data field */
6 W& X" ~0 b7 |0 d* o - #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */
9 d' M2 [) P o; B - #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */- |$ b1 S J1 D1 e: K
- #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */3 H* q' I$ B8 R2 I8 ~
- #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */$ \7 [% ]. T; ^+ @' ?5 `
- #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */0 J: S- c9 l' K6 S0 R
- #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */0 I& r5 l5 S3 c* @0 I) ~" N1 }8 @) G
- #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
复制代码 3 x A6 n" v3 Y
ErrorStateIndicator- @$ q7 \3 {4 v# S7 r K0 P5 p
用于设置错误状态指示:% s2 A/ O, K. Y
$ `; d8 W! Q7 X$ b. K' }+ G- #define FDCAN_ESI_ACTIVE ((uint32_t)0x00000000U) /*!< 传输节点 error active */
' Q0 t' M# S# u' t2 I - #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码 ( M" s9 N( O A* D
BitRateSwitch1 P3 O/ H' a2 L6 i
用于设置发送是否波特率可变。
2 _4 E- a8 I& o' A
1 ]& j6 q3 R% x& f- #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN帧发送/接收不带波特率可变 */
; a9 ]" L. h9 F+ o2 C - #define FDCAN_BRS_ON ((uint32_t)0x00100000U) /*!< FDCAN帧发送/接收带波特率可变 */
复制代码 6 y$ D, S" K: v& j0 D' T
FDFormat
4 x4 A9 o- ? Q- \: Z用于设置发送帧是经典格式还是CANFD格式。
; }) q! }! t5 u( K: x- p- : O* n2 O6 k/ r5 n0 N! q
- #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 帧发送/接收使用经典CAN */
; x8 B* ~0 @6 |' h3 P2 Z7 ~4 R1 o - #define FDCAN_FD_CAN ((uint32_t)0x00200000U) /*!< 帧发送/接收使用FDCAN格式 */
复制代码
" j; [7 L) ~0 L7 m) h TxEventFifoControl* Z" Z c3 I9 f) y
用于设置发送事件FIFO控制。
' q0 Q" l4 k. v/ s6 Y
3 x/ H. D1 T0 e) w/ u% P5 M/ A- #define FDCAN_NO_TX_EVENTS ((uint32_t)0x00000000U) /*!< 不存储 Tx events */
9 \9 y! O5 B$ G0 S$ ? Y" }2 e - #define FDCAN_STORE_TX_EVENTS ((uint32_t)0x00800000U) /*!< 存储Tx events */
复制代码 + j3 Y8 I6 k4 x4 S
MessageMarker* Z: \8 a! L4 s1 \) `
用于设置复制到TX EVENT FIFO的消息Maker,来识别消息状态,范围0到0xFF。4 a: `$ ]1 k1 F
: m/ E) D" b# [6 L3 _* e: @91.3.7 FDCAN总线消息接收结构体FDCAN_RxHeaderTypeDef% u8 H* E6 U7 M: l* f# q; u7 r0 X
下面是CAN FD接收消息结构体:
2 }2 _3 ~( M Z( @8 d0 \; P% ]; |4 C2 h' w' B+ W
- typedef struct
& w, Z* t% C; F$ _7 ?3 r( ]: v - { G" P* [! H# k9 d; E R
- uint32_t Identifier; /*!< Specifies the identifier.7 d& g4 }* i3 y2 m* f
- This parameter must be a number between:0 H1 f n/ `! \1 i2 D6 G
- - 0 and 0x7FF, if IdType is FDCAN_STANDARD_ID
( r% f0 r1 U4 A( e a( Y+ C/ [ - - 0 and 0x1FFFFFFF, if IdType is FDCAN_EXTENDED_ID */
( n# k0 J/ T* Z$ n - - N$ _& b2 q' l4 l) ]' k" u! w: ~
- uint32_t IdType; /*!< Specifies the identifier type of the received message.+ G- N7 e. X8 y2 S* P
- This parameter can be a value of @ref FDCAN_id_type */7 k; F# @$ c' i
5 v( @% o6 D. V6 s- uint32_t RxFrameType; /*!< Specifies the the received message frame type.) i( ?6 f1 D. Y8 l) H
- This parameter can be a value of @ref FDCAN_frame_type */
1 {" p8 k9 C- N
5 M; H+ c' H) s5 E1 x2 t- o: d- uint32_t DataLength; /*!< Specifies the received frame length.
; T; F4 u! }" P0 k8 n: }- x7 T - This parameter can be a value of @ref FDCAN_data_length_code */
. }# N3 E0 A4 d; L) }% l" G& E - 0 |0 }! k0 ?+ u$ S9 A0 G
- uint32_t ErrorStateIndicator; /*!< Specifies the error state indicator.; y8 K* J2 F+ l! t
- This parameter can be a value of @ref FDCAN_error_state_indicator */
2 z8 \3 ?, Z, [& o: [% _3 N - 4 r- D! F4 ]$ t M
- uint32_t BitRateSwitch; /*!< Specifies whether the Rx frame is received with or without bit
# ^ F3 s2 ?8 w - rate switching.
0 G% |# Z! _$ ?. O/ B - This parameter can be a value of @ref FDCAN_bit_rate_switching */+ _* c6 W0 U4 [$ m! k1 @6 @* j
- ! X+ ]& n! {, N& g3 Z* a) k3 N
- uint32_t FDFormat; /*!< Specifies whether the Rx frame is received in classic or FD8 z5 J- V8 M/ y R5 w( \& M: c$ D
- format.8 s6 h' `4 B1 [: {/ F4 F1 P2 Y0 D
- This parameter can be a value of @ref FDCAN_format */
( {( z3 i E# i$ X8 E
/ P& H2 n) W2 |1 @" {0 r- uint32_t RxTimestamp; /*!< Specifies the timestamp counter value captured on start of frame; p Q/ Q9 g; k) H
- reception.
" }2 Z. T+ O5 U& w: X, k - This parameter must be a number between 0 and 0xFFFF */5 g! n1 E# e6 n4 _# g5 H6 x
- 3 q3 D2 `4 B7 i
- uint32_t FilterIndex; /*!< Specifies the index of matching Rx acceptance filter element.
+ }, u1 K2 e0 y0 | - This parameter must be a number between:% T/ d# r3 [1 ~
- - 0 and 127, if IdType is FDCAN_STANDARD_ID& {; u$ @5 W( M9 f2 i
- - 0 and 63, if IdType is FDCAN_EXTENDED_ID */% \9 t+ ?& y2 R& D, b1 D
- $ s. [1 m3 ^0 Y3 U9 w0 e* M" c* ~, d
- uint32_t IsFilterMatchingFrame; /*!< Specifies whether the accepted frame did not match any Rx filter.# A. r+ Y) u, f, Y% v. c7 x) G
- Acceptance of non-matching frames may be enabled via
1 a0 P q7 C+ B$ N% g - HAL_FDCAN_ConfigGlobalFilter().
; `$ ?, r( z/ g5 Z% M - This parameter can be 0 or 1 */
2 ]8 h+ z$ U8 h - 1 h+ r" W1 n6 a
- } FDCAN_RxHeaderTypeDef;
复制代码
$ w# l7 P2 d9 X+ J$ O; m6 K! ? Identifier
. Q; L: e! G5 B" s: o; m3 n) f用于设置ID,如果IdType是标准FDCAN_STANDARD_ID,范围0到0x7FF,如果IdType是FDCAN_EXTENDED_ID扩展ID,范围0到0x1FFFFFFF。
- s( w" X, Q/ q. v, {( h
, }" A3 F; K, a+ V5 H+ ? IdType
' u/ |" S8 p+ s8 o& ]' a用于设置标志ID或者扩展ID。
6 \- u; v. L4 \: R3 l9 b6 `
' C+ w) p5 r5 Z6 [$ j5 t% Z- #define FDCAN_STANDARD_ID ((uint32_t)0x00000000U) /*!< 标准ID */
4 ^. I3 h& ~5 C - #define FDCAN_EXTENDED_ID ((uint32_t)0x40000000U) /*!< 扩展ID */
复制代码
! v& V. h7 J4 m3 T4 D5 P% u: u/ Z( c7 J RxFrameType
- q) H5 o% S8 C' z$ \, c; A用于设置接收帧类型,数据帧或遥控帧' X3 s. U7 I, M4 T1 p5 q
$ g( `3 {6 y0 F r5 j- #define FDCAN_DATA_FRAME ((uint32_t)0x00000000U) /*!< 数据帧 */
+ I$ N- V7 e" H+ J - #define FDCAN_REMOTE_FRAME ((uint32_t)0x20000000U) /*!< 遥控帧 */
复制代码 : `% u2 C% i3 P
DataLength
8 ?; Z0 J# x, d2 g! ]$ v用于设置数据长度。+ _( a- L' ~' M$ |& H
# g0 Q( v( g2 H1 i2 h0 v% V
- #define FDCAN_DLC_BYTES_0 ((uint32_t)0x00000000U) /*!< 0 bytes data field */# F) `# _3 `2 |4 [5 A' E M. |
- #define FDCAN_DLC_BYTES_1 ((uint32_t)0x00010000U) /*!< 1 bytes data field */
7 O1 H/ q. r4 ]6 g( H1 ^ - #define FDCAN_DLC_BYTES_2 ((uint32_t)0x00020000U) /*!< 2 bytes data field */
5 ?+ _" H3 E' \0 M& C$ \% |& g. O - #define FDCAN_DLC_BYTES_3 ((uint32_t)0x00030000U) /*!< 3 bytes data field */9 o; ^6 _# c2 S
- #define FDCAN_DLC_BYTES_4 ((uint32_t)0x00040000U) /*!< 4 bytes data field */
; A, {* `0 n4 x" n6 D - #define FDCAN_DLC_BYTES_5 ((uint32_t)0x00050000U) /*!< 5 bytes data field */
6 \9 ~# T: _* x0 ] - #define FDCAN_DLC_BYTES_6 ((uint32_t)0x00060000U) /*!< 6 bytes data field */3 i0 `- R* W/ r. ^- ^5 U& W
- #define FDCAN_DLC_BYTES_7 ((uint32_t)0x00070000U) /*!< 7 bytes data field *// v. h0 B8 k# i4 Z# L2 Z, w, S
- #define FDCAN_DLC_BYTES_8 ((uint32_t)0x00080000U) /*!< 8 bytes data field */
+ z9 [! {5 t! |' c& {6 `9 a - #define FDCAN_DLC_BYTES_12 ((uint32_t)0x00090000U) /*!< 12 bytes data field */4 K. [9 I* z, |6 i+ I$ K
- #define FDCAN_DLC_BYTES_16 ((uint32_t)0x000A0000U) /*!< 16 bytes data field */! @5 U- @& ?) C7 r0 r0 k* E
- #define FDCAN_DLC_BYTES_20 ((uint32_t)0x000B0000U) /*!< 20 bytes data field */: S' u$ X+ ~ m# R
- #define FDCAN_DLC_BYTES_24 ((uint32_t)0x000C0000U) /*!< 24 bytes data field */+ N6 i @! o4 V
- #define FDCAN_DLC_BYTES_32 ((uint32_t)0x000D0000U) /*!< 32 bytes data field */
) j e/ _( J' D g9 u - #define FDCAN_DLC_BYTES_48 ((uint32_t)0x000E0000U) /*!< 48 bytes data field */. T' [, d6 O7 p" [' a$ X
- #define FDCAN_DLC_BYTES_64 ((uint32_t)0x000F0000U) /*!< 64 bytes data field */
5 Q5 K0 H. ^( `7 l5 E - ErrorStateIndicator
复制代码 \$ E7 Y p. x$ J
用于设置错误状态指示:% t/ [9 L' ~+ P0 z; }6 z2 r
* }) V. q0 i( x9 ]
- #define FDCAN_ESI_ACTIVE ((uint32_t)0x00000000U) /*!< 传输节点error active */( _4 \/ G* }/ X( y. O s
- #define FDCAN_ESI_PASSIVE ((uint32_t)0x80000000U) /*!< 传输节点error passive */
复制代码
0 O: X% I$ M7 y" i* f$ {# g BitRateSwitch2 x, n8 B# U" [ B- L! f
用于设置接收是否带波特率切换
3 K; N# C6 k2 j9 i# S( m& \ K: o* Y
- #define FDCAN_BRS_OFF ((uint32_t)0x00000000U) /*!< FDCAN 帧发送/接收不支持波特率可变*/
+ w2 \# ?8 X2 d! J+ Z/ z0 F0 K - #define FDCAN_BRS_ON ((uint32_t)0x00100000U) /*!< FDCAN 帧发送/接收支持波特率可变 */
复制代码
( `( b {' ^+ T2 G, e FDFormat
/ W6 p* s9 |, P5 i5 F用于设置接收帧是经典格式还是CANFD格式
\& P: F' m* \7 E- }* R- W
- a2 U5 x& S( J& U' y/ q- #define FDCAN_CLASSIC_CAN ((uint32_t)0x00000000U) /*!< 经典帧 */% g ]6 S) Q8 D9 R4 W5 |1 H6 l7 @
- #define FDCAN_FD_CAN ((uint32_t)0x00200000U) /*!< FDCAN帧 */
复制代码 $ W* c( V9 n# N# I% P- M; {& E/ H( m' W1 s
RxTimestamp
5 N0 v( t( L( Q8 [# L2 E用于设置帧接收时间戳,范围0到0xFFFF。
6 v$ n+ X0 W4 m' [" X: F
" G5 z" z/ C5 r/ \0 g9 t8 Z FilterIndex
7 S% X; |% K/ U5 h! W( w! m5 f用于设置接收过滤索引。如果是标准ID,范围0到127,如果是扩展ID,范围0到63。
; k: A R; u! n2 H. I b" T& J7 H! _
8 _3 ?* E, m! a4 p6 i, p IsFilterMatchingFrame: _, \; ^: }+ P/ d* i; [
用于设置是否接收非匹配帧,通过函数HAL_FDCAN_ConfigGlobalFilter()可以使能。4 ~) X l2 y+ e3 z* ~+ N
- a. x+ s- T$ P7 b3 h% u
0:表示不接受。5 E. ^# c8 g' i: d# Z# N8 O7 |6 `( I' B/ g% _
& C4 V$ N& ~) n; q6 M, C' M% n6 U5 t1:表示接收。; T$ f: r9 t' T* c
! p2 L1 o7 u- F4 @
91.3.8 FDCAN总线句柄结构体FDCAN_HandleTypeDef
& P) Q2 v6 R$ U9 D) i9 i. u& L下面是CANFD句柄结构体:- a) p, C8 Q% p# d( L+ |
1 Z$ J- G& q; d9 y) ?) |' D- #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
& k9 x% }2 Y/ @1 R: @ - typedef struct __FDCAN_HandleTypeDef. i% ]& d; `. A4 e/ e, h
- #else
( V2 w- y( ~' M% {- d - typedef struct! {1 k" g4 r& e/ ?
- #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
6 p K- Q6 ~$ Q$ r - {
- Y% n5 d: Y3 D - FDCAN_GlobalTypeDef *Instance; /*!< Register base address */$ c" l3 X: a ?$ v2 w
- " A/ V0 h. J* M, _* q7 _( F" g2 f
- TTCAN_TypeDef *ttcan; /*!< TT register base address */( v& e" ^2 Z8 d2 e
- - j6 B& F; ]3 A. r, q: }
- FDCAN_InitTypeDef Init; /*!< FDCAN required parameters */
7 {. t7 X/ y A/ y5 x6 o6 `, }5 x) ` - ( _3 o# i3 V, \$ m/ L1 C5 k
- FDCAN_MsgRamAddressTypeDef msgRam; /*!< FDCAN Message RAM blocks */# @% d( R# o" }. F: E3 G) p
% Y9 D+ A. p4 ?8 L/ G& k- uint32_t LatestTxFifoQRequest; /*!< FDCAN Tx buffer index8 k2 h/ m- S6 \- I! _. {: F
- of latest Tx FIFO/Queue request */
7 E( r' e* {. O - 8 ~. A' x: y: T5 e. c( @. S
- __IO HAL_FDCAN_StateTypeDef State; /*!< FDCAN communication state */
9 A3 S( H$ b4 u; T0 ]% x3 g" |# _ - , j# s |2 }( }0 E# P
- HAL_LockTypeDef Lock; /*!< FDCAN locking object */
! Z' `4 H" R6 _3 g7 M - ; o. k; H+ g6 M4 o% p: o+ T+ Q& _* i
- __IO uint32_t ErrorCode; /*!< FDCAN Error code */9 a$ K) b; _2 a1 o" m
- # P9 u7 L& B; Y2 P z8 b' W2 w
- #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 14 {% T- m3 { b; K
- void (* ClockCalibrationCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ClkCalibrationITs); /*!< FDCAN Clock Calibration callback */5 s& |$ J; V- ~" [- W D
- void (* TxEventFifoCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TxEventFifoITs); /*!< FDCAN Tx Event Fifo callback */
! ^- P' _& e9 |) [ - void (* RxFifo0Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs); /*!< FDCAN Rx Fifo 0 callback */1 }( V# ^( b1 D: C
- void (* RxFifo1Callback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo1ITs); /*!< FDCAN Rx Fifo 1 callback */: ^0 z' Z9 v" m4 s0 L
- void (* TxFifoEmptyCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Tx Fifo Empty callback */9 D/ f3 f% ~4 ?$ J& c
- void (* TxBufferCompleteCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< FDCAN Tx Buffer complete callback */' z$ t* U) k% f* a/ A& n1 B
- void (* TxBufferAbortCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes); /*!< FDCAN Tx Buffer abort callback */
% P# f: {# i6 b( b( R* i - void (* RxBufferNewMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Rx Buffer New Message callback */
+ f7 n4 M% b* `* [( F - void (* HighPriorityMessageCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN High priority message callback */, L1 F& c, ^: p0 s1 K+ z/ W' ^
- void (* TimestampWraparoundCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Timestamp wraparound callback */
/ ^. G% f5 n& C6 e; J/ k% \' A+ D - void (* TimeoutOccurredCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Timeout occurred callback */- J" x4 M5 ^% {& Y' F% t
- void (* ErrorCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Error callback */. \7 y" F) @+ ] r$ S5 _$ e
- void (* ErrorStatusCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs); /*!< FDCAN Error status callback */
d4 N" ]1 e, j# ^- @ - void (* TT_ScheduleSyncCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTSchedSyncITs); /*!< FDCAN T Schedule Synchronization callback */
1 I: ~+ \/ \- J G/ O1 q - void (* TT_TimeMarkCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTTimeMarkITs); /*!< FDCAN TT Time Mark callback */. a. t+ S/ Y% x+ V) v6 v N, j* K1 L
- void (* TT_StopWatchCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t SWTime, uint32_t SWCycleCount); /*!< FDCAN TT Stop Watch callback */
" f8 f# p; D" ^% u - void (* TT_GlobalTimeCallback)(struct __FDCAN_HandleTypeDef *hfdcan, uint32_t TTGlobTimeITs); /*!< FDCAN TT Global Time callback */. D& @0 @, Q4 \+ M* H$ C
8 r- s8 @; T+ K/ O m, R- void (* MspInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Msp Init callback */
7 u3 K, M2 k/ ^' u. |' w - void (* MspDeInitCallback)(struct __FDCAN_HandleTypeDef *hfdcan); /*!< FDCAN Msp DeInit callback */
9 d: c" A3 p# ]+ m4 Z9 u - #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */7 q3 m9 m3 m# E+ x$ g* L) f
! q {( [% O% j5 [. B) Y6 a% x4 O- } FDCAN_HandleTypeDef;
复制代码 * V6 W6 m+ F X. z
注意事项:& |! ?" ]4 t I
' Y+ J8 M/ C+ `1 o, N3 j
条件编译USE_HAL_FDCAN_REGISTER_CALLBACKS用来设置使用自定义回调还是使用默认回调,此定义一般放在stm32h7xx_hal_conf.h文件里面设置:
# k5 }& Z& l8 Z+ A# K* f9 ^- #define USE_HAL_FDCAN_REGISTER_CALLBACKS 1
复制代码
^5 V2 v) _* I5 k' o( D9 Y( O
. M- @- W* r! n( f A$ p# j7 O函数HAL_FDCAN_RegisterCallback注册回调,取消注册使用函数HAL_FDCAN_UnRegisterCallback。, K7 N# j% d! |$ o8 u2 Z
/ n8 m# J" F- m" g: e- @% x这里重点介绍下面几个参数,其它参数主要是HAL库内部使用和自定义回调函数。
) N# V0 O7 G2 v
9 {- X7 F9 N2 I8 L5 d$ \ FDCAN_GlobalTypeDef *Instance
, q$ Q, ?. E& B3 H& n这个参数是寄存器的例化,方便操作寄存器。
y/ ?5 V" i* _6 y; c, V% O) G; a3 U9 }8 b) n
TTCAN_TypeDef *ttcan2 J# E/ c' A' L. U& l
TT CAN时间触发寄存器基地址。
8 C: ^9 U# t+ W
o9 l; |* A* z; x# `: b FDCAN_InitTypeDef Init
6 C4 Q9 r9 l2 V* ?: Z2 T: YFDCAN相关的初始化参数。
2 b2 @$ h6 H, p7 T& h8 {! x5 B0 M7 o) L+ ^3 `" \: n9 I
FDCAN_MsgRamAddressTypeDef msgRam2 P/ O, t" S& O9 ], [
消息RAM地址。
3 F1 }3 Z1 |4 z& r: [7 X% W
8 L4 h9 a, B( B) ? uint32_t LatestTxFifoQRequest9 z# H4 D, c" W K; J7 W9 h
Tx buffer索引最后一个Tx FIFO/Queue参数。! C6 O C, C9 y- Z# Q! R/ k) `9 r" S
/ k3 p$ \7 B& `# i6 C% X# C
__IO HAL_FDCAN_StateTypeDef State 1 z/ a' g+ k0 r" i/ K- }% `. c
HAL_LockTypeDef Lock
' T- v, G* h4 L7 v4 H h7 T; @
! M% Z* n* W# i__IO uint32_t ErrorCode& W! L8 A1 F: j3 t" U# [
4 M5 }7 L# |" h' ?# r9 a; V# V* J程序内部使用的状态参数。) b" f0 n$ B' Z L' v2 x7 ~3 X8 _! D
3 [/ K$ i& ^8 C' \9 i9 u
剩下的都是回调函数
( A& ^ o) m0 m& |4 _' x91.4 FD CAN总线源文件stm32h7xx_hal_fdcan.c
4 L5 _9 t7 k# m: y此文件涉及到的函数较多,这里把几个常用的函数做个说明:
: f9 A" w: F' R8 P/ m- B' P$ r2 l0 |& K5 |2 U
91.4.1 函数HAL_FDCAN_Init
: y: G3 X! N4 ?7 L3 C1 I% p' q函数原型:8 _# Y. v7 J, J# S' S! `' S0 f
. w7 d+ v, V3 w! \) e) z/ T( ^- HAL_StatusTypeDef HAL_FDCAN_Init(FDCAN_HandleTypeDef *hfdcan)
8 C ]( m0 I' w - {
: z( y6 F6 @5 o; P; J: g - uint32_t tickstart;
2 a. v& \8 L3 P' O; P% i1 R7 r - HAL_StatusTypeDef status;) ~* Z1 e% U' s3 H4 a, x
- const uint32_t CvtEltSize[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7};* k. M8 J$ Q* k/ G0 r2 t, J0 l% u
- . I9 V' n- u. U1 u; ~* F: x5 ]" v+ J
- /* 检测FDCAN句柄是否有效 *// l- g# R2 @* ?
- if (hfdcan == NULL)
3 B" U' }+ b4 K, N* s - {
* `% t1 F1 J R) D - return HAL_ERROR;1 ?! P: d' T5 r
- }; L8 n3 b e) g2 K1 Z
: I/ p; g% }0 B8 n- /* 检查FDCAN例化 */
% x/ _) q' N: C+ M5 ?4 K' t - if (hfdcan->Instance == FDCAN1)* f) L; J" i9 I% Y) _! _% S
- {
' u6 g8 U: [* V1 Q5 m g! @1 r - hfdcan->ttcan = (TTCAN_TypeDef *)((uint32_t)hfdcan->Instance + 0x100U);
z' I: ]0 |3 a4 Z, p7 F. { - }
2 l5 R# X9 N7 Y$ J; ~ - 6 e t5 m* J; s3 Q. d& w
- /* 检查函数参数 */- |7 m: I7 c4 I$ }0 j
- assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));
) I0 s9 T3 \1 S4 g6 H - assert_param(IS_FDCAN_FRAME_FORMAT(hfdcan->Init.FrameFormat));
( @( R0 j$ E6 {( E) a5 J% w - assert_param(IS_FDCAN_MODE(hfdcan->Init.Mode));
' d/ [" W! z% g& h - assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.AutoRetransmission)); h( P2 v8 j# M4 R4 Q
- assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.TransmitPause));
; H0 U' f" B, q, v: B$ I - assert_param(IS_FUNCTIONAL_STATE(hfdcan->Init.ProtocolException));
; R, p8 f I" S8 z - assert_param(IS_FDCAN_NOMINAL_PRESCALER(hfdcan->Init.NominalPrescaler));) s, H4 m: W y* i) \
- assert_param(IS_FDCAN_NOMINAL_SJW(hfdcan->Init.NominalSyncJumpWidth));
( G1 |# F. S! J- s! m6 w' I& p. |$ W) [5 Z - assert_param(IS_FDCAN_NOMINAL_TSEG1(hfdcan->Init.NominalTimeSeg1));- v7 q. E1 x1 p) q/ {; L
- assert_param(IS_FDCAN_NOMINAL_TSEG2(hfdcan->Init.NominalTimeSeg2));8 R$ J7 M+ L* h5 n7 O2 P+ P
- if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
+ K v( V5 u2 C y) T' N - {
6 B0 @* @3 Z4 \ - assert_param(IS_FDCAN_DATA_PRESCALER(hfdcan->Init.DataPrescaler));. `, s; a, H, S. o3 m
- assert_param(IS_FDCAN_DATA_SJW(hfdcan->Init.DataSyncJumpWidth));* H- Q) w- w+ ~- _' `* H& }
- assert_param(IS_FDCAN_DATA_TSEG1(hfdcan->Init.DataTimeSeg1));
3 m% J# D" W$ ~4 G/ i6 I- `6 t - assert_param(IS_FDCAN_DATA_TSEG2(hfdcan->Init.DataTimeSeg2));9 t& q9 l" Z6 b. a3 a# o V0 G- ~
- }
5 l2 i# s! q! D8 s ~ - assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.StdFiltersNbr, 128U));' x+ p H% }* k& E7 K" }
- assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.ExtFiltersNbr, 64U));( G, t3 X9 L" I5 h
- assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo0ElmtsNbr, 64U));
. n3 a R1 }) X - if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)* I9 ^* y+ L, U: W8 a
- {8 E; F1 Z8 D1 x6 S; G; E
- assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo0ElmtSize));# b$ s9 C8 I: t+ P4 f/ A. z
- }4 b# D" ?; @4 {( N- |, B3 x
- assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxFifo1ElmtsNbr, 64U));
% k7 e9 i% z% k$ a - if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)" ^6 x$ ~4 j' L6 V. Q
- {
9 z# A/ B: o; p1 Y& Q; W - assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxFifo1ElmtSize));
4 L7 p/ q6 s% n6 |! ]0 U - }* E5 F" }" t. I( t* M
- assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.RxBuffersNbr, 64U));
$ i6 ]) N2 G2 i5 E$ |4 y: M6 W - if (hfdcan->Init.RxBuffersNbr > 0U)
3 y* m' z4 R* ?, O }% j5 Q - {9 T# ?: w9 T1 r6 B. o' {
- assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.RxBufferSize));% j% l( P: _, y( Y6 O* k& t
- }
2 w8 p/ E; _+ v, ` i8 Q0 l3 D6 g - assert_param(IS_FDCAN_MAX_VALUE(hfdcan->Init.TxEventsNbr, 32U));% [7 M, {/ X- @) f7 w" W: M* m
- assert_param(IS_FDCAN_MAX_VALUE((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr), 32U));* x# E" {' ~# P0 c6 [; X* @
- if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)
* A* ^; P8 ^, \1 A0 M/ O* z - {
) O" w' v7 |+ ^5 F$ x: e6 k, F - assert_param(IS_FDCAN_TX_FIFO_QUEUE_MODE(hfdcan->Init.TxFifoQueueMode));
2 d; C2 _( O! |6 ^: Y3 n - }7 Q7 F# a% r$ I, F7 f% g1 A. M0 @
- if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)7 Y7 K1 S b* W* H4 g/ G
- {
. N Z9 L' F; O! t# T( }5 j - assert_param(IS_FDCAN_DATA_SIZE(hfdcan->Init.TxElmtSize));
* ~& z7 O% |$ u8 R, c" a - }: P) v6 t/ {7 o5 {, d3 h3 B) Q
" I; y7 P8 O# @+ @, h/ Z- #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
S* b8 I9 {& H6 U" S - if (hfdcan->State == HAL_FDCAN_STATE_RESET); f7 W4 r9 y$ K; Y4 Q7 ? a) x% d
- {; O2 ]" y1 O; ?: z
- /* 解锁*/( Y# |7 T* r& F1 P
- hfdcan->Lock = HAL_UNLOCKED;
, D, C' H1 X' e6 B
) _7 K9 [/ @9 S/ R- c4 b- /* 复位设置默认回调 */
3 G* B$ F% V$ C% a - hfdcan->ClockCalibrationCallback = HAL_FDCAN_ClockCalibrationCallback; /* Legacy weak ClockCalibrationCallback */' h! D$ p0 T% E% C/ t, {3 @: N
- hfdcan->TxEventFifoCallback = HAL_FDCAN_TxEventFifoCallback; /* Legacy weak TxEventFifoCallback */) r* `1 x6 V& `! ~* _. d! e7 A
- hfdcan->RxFifo0Callback = HAL_FDCAN_RxFifo0Callback; /* Legacy weak RxFifo0Callback */
6 Q8 |" K5 f' I, \ - hfdcan->RxFifo1Callback = HAL_FDCAN_RxFifo1Callback; /* Legacy weak RxFifo1Callback */
3 l! j! }8 z) @2 Q8 D - hfdcan->TxFifoEmptyCallback = HAL_FDCAN_TxFifoEmptyCallback; /* Legacy weak TxFifoEmptyCallback */
, f( {- K& N3 T; z; z8 ? - hfdcan->TxBufferCompleteCallback = HAL_FDCAN_TxBufferCompleteCallback; /* Legacy weak TxBufferCompleteCallback */
3 ]. y; S+ I' x0 L/ |9 u% H5 C - hfdcan->TxBufferAbortCallback = HAL_FDCAN_TxBufferAbortCallback; /* Legacy weak TxBufferAbortCallback */
* N4 r7 F1 t/ ~8 I; Z5 }( R# H - hfdcan->RxBufferNewMessageCallback = HAL_FDCAN_RxBufferNewMessageCallback; /* Legacy weak RxBufferNewMessageCallback */8 Q; b- u% p. ~5 _9 o* j0 g
- hfdcan->HighPriorityMessageCallback = HAL_FDCAN_HighPriorityMessageCallback; /* Legacy weak HighPriorityMessageCallback */! v5 J5 }0 }: H1 r+ u
- hfdcan->TimestampWraparoundCallback = HAL_FDCAN_TimestampWraparoundCallback; /* Legacy weak TimestampWraparoundCallback */
/ B3 \8 o, `9 A7 w/ J - hfdcan->TimeoutOccurredCallback = HAL_FDCAN_TimeoutOccurredCallback; /* Legacy weak TimeoutOccurredCallback */
. r* M4 H# D2 P% O' r* Q6 V# p - hfdcan->ErrorCallback = HAL_FDCAN_ErrorCallback; /* Legacy weak ErrorCallback */0 v6 B1 G6 O3 v; E* q+ C4 X% D) Y
- hfdcan->ErrorStatusCallback = HAL_FDCAN_ErrorStatusCallback; /* Legacy weak ErrorStatusCallback */7 C2 i0 B3 z" d- J
- hfdcan->TT_ScheduleSyncCallback = HAL_FDCAN_TT_ScheduleSyncCallback; /* Legacy weak TT_ScheduleSyncCallback */& j" ]3 o8 E0 a% S4 K0 S8 d# o
- hfdcan->TT_TimeMarkCallback = HAL_FDCAN_TT_TimeMarkCallback; /* Legacy weak TT_TimeMarkCallback */
2 K- q5 M: `9 _3 W. j- m& l& _ - hfdcan->TT_StopWatchCallback = HAL_FDCAN_TT_StopWatchCallback; /* Legacy weak TT_StopWatchCallback */
, P* N, K; s5 S7 }6 @6 O! q - hfdcan->TT_GlobalTimeCallback = HAL_FDCAN_TT_GlobalTimeCallback; /* Legacy weak TT_GlobalTimeCallback */
* O2 u; L* h! c/ D, h- A6 m
* e2 R; p0 w5 e7 k3 o3 [& R- if (hfdcan->MspInitCallback == NULL)" w! L. F9 j4 e: W9 X
- {
6 E. _3 X8 W9 Q# g( G J& q9 T - hfdcan->MspInitCallback = HAL_FDCAN_MspInit; /* Legacy weak MspInit */5 u0 P, m$ W4 }& @8 F: @
- }
$ v/ V! n, m/ V
) f/ `% V& P4 H$ r9 d7 h- /* 初始化CLOCK和NVIC */
" x" r4 C, J. y) S3 z+ E0 | - hfdcan->MspInitCallback(hfdcan);
/ e( T6 j' x0 p - }
* [& i5 m: q4 _) N7 W% m) A) f - #else
0 M6 b+ G+ W2 x4 J( x1 R - if (hfdcan->State == HAL_FDCAN_STATE_RESET)
& x8 {' Q; q; r$ W P$ v - {9 Y* Z& Y1 a+ i6 A4 V
- /* 解锁 */; a/ W. @6 X; W0 B8 S# v
- hfdcan->Lock = HAL_UNLOCKED;
+ B- P1 G! V7 R3 ?# U, J+ t - ! L/ ? w. \+ E
- /* 初始化底层硬件 */
0 q- x7 f6 o4 X - HAL_FDCAN_MspInit(hfdcan);
' d* B4 h) D" r8 g( z) O - }
9 j1 `( K. ^* z - #endif /* USE_HAL_FDCAN_REGISTER_CALLBACKS */
9 Z4 q8 A( _9 | - 5 N( X- Q0 f4 |" y& q
- /* 退出Sleep */
, }' G: q+ H* H - CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CSR);: h6 T h! H! J1 n" _$ d6 h
- 2 ?- ~+ P( {7 M" Z; [; u, e4 f# |
- /* 获取时钟 */
) ~( J X* H, ~! }1 k+ b) O - tickstart = HAL_GetTick(); g* [1 L& `$ C) E$ @! W% Y
9 {" f2 K0 Y5 O- /* 等待Sleep模式确认 */
2 F b( X9 {7 }2 W( [2 F. \ - while ((hfdcan->Instance->CCCR & FDCAN_CCCR_CSA) == FDCAN_CCCR_CSA)# V; K' D/ M m' ?0 |" t
- {
6 B* j6 [2 ^( u$ P - if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)- \) [" w b& o E
- {
+ m/ f! |( P( O/ n7 `5 [, } - /* 更新错误码 */" E) V5 l8 g5 o. N
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;% c9 z5 y& x. q5 c( M) }
- - Z0 v. w5 _. A1 h! T$ z s
- /* 改变FDCAN状态 */# D8 M* q, K1 ^& _9 i9 l+ F9 Z
- hfdcan->State = HAL_FDCAN_STATE_ERROR;
2 `; K& U+ O% n5 i
6 l5 ^( g# B* v( r. {( C" @- return HAL_ERROR;. G+ \$ G# W$ s
- }8 v* R7 H: S# S* {; r/ R5 B
- }
0 Y& {: ?* N% Y# V
5 e. m+ f) e& D- B. D/ B* |2 ^- /* 请求初始化 */7 z# w. Y( M. n5 f. K0 v
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);
9 T2 S; f. Y" }+ P: w( T - - @# @8 u( O. u# R" O4 X9 p
- /* 获取时钟 */2 B* B7 U2 g% H$ j& ]
- tickstart = HAL_GetTick();
; K. e+ A6 `" v7 F
4 E3 s, W0 W, S8 i& U) D+ r- /* 等待CCCR寄存器的INIT位 */- ]/ J% ^1 H& R9 x
- while ((hfdcan->Instance->CCCR & FDCAN_CCCR_INIT) == 0U)" x, B+ s, \% P
- {
8 T) m$ n0 e- r/ h; x$ I8 B$ d' i - /* 检查溢出时间 */; G M) P0 O' Z, }$ L e, J2 ]
- if ((HAL_GetTick() - tickstart) > FDCAN_TIMEOUT_VALUE)
4 v9 }) [' Y" { \: v - {1 O% N- s; _ t- I
- /* 更新错误码 */
% H# O9 U' L: U# U& p - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_TIMEOUT;
5 ?# g3 n) Y! @+ c6 V9 o- i
( K1 q7 D: d- o& [6 I+ S- /* 设置FDCAN状态 */3 \, A/ |4 O5 o" Y
- hfdcan->State = HAL_FDCAN_STATE_ERROR;- O% D3 h# G" g) r+ q/ w
+ p6 ~+ { p. G F3 P/ T- return HAL_ERROR;
6 Y" `# w$ c5 ^3 `6 L9 s; R - }
! P3 c" ^* f+ S8 {8 v( @ - }0 J5 z9 c* Z7 W$ Q* Q
- ! Y1 f8 [, Q9 |- Q' ?
- /* 使能配置修改 */
* c4 G( x v, D9 a5 ?$ s+ Z1 C" C - SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_CCE);
S% m+ N8 ^+ F8 S* t - 7 u0 [0 ]9 K( o) u
- /* 设置是否自动重传 */% d, @) m4 x+ E$ O9 I
- if (hfdcan->Init.AutoRetransmission == ENABLE)
# ^. G1 f# e3 x% ` - {0 n0 G' E/ n- q ?0 `; `- A
- CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);# Q' M- c# g) }7 |4 q
- }
8 N4 k/ {" a; t" V. E - else
: h/ y# x+ {. R: B3 v; O0 {5 c - {# a7 e8 M# M6 v' ]
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_DAR);
0 ^$ u8 p7 V, q; a - }
$ t: m3 h7 p @& } - 5 l6 ^& s% R& i# z$ `. D. C+ _& |
- /* 设置传输暂停特性 */
: T( Q: x: ^' `) f* C: w6 B - if (hfdcan->Init.TransmitPause == ENABLE)
9 L" w6 ~+ z, X - {: {8 U3 `' _/ L5 N9 Y
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
9 a( j& B( z0 J+ V - }
/ S/ R- O# }( Y: M* X - else
$ q) g2 m# E% S8 m) n7 c; j/ v- Q- E - {
1 R p% s8 ?4 w2 ^' j: q8 |2 D - CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TXP);
6 p9 Y- c- D8 u4 C. H7 H - }
# u6 b0 L7 P6 R |/ J2 p
. z. T( E" c* D; N. `- /* 设置协议异常处理 */
* G/ t5 A) R% }- [) e - if (hfdcan->Init.ProtocolException == ENABLE)
7 ~' v7 f& ~/ J) a - {
) v' j! }. h& S2 Q - CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);
- W; A2 i2 G' N. `3 X - }1 K% o" R& i& h
- else
. A# E& L z) O, o - {: C1 h% ?% F( T* k i9 a8 K
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_PXHD);/ n9 m; @6 w. C: d3 W
- }1 h; Z: l; _' j- Q( h
- 3 Y/ H9 F8 [5 }
- /* 设置FDCAN帧格式 */& P& o0 {4 V7 ~
- MODIFY_REG(hfdcan->Instance->CCCR, FDCAN_FRAME_FD_BRS, hfdcan->Init.FrameFormat);
2 v" \# c: V+ x9 H& U# R - 9 w+ ^8 m! f, f( J+ S3 N- P6 E
- /* 复位FDCAN操作模式 */
. ^" r" ~! A6 F( B) z& N1 R; D - CLEAR_BIT(hfdcan->Instance->CCCR, (FDCAN_CCCR_TEST | FDCAN_CCCR_MON | FDCAN_CCCR_ASM));+ [. F. r& \9 J* T% Q3 @
- CLEAR_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);
3 E" h: M$ I4 N! r( ~! y - F7 A ~3 O+ Z# ^! b8 J
- /* 设置FDCAN操作模式:
$ ~& X; H- I& O% Z, N - | Normal | Restricted | Bus | Internal | External& H' h/ U% m* d6 N
- | | Operation | Monitoring | LoopBack | LoopBack
2 I( ~+ ^! o" |$ \; c# B - CCCR.TEST | 0 | 0 | 0 | 1 | 11 J; J" I) S$ H( y+ @
- CCCR.MON | 0 | 0 | 1 | 1 | 00 s. K# i. _( @7 h' i# p& Q9 B
- TEST.LBCK | 0 | 0 | 0 | 1 | 11 g; N5 _% N' O, h+ q) w
- CCCR.ASM | 0 | 1 | 0 | 0 | 05 g% m |6 ], R2 c* L' E( }* o$ e( ^
- */
% [9 I# A0 h+ o! Q( M - if (hfdcan->Init.Mode == FDCAN_MODE_RESTRICTED_OPERATION)
* k/ Y7 W1 X' d' A/ x6 J - {3 A( S1 i6 v4 d* L& U% B0 u" B
- /* 使能限制操作模式 */
$ j1 ^* V" W5 W& g - SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_ASM);
% s* T+ R4 v. n0 G8 D - }
6 O" g) g: i q' I# p - else if (hfdcan->Init.Mode != FDCAN_MODE_NORMAL)
. t/ |6 Y3 c2 \2 k( f - {2 V+ W5 H( o) u9 b& j1 n4 d
- if (hfdcan->Init.Mode != FDCAN_MODE_BUS_MONITORING)$ G5 P" x( t% l" C# i
- {3 _6 A6 a" T; u& |% K8 t
- /* TEST寄存器写访问使能 */) L; ^4 D w; a
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_TEST);2 h1 [" |) r1 C0 p
- % K. m6 J. ^: H1 [" K
- /* 使能回环模式 */. f6 q$ s7 G% C; {
- SET_BIT(hfdcan->Instance->TEST, FDCAN_TEST_LBCK);' ^# I" e" M1 z
1 h. S- Q Q. u a; ]- if (hfdcan->Init.Mode == FDCAN_MODE_INTERNAL_LOOPBACK)$ o' V- o4 r. D4 z
- {
: s* S4 Y1 w9 _9 q+ c" d t' a( l - SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);
2 N' m4 K J& ~& E' |' u" m - }
* G2 p* x. e% M - }
4 D: b ]. G5 g0 _% O, R) U - else
' Q& f1 j. [+ p: i - {
2 T7 z* w; ?( `, P" T; J* G - /* 使能检测模式 */: T! i) [5 g0 t( c& G
- SET_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_MON);: l, K( W! X- X* V5 U3 r6 H7 c& Z
- }
0 ~0 b% E( t1 c) D, x% Z9 t3 M - }
, X9 \! g( c" Q* M - else# \7 i" H% L1 g# K; v
- {
4 p1 d# Z1 u: e" K$ d - /* Nothing to do: normal mode */( u. `8 A; Y5 a: R" N; b6 U* \
- }
7 f* I$ ]4 k% N% l( L) \ - 7 ~8 U5 I# t! J1 |3 j3 ]2 h: C
- /* 设置nominal bit timing 寄存器 */
; O# R1 j- |+ j# H - hfdcan->Instance->NBTP = ((((uint32_t)hfdcan->Init.NominalSyncJumpWidth - 1U) << FDCAN_NBTP_NSJW_Pos) | \* Z* q8 E# E. Q3 m1 U) {" D) m
- (((uint32_t)hfdcan->Init.NominalTimeSeg1 - 1U) << FDCAN_NBTP_NTSEG1_Pos) | \
+ U( e: H; {" S: \# s# N F ^ - (((uint32_t)hfdcan->Init.NominalTimeSeg2 - 1U) << FDCAN_NBTP_NTSEG2_Pos) | \
+ x+ a& W0 Z! _, t9 F - (((uint32_t)hfdcan->Init.NominalPrescaler - 1U) << FDCAN_NBTP_NBRP_Pos));9 }, v- }, j- e2 d+ v b! e5 B; _
- 3 v7 T7 l4 T1 L
- /* 如果使能BRS(BitRate Switching可变波特率),设置data bit timing 寄存器*/
* `! @) L4 j% ~1 \ - if (hfdcan->Init.FrameFormat == FDCAN_FRAME_FD_BRS)
$ [. t* P/ z% z5 a" K6 ` - {
, A+ \5 V% x9 t+ e( g - hfdcan->Instance->DBTP = ((((uint32_t)hfdcan->Init.DataSyncJumpWidth - 1U) << FDCAN_DBTP_DSJW_Pos) | \- L V+ T# O' F8 w6 c7 X0 L
- (((uint32_t)hfdcan->Init.DataTimeSeg1 - 1U) << FDCAN_DBTP_DTSEG1_Pos) | \" m6 k6 w! c3 l' Y! E4 v9 X; L, x
- (((uint32_t)hfdcan->Init.DataTimeSeg2 - 1U) << FDCAN_DBTP_DTSEG2_Pos) | \ G2 u, }! G6 p' p9 E( B( D
- (((uint32_t)hfdcan->Init.DataPrescaler - 1U) << FDCAN_DBTP_DBRP_Pos));8 ^( F* M6 K- z; [' z
- }
) x4 F6 k$ N/ c3 u% n - 0 E0 ^( B2 u) S8 W
- if (hfdcan->Init.TxFifoQueueElmtsNbr > 0U)" Q6 { f% P. F' J7 J7 c4 {
- {9 c( }5 i$ J! `4 b. _+ u$ D; C
- /* 设置Tx FIFO 或 Tx Queue 操作模式 */0 b' @9 G; K" Z; L" C
- SET_BIT(hfdcan->Instance->TXBC, hfdcan->Init.TxFifoQueueMode);
( ^; Y2 C: b3 ], q - }- g$ K2 X' y8 e% |5 O
- $ x2 N/ s: G# {! G
- /* 配置Tx element 大小 */
1 U+ Y! e$ J) ?* c1 Z( B; x$ k8 O ? - if ((hfdcan->Init.TxBuffersNbr + hfdcan->Init.TxFifoQueueElmtsNbr) > 0U)
9 N" Q# }0 j9 p7 j - {7 r1 W. d' o) V: P! e
- MODIFY_REG(hfdcan->Instance->TXESC, FDCAN_TXESC_TBDS, CvtEltSize[hfdcan->Init.TxElmtSize]);
$ B( M) i$ f0 ] - }; ?. n% b: i2 k7 `
4 e6 b2 U$ x( W0 _8 d* Z5 t- /* 配置Rx FIFO 0 大小 */
& ~9 |. b" s$ D$ { - if (hfdcan->Init.RxFifo0ElmtsNbr > 0U)6 h0 s; Q# y( e* X/ c' N3 S7 e M
- {) @/ p+ r! K: e
- MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F0DS, (CvtEltSize[hfdcan->Init.RxFifo0ElmtSize] << FDCAN_RXESC_F0DS_Pos));# _4 s4 S9 [* e+ G4 Q
- }
6 j; V' [' d& l; q7 |0 `1 j# ~ - ! v7 n( P+ r( x/ i$ i4 }
- /* 配置Rx FIFO 1大小 */
4 o! U% a: Z5 {) O5 p+ s - if (hfdcan->Init.RxFifo1ElmtsNbr > 0U)
) ?" K) k7 z4 I: V2 f( U0 w - {
! B% Q- ]& h' R$ r1 v( n - MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_F1DS, (CvtEltSize[hfdcan->Init.RxFifo1ElmtSize] << FDCAN_RXESC_F1DS_Pos));: b( }. w1 L: T" ?
- }
. q5 A6 i3 `. u" Y8 `
7 [! y |2 J' P6 ]( e+ K- /* 配置 Rx buffer element 大小 */, g% i4 Y& }7 T9 R+ t( n
- if (hfdcan->Init.RxBuffersNbr > 0U)
9 P( n7 y' [( d- K - {
- j6 p4 c/ ~/ |* g - MODIFY_REG(hfdcan->Instance->RXESC, FDCAN_RXESC_RBDS, (CvtEltSize[hfdcan->Init.RxBufferSize] << FDCAN_RXESC_RBDS_Pos));; n1 E$ P$ f/ `6 F7 \
- }
8 Z3 u& ~- {3 |! k; } E
# A3 I/ k& t7 c7 ?1 S5 w2 w r, @- /* 默认是的事件触发模式,如果使用时间触发模式,用户需要在HAL_FDCAN_Init 0 `0 W- O$ I/ L4 C# j4 Q
- 后调用HAL_FDCAN_TT_ConfigOperation */
+ a# M, c2 L. [+ W T) ?$ A - if (hfdcan->Instance == FDCAN1)8 j( _: J. b) @7 j' e) F, v
- {6 A3 v5 H, H# ?9 b' H
- CLEAR_BIT(hfdcan->ttcan->TTOCF, FDCAN_TTOCF_OM);
; @' J1 n9 F- h* B& ?% x* j% x - }/ l3 V7 H, P# [) |8 s
- $ W) u6 o, D$ A/ a, n
- /* 初始化Tx FIFO/Queue */
) R* I/ _7 ~6 G! W. h, n/ v2 H - hfdcan->LatestTxFifoQRequest = 0U;
! U9 K/ K# h: l - 2 ^' R1 U7 e d4 @
- /* 初始化错误码 */2 n+ A$ O6 ?) F* t
- hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;8 l5 @5 E1 A: X; M6 z1 l) L9 k
- - a7 w4 R, x0 L& D
- /* 初始化FDCAN状态 */3 @; b- y6 Z' I1 Y6 _, A
- hfdcan->State = HAL_FDCAN_STATE_READY;2 d7 ?$ ^" P) i! O! V9 Z# |
: G% t: Q7 N# r; P* l) i8 X- /* 计算每个RAM块地址 */3 h1 q, I# D3 j2 V# O: T
- status = FDCAN_CalcultateRamBlockAddresses(hfdcan);
& h, T2 ]5 y0 P4 D% ~( P$ \ v: E( Z
. {) Q7 I) F) Y# _# l& P- /* 返回函数状态 */# E1 d( V4 J! y+ y, k5 p) R
- return status;( r2 h& c1 @3 m3 [/ L3 C, X
- }
复制代码 . q$ K( g8 p8 s6 h+ g
函数描述:2 a3 V, h$ O; S- ?
7 J9 [" y' |, o$ M此函数用于初始化FDCAN。; l) m, J ?, P
( ?8 b1 K1 [/ J5 o函数参数:
, q/ e) t) A) p3 o* ^" x# t0 j2 H4 n: K# V1 ~
第1个参数是FDCAN_HandleTypeDef类型结构体指针变量,用于配置要初始化的参数。
& t a: r7 a" v3 `) x 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。4 E2 V Q+ w! n g3 w
注意事项:
8 p: y; X' q0 |0 Q: @/ e! P6 G5 J* h, j' }5 ?- n7 {9 q
函数HAL_FDCAN_MspInit用于初始化FDCAN的底层时钟、引脚等功能。需要用户自己在此函数里面实现具体的功能。由于这个函数是弱定义的,允许用户在工程其它源文件里面重新实现此函数。当然,不限制一定要在此函数里面实现,也可以像早期的标准库那样,用户自己初始化即可,更灵活些。+ }) f' X4 O2 q: a% m$ O& d; ]- v+ r
如果形参hfdcan的结构体成员State没有做初始状态,这个地方就是个坑。特别是用户搞了一个局部变量FDCAN_HandleTypeDef FdCANHandle。
) s( E. m+ G0 B( x- I! P7 Y8 K对于局部变量来说,这个参数就是一个随机值,如果是全局变量还好,一般MDK和IAR都会将全部变量初始化为0,而恰好这个 HAL_FDCAN_STATE_RESET = 0x00U。
/ z* {+ p# A& D2 y
) `' ^9 z# X1 B v2 h- V+ |% E, C$ F$ [解决办法有三
' k* e2 q$ d: D8 z- _
6 g* n0 `4 Z( Y* _5 h" Q方法1:用户自己初始化FDCAN和涉及到的GPIO等。
9 J' j3 w+ V$ l% \
5 a7 o$ G) \+ y方法2:定义FDCAN_HandleTypeDef FdCANHandle为全局变量。: h& g* s6 B" W8 e8 Z' W+ h6 v
5 v: {! [# T$ \0 d8 q
方法3:下面的方法
& \+ M/ Q! L$ ^
# { ^, N3 N, b M! I. A- if(HAL_FDCAN_DeInit(&FdCANHandle) != HAL_OK) P& |' D8 v" S q
- {
& @% n" t) K# i5 c6 { - Error_Handler();! v: r7 U& a. c+ F
- }
# ]# c' B& Y$ W* @ I - if(HAL_FDCAN_Init(&FdCANHandle) != HAL_OK)& F5 ?# s4 A7 `9 S% w
- {
( w2 H9 S/ ?3 Z# v4 J0 u' b - Error_Handler();: R i2 V6 b7 O4 f4 _* ]: ~& Y
- }
复制代码
; T. y. Z4 @. h' G6 w4 T使用举例:; ^, U) f+ D/ s w% W
/ ? y$ e6 m9 B. n- FDCAN_HandleTypeDef hfdcan1;1 G r ]0 l- _/ W
( M+ o% `) U; o/ Q: e- /*
6 S# T3 A! f+ f/ g - *********************************************************************************************************
+ d/ H; O: m: C0 [# y - * 函 数 名: bsp_InitCan1- R! `; x3 ]% z9 x
- * 功能说明: 初始CAN1
6 l0 o ?; u% v- {" S1 K* t - * 形 参: 无 ]; d2 e8 T9 e! V* A
- * 返 回 值: 无5 r5 w7 ?4 Z' k$ ]- V: h7 k
- *********************************************************************************************************
& Y# u) g& i& [' f% N - */% k2 d; a: _/ A, [% I
- void bsp_InitCan1(void)
9 A7 b" V( y' L - { Y u# S6 m; m* m8 D9 A
- /* 位时间特性配置
: ?# Y9 N$ f1 d& g+ N - Bit time parameter | Nominal | Data1 }* H% l9 Q; N) J. M3 ]5 H- z
- ---------------------------|--------------|----------------# c- I. O1 B- ^- T( d8 Y: R
- fdcan_ker_ck | 20 MHz | 20 MHz8 v& S% V5 L) z( l- {4 G
- Time_quantum (tq) | 50 ns | 50 ns9 n# l- `% w. Q1 w' ~2 x$ v
- Synchronization_segment | 1 tq | 1 tq
. X5 `0 x( F' _* u& ?4 \& O3 E - Propagation_segment | 23 tq | 1 tq
}) s1 }4 Q7 p0 i - Phase_segment_1 | 8 tq | 4 tq4 S2 q. B; l8 ~# y/ T
- Phase_segment_2 | 8 tq | 4 tq
; ?$ I, s2 x& l% p* b - Synchronization_Jump_width | 8 tq | 4 tq
- K" R- {# q/ {9 d - Bit_length | 40 tq = 2us | 10 tq = 0.5us" d' E: k! {4 b, @2 E
- Bit_rate | 0.5 MBit/s | 2 MBit/s5 D9 M: P, ]1 ^* M
- */0 E3 A+ N3 U7 M" l% x$ f
- hfdcan1.Instance = FDCAN1; /* 配置FDCAN1 */ - |5 U$ D- N% b. a" E
- hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS; /* 配置使用FDCAN可变波特率 */ 0 @( z0 D) y2 e) h2 ?% B1 S6 k
- hfdcan1.Init.Mode = FDCAN_MODE_NORMAL; /* 配置使用正常模式 */ K1 G$ P( b+ A& j/ ]
- hfdcan1.Init.AutoRetransmission = ENABLE; /*使能自动重发 */ ) E: \; F' U( e& p+ I" p* H
- hfdcan1.Init.TransmitPause = DISABLE; /* 配置禁止传输暂停特性 */
4 r/ {: M$ t9 ^1 v' S5 ] - hfdcan1.Init.ProtocolException = ENABLE; /* 协议异常处理使能 */! \, c' a3 q1 r' i' ^
- 6 |$ s& H v: `
- /* 7 s C2 U( t3 g6 M
- 配置仲裁阶段波特率 * x9 [7 V4 z6 l' G8 Y; n
- CAN时钟20MHz时,仲裁阶段的波特率就是
4 g' J9 ^& g6 a. z" s - CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+0x1F + 8) = 0.5Mbps 5 K- ~ P/ v8 h `( E
- : L) l' Z; P) s; J! C W
- 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2
6 u! N' z7 d% l; m( ]6 Y4 x. ^ - */
, I3 C. u% e2 ]! F2 E9 e - /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck) */2 ~: p, S9 A- T4 z/ ]- n
- hfdcan1.Init.NominalPrescaler = 0x01;
' A0 q) v) N$ D1 b+ w - ( y5 {9 T; E9 |( }: u* |( a: v
- /* 用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大 */* l' _2 P# _! e1 l! Q. k
- hfdcan1.Init.NominalSyncJumpWidth = 0x08; : W8 u/ t7 m! s |8 u+ x
- + {" ^; O* b; F
- /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1 */
, w" {5 B0 l3 O+ e* } - hfdcan1.Init.NominalTimeSeg1 = 0x1F; ) v+ ^, |. @5 x5 k8 _# l* n
- + U" I$ G7 C6 R5 G# V A
- /* 对应位时间特性图的 Phase_Seg2 */
1 ~: n9 r( _: Z: ? - hfdcan1.Init.NominalTimeSeg2 = 0x08;
: _1 M) R+ F. D( R. X6 B - * k2 |% V7 r3 v# K
- 0 Y" o8 d$ t- X; j% O, i( f2 [
- /*
2 A L- K9 W: Y; |. m/ j - 配置数据阶段波特率
# S+ S# q; B3 H/ t6 n - CAN时钟20MHz时,数据阶段的波特率就是
* ^' f- Q9 m2 r4 ]; W% O$ i - CAN FD Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2) = 20MHz / (1+5+ 4) = 2Mbps* z9 S) r# q2 e2 b0 I) j% G: Y
-
# Q. o9 P# }) H& U - 其中Sync_Seg是固定值 = 1 , Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2+ F( F* d' h# O( I$ o$ \
- */
* i. p/ w8 J% C5 H- p - /* CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),
$ z, Y5 _) w" @ I) ^2 f2 q - 范围1-32 */9 t$ `/ @" P0 P: g f, X
- hfdcan1.Init.DataPrescaler = 0x01; , Y: E5 }* ~# M9 H7 |
- ; B; m' q! j" C
- /* 用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16 */
3 Q, d1 I3 C* a( b+ h+ } - hfdcan1.Init.DataSyncJumpWidth = 0x04; ; W' v& @& `9 B4 z3 E# l1 c \) ^
3 ^4 f# v; @0 o, x8 M8 b7 d- /* 特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1,范围 */4 {$ t5 D4 t$ U$ d* M6 w+ U J1 z7 T8 c
- hfdcan1.Init.DataTimeSeg1 = 0x05; 0 R* }5 ~0 L9 V3 Q& F* y% G
- ( [2 e9 h! v: I/ z. O
- /* 对应位时间特性图的 Phase_Seg2 */ " V* m, Z3 f6 Q5 e% Y& M
- hfdcan1.Init.DataTimeSeg2 = 0x04; # t) ^1 ~+ R; f% t, \% U! [0 w) ]
- 8 Z! @9 l. j' a; N- B" g5 [
- # R0 L0 A4 {( b
- hfdcan1.Init.MessageRAMOffset = 0; /* CAN1和CAN2共享2560个字, 这里CAN1分配前1280字 */2 V' U9 K1 ]7 |4 E1 x& U
-
. l# d$ z/ x! k/ X' K* |! V0 F -
7 v. c6 @& a% |" o% c B# T - hfdcan1.Init.StdFiltersNbr = 1; /* 设置标准ID过滤器个数,范围0-128 */
$ {% d' T/ l/ a0 m" q, d - hfdcan1.Init.ExtFiltersNbr = 0; /* 设置扩展ID过滤器个数,范围0-64 */ * L, ~' V+ J3 K0 ?: L1 W
- hfdcan1.Init.RxFifo0ElmtsNbr = 2; /* 设置Rx FIFO0的元素个数,范围0-64 */ ; m2 N) |) R5 C
- /* 设置Rx FIFO0中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */ - [: _( g2 [$ g# o! G! c- |
- hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
8 u7 J8 X' a& \ - hfdcan1.Init.RxFifo1ElmtsNbr = 0; /* 设置Rx FIFO1的元素个数,范围0-64 */" q* t% u2 @: G* k9 X/ Z
: b3 y: }+ Y: j, o% P+ b- /* 设置Rx FIFO1中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */ 9 K3 I6 E. h o" ~/ e- k% W6 g# _
- hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
$ Z' F ^ F9 S; d& x e9 C6 x* O - hfdcan1.Init.RxBuffersNbr = 0; /* 设置Rx Buffer个数,范围0-64 */
4 k* a: }3 V) W2 k - + Z8 q5 j- T8 P9 d2 [
- /* 设置Rx Buffer中每个元素大小,支持8,12,16,20,24,32,48或者64字节 */7 [% U9 Q: ]( B( F5 V
- hfdcan1.Init.RxBufferSize = 0; + E2 S( U; |8 b
1 K$ p9 s. F$ ]) e- 2 w1 V& x- c' P( H& B) p
- hfdcan1.Init.TxEventsNbr = 0; /* 设置Tx Event FIFO中元素个数,范围0-32 */
6 F, t+ n4 g0 Y7 x3 o* X3 G - hfdcan1.Init.TxBuffersNbr = 0; /* 设置Tx Buffer中元素个数,范围0-32 */: \0 G+ ?' W9 q8 {
- hfdcan1.Init.TxFifoQueueElmtsNbr = 2; /* 设置用于Tx FIFO/Queue的Tx Buffers个数。范围0到32 */1 S- B* y7 Y6 V# a: r# I
- hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION; /* 设置FIFO模式或者QUEUE队列模式 */
5 ?, ` [# y `* U - # `& K7 F$ D/ B/ U+ ]& k- z
- /* 设置Tx Element中的数据域大小,支持8,12,16,20,24,32,48或者64字节 */+ z% A' o6 h8 ?
- hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8; , G4 ~ F. e5 @0 \. `) \
- HAL_FDCAN_Init(&hfdcan1);/ A/ j. n, t( [6 A" {' @
- # k0 l! Z$ g; p7 }2 K. B# J' v
# F* k+ v- A$ V- A7 |- K- //省略未写( T t5 C1 P0 Z7 }" I% U& R
& L3 p0 U2 {2 x1 [& g. E% k- }
复制代码 7 d& X3 \; r+ H0 R2 B
91.4.2 函数HAL_FDCAN_DeInit
" L' { l1 R- K6 M0 K- [, @. Y函数原型:
+ [$ ^" j7 D. `/ i' O: W
4 ?/ j+ y" g$ T" ]3 C, |- HAL_StatusTypeDef HAL_FDCAN_DeInit(FDCAN_HandleTypeDef *hfdcan)% D, R. R* u3 I- ~2 h
- {
. g3 b( n# y8 A0 P) t3 f; X - /* 检测句柄 */
?7 A6 n5 l# g - if (hfdcan == NULL)' ]/ b4 u' v* |8 ~# D$ ~
- {
, N8 C8 q/ Z; x4 ]: g* S1 H! [& \ - return HAL_ERROR;
' C5 ?0 b" S4 F6 c4 \, ~+ b - }( B t z3 R( {/ H3 b5 a/ U+ w/ \
6 i& x* }: Z5 R, `0 `3 d9 e- /* 检查函数形参 */" }+ g0 \1 y1 k# j# l: @( N
- assert_param(IS_FDCAN_ALL_INSTANCE(hfdcan->Instance));0 q2 a- }* V6 H8 U4 _( }$ w+ c
- % m$ E. P8 l, f5 J
- /* 停止FDCAN */
; ^0 y0 w) f( [( n4 n# a - (void)HAL_FDCAN_Stop(hfdcan);
; a# j# t3 O9 M - 2 Y& R6 e2 |& b7 d2 ?; _
- /* 禁止中断 */
8 n9 j. I0 e ?; F6 Y - CLEAR_BIT(hfdcan->Instance->ILE, (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1));
% E) k0 X- l' J; x Y2 T" z
: F) V8 J1 V8 v$ _" h1 Z( Z- #if USE_HAL_FDCAN_REGISTER_CALLBACKS == 1
/ O5 ?4 d, B9 r, D/ k - if (hfdcan->MspDeInitCallback == NULL)1 T1 e3 V8 o9 z9 Q0 d% s* \4 C# e* H
- {, \" y8 u2 z) i, u' [
- hfdcan->MspDeInitCallback = HAL_FDCAN_MspDeInit; /* Legacy weak MspDeInit */
; [" E8 P: h6 T' i - }1 l. q/ n) }8 |7 k1 w3 p& t
- ! S6 e4 L' b4 _1 u% \. u. {6 N
- /* 复位底层硬件,如时钟,NVIC等 */
+ P9 M' x9 a0 B: J7 t - hfdcan->MspDeInitCallback(hfdcan);4 s5 w2 {- F+ B+ y
- #else
# g- n. ^0 ~8 O- d# D9 x# k - /* 复位底层硬件,如时钟,NVIC等 */
# a# W$ u7 g5 ~/ t; ~ - HAL_FDCAN_MspDeInit(hfdcan);
; l0 _: e5 ^, i2 G - #endif
) a f7 v8 C ?: Z* i - % x8 b# {( N( P6 x
- /* 复位错误码 */ _. s2 c6 T5 J
- hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;$ ]2 f. c" K* }. O- q
- . Z6 o( S8 P f7 P2 W# {
- /* 设置FDCAN状态 */
' M/ R* {4 [0 ]4 _( X9 W2 T; r3 K - hfdcan->State = HAL_FDCAN_STATE_RESET;- i: k$ z5 o6 w5 ^2 q& v U* _$ [
0 ^- D9 q; X4 I8 V- /* 返回HAL_OK */
1 g8 s( s$ T; z" K. O - return HAL_OK;
: H) t8 b7 `0 o( f+ f - }
复制代码
; p+ Y' p# g9 R* D" P. L( g函数描述:) [5 D5 G3 y' c5 B3 W2 E( y
; p- W! u7 f; H6 i& k* I6 r/ c6 T& L0 T
用于复位FDCAN。
/ f$ }9 \4 x% a$ N- l' C f2 }1 e* n! y; U& S
函数参数:
1 D/ ~0 O0 f1 l. U2 K: F# P, l! J! e# W S- N
第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
' k* x* q6 f' j) h 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
: T; T1 E" W6 i91.4.3 函数HAL_FDCAN_ConfigFilter
0 Y2 I } A% f( h函数原型:
8 U3 D1 ^ P7 ^ v& [6 E1 s: ?# Y/ m' B
- HAL_StatusTypeDef HAL_FDCAN_ConfigFilter(FDCAN_HandleTypeDef *hfdcan, FDCAN_FilterTypeDef *sFilterConfig)
! e! o& f' r$ d# w! h, N* `, P - {- D3 s0 |: D! G" {' A
- uint32_t FilterElementW1;# E7 [+ z2 q+ g$ D y/ a
- uint32_t FilterElementW2;
2 s- c4 }& ~& D7 T$ T, Q - uint32_t *FilterAddress;0 N4 l) J3 s4 O5 m& B) T. Q
- HAL_FDCAN_StateTypeDef state = hfdcan->State;
( z5 H# v+ ^4 l& v/ X* c
( x; q3 z: m; A) l% q. l- if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
& R( U0 Z2 }# ^ Y2 G* k - {5 z# m5 d6 p$ O2 }& S
- /* 检测函数参数 */
+ }# Q1 z: g$ m" [* G! F7 |; I - assert_param(IS_FDCAN_ID_TYPE(sFilterConfig->IdType));
+ R" `/ s' L O6 P5 y- m - assert_param(IS_FDCAN_FILTER_CFG(sFilterConfig->FilterConfig));
, b! a5 m+ ~% f; X j. r1 W- H - if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
7 v9 r' A/ g6 Z4 f. W N! [ - {5 ~5 u- I; i7 U% Y- N
- assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->RxBufferIndex, 63U));
. i* ?, K- D. c% U2 @, Y. N - assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->IsCalibrationMsg, 1U));
+ Y+ r# f$ U2 N! m - }. l) B! L5 H0 C }
; F* Q; Z c: O- R4 ?, P- /* 标准ID */1 m* n" s, _9 y+ f. y* `) n
- if (sFilterConfig->IdType == FDCAN_STANDARD_ID)
- n4 N9 b: A6 ~% D) d N - {
9 C B8 v4 \* c - /* 检测函数形参 */* M1 O. J+ \' g Z
- assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.StdFiltersNbr - 1U)));
, _; s, J. |* d0 I H( C7 F - assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x7FFU));
3 d2 L3 H( g! D4 Y$ k - if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)3 f9 a! k) o3 s+ b: ~7 B# a
- {: P& q6 k" t( f% ]2 l; |
- assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x7FFU));
: ~, S: a7 q6 c; t4 g$ _6 T* u - assert_param(IS_FDCAN_STD_FILTER_TYPE(sFilterConfig->FilterType));/ J1 C# e" s( ]2 t( @
- }
4 C2 H9 I: {1 }( q3 i( m - 8 {( f8 k2 {2 X6 p/ z) f
- /* 构建过滤元素 */
2 ^0 x& d6 i9 v* H! A% M+ S+ r - if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)) m8 g' t- C6 s- Q* |4 l7 i% V
- {
* e$ s) E) u/ Z$ _ - FilterElementW1 = ((FDCAN_FILTER_TO_RXBUFFER << 27U) |! I% p+ Z0 a. @! c7 ?
- (sFilterConfig->FilterID1 << 16U) |% v* h u0 L/ i l6 m
- (sFilterConfig->IsCalibrationMsg << 8U) |/ I3 s9 y6 N y) w+ W) t0 S0 ]
- sFilterConfig->RxBufferIndex);& H2 W- R- q, T: r$ `3 \; n) R
- }" ]1 }% U" G/ } I1 C* i) j2 Q5 N
- else! h& G0 }0 W; _! B& y2 z" w
- {
3 H3 x5 h$ n& p+ O: i6 i' k - FilterElementW1 = ((sFilterConfig->FilterType << 30U) |$ }6 [' H% h2 D1 ~
- (sFilterConfig->FilterConfig << 27U) |% j! ]/ [' z5 _$ P8 \% ?$ L& F8 {
- (sFilterConfig->FilterID1 << 16U) |, Q- S$ ?& a V/ O7 t- J
- sFilterConfig->FilterID2);
5 V% W" f- |. {# i- F+ L% W - }
2 `' v) }' f1 ?0 j& v - / t: m: k, _2 o' ~; U
- /* 计算过滤地址 */+ }% O j) W+ B% E5 [
- FilterAddress = (uint32_t *)(hfdcan->msgRam.StandardFilterSA + (sFilterConfig->FilterIndex * 4U));
* H; ] y, p1 u" N- \+ b* w - 4 @/ C5 Z1 j& m( m( o; D
- /* 将过滤元素写到消息RAM中 *// w. R& c; y* c& A
- *FilterAddress = FilterElementW1;+ Y0 J8 G4 }# m
- }- T3 d v. G, I# n4 z6 K2 F2 T4 O0 H
- /* 扩展ID */
- h+ B) l/ G+ @7 _2 z( A$ V - else + @; N1 J; V0 q" ]' p
- {; T7 K4 v7 s% x% M& K; f
- /* 检测函数参数 */
9 r! m! T* c- k0 H( |9 b [ - assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterIndex, (hfdcan->Init.ExtFiltersNbr - 1U)));; q1 L( n4 z: w
- assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID1, 0x1FFFFFFFU));3 M8 Z+ A% `, E+ }
- if (sFilterConfig->FilterConfig != FDCAN_FILTER_TO_RXBUFFER)& \; S L% s# H2 p- F
- {, y/ f/ X; t# k, W( n/ o X C; T& |
- assert_param(IS_FDCAN_MAX_VALUE(sFilterConfig->FilterID2, 0x1FFFFFFFU));$ z, s d; ~3 r, D/ S6 W
- assert_param(IS_FDCAN_EXT_FILTER_TYPE(sFilterConfig->FilterType));+ b- N2 x4 }: {" ?# o4 p
- }
4 i, k. Q% L: H - " @! W! o- }7 u& u" D
- /* 构建第1个word的过滤元素 */
; h( |' H5 h' h3 z0 ] - FilterElementW1 = ((sFilterConfig->FilterConfig << 29U) | sFilterConfig->FilterID1);
& V# t5 W: e; ^1 W6 P- _
4 Y" @5 t/ w# V7 t$ S Z1 u; v- /* 构建第2个word的过滤元素 */$ D+ @+ @6 v! E& k/ v& Q
- if (sFilterConfig->FilterConfig == FDCAN_FILTER_TO_RXBUFFER)
, Z O4 p5 n) i; x5 ~4 W - {1 C) s( S+ n$ f) x; h
- FilterElementW2 = sFilterConfig->RxBufferIndex;0 u) w6 ~ {) R
- }) Z7 {# Q) f& S% c" d5 I1 _2 D) n
- else
/ c( R( P# n" N - {
* k* k3 I S: G" Y - FilterElementW2 = ((sFilterConfig->FilterType << 30U) | sFilterConfig->FilterID2);1 F5 B6 A! f' W" c. {) M
- }
# b6 W1 f/ e- g6 m+ t
6 G4 s# j6 V* o- E- /* 计算过滤地址 */
8 d8 W0 G2 s: j - FilterAddress = (uint32_t *)(hfdcan->msgRam.ExtendedFilterSA + (sFilterConfig->FilterIndex * 4U * 2U));' S+ B: Y4 } a7 r5 \
- 4 c2 \4 b' B+ Q B
- /* 写过滤元素到消息RAM */
* v# L- H9 Y+ Y5 l% j4 ~3 N( M - *FilterAddress = FilterElementW1;
) R9 N9 ]$ Y# _& o+ m7 } - FilterAddress++;
0 P( b4 }! [4 c$ Y - *FilterAddress = FilterElementW2;
$ s2 S8 A+ ~; p+ {; ?9 w; U) q - }4 @* z* v, f! |/ Y& A8 I
* j9 o' g( U# A7 l+ B* i- return HAL_OK;& D$ b+ H9 G8 k$ N9 ^2 N0 K+ Q* C: j Y
- }+ H) i" F9 n0 T5 q3 U! N# |
- else6 ^! o) O4 g9 y2 u
- {
2 E+ q2 L3 |% F; P# l/ C' Y; W - /* 更新错误码e */
+ N6 ?6 k+ T O. F- z! d0 X - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
! s4 i& [6 f7 ]
( I) `* W9 q; B5 p6 a, L- return HAL_ERROR;
% Z# U$ }/ W: {2 o1 a - }
& f& s* a) Y1 _ - }
复制代码
f/ L* f. ?+ {8 n9 E函数描述:' Z# k5 b& U2 z- l+ J; K
}1 [6 v5 I( p5 s4 k, J; w
此函数主要用于设置FDCAN过滤。
6 Z9 C1 M J2 m# M$ |# x2 e7 V; }7 X) \9 f1 b# Z
函数参数:! u7 U" v$ g- p9 Y! G: N
: i6 c% q% Y) \8 J- o0 A
第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
9 V3 |* u( b9 O5 B% X! x; T 第2个参数是FDCAN_FilterTypeDef类型结构体变量,主要用于过滤参数配置。
" e1 ?* S/ B2 n0 t2 u7 N- ~# D$ c c2 b 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。- Q7 ]5 J8 z, z) a, d
使用举例:0 f( x6 V8 a/ y1 d. C
! T6 D: q" `- P7 A% W" x
- FDCAN_HandleTypeDef hfdcan1;; C5 N' o8 A/ s' m Q
& Q& U. C2 G( T% f" ?- /*
( Y5 o+ N! X* c$ d1 k - *********************************************************************************************************/ {4 \2 u5 {, S# q
- * 函 数 名: bsp_InitCan1! Y4 H" s% r4 k( g. X3 N3 a+ U
- * 功能说明: 初始CAN1
) E& O, s3 B+ f$ G: U - * 形 参: 无) Y8 K1 m; N: k/ Z3 I
- * 返 回 值: 无
4 ]! X8 L; p" M - *********************************************************************************************************' S/ }; x* ], b& }6 s" k
- */; X7 \2 \8 U3 z- c7 p
- void bsp_InitCan1(void)
- g& _; L3 |4 @6 I - { * I& P" S+ r) r; A, |
-
# T1 t+ d. L- d) d4 `: x* ^* `6 X1 K7 z - /*
: K N7 Q' [2 s* J - 配置过滤器, 过滤器主要用于接收,这里采样屏蔽位模式。
8 d8 u" c, m u6 A. [7 Y - FilterID1 = filter% o+ ^7 m+ h" v' E; `/ A
- FilterID2 = mask; n1 c) O$ }( [
- ( x- U( | x7 C
- FilterID2的mask每个bit含义
* i& c3 t- n. B - 0: 不关心,该位不用于比较;
; \/ e4 |* G1 L# b - 1: 必须匹配,接收到的ID必须与滤波器对应的ID位相一致。$ ]$ @* c# ]4 A6 }$ j
- : x5 Z9 g9 \$ I; k( b- ~0 @
- 举例说明:
7 O" ?6 R# ?- @% b0 K - FilterID1 = 0x111
/ @: K2 c+ W, ~# v" P6 s$ ?2 @ - FilterID2 = 0x7FF
; w" I) q! h2 h8 s, P - 表示仅接收ID为0x111的FDCAN帧。
6 l8 g4 l6 Y' x" j5 `) ]0 m - 7 w6 h" U( }, s1 B5 Z% @; S
- */, B" R$ ^4 c" a) r, e
- sFilterConfig1.IdType = FDCAN_STANDARD_ID; /* 设置标准ID或者扩展ID */
7 l1 i: p% {1 o5 F1 }, f% A - /* 用于过滤索引,如果是标准ID,范围0到127。如果是扩展ID,范围0到64 */
4 z Q9 l6 X, P! P9 L - sFilterConfig1.FilterIndex = 0; 8 m; g' t& S7 g. @1 u
- sFilterConfig1.FilterType = FDCAN_FILTER_MASK; /* 过滤器采样屏蔽位模式 */
% r1 F1 f9 q3 G/ y0 t* h% j+ ^ - sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; /* 如果过滤匹配,将数据保存到Rx FIFO 0 */
. V& T. ?" t' N - sFilterConfig1.FilterID1 = 0x111; /* 屏蔽位模式下,FilterID1是消息ID */
) `! o, T9 h4 }7 D - sFilterConfig1.FilterID2 = 0x7FF; /* 屏蔽位模式下,FilterID2是消息屏蔽位 */ U8 i- o! y" s% M; p( e
- HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1); /* 配置过滤器 */
! m$ w6 E+ K B" P# q% s - 8 |- t0 N8 |2 X! |' ^3 T+ l) t& K
- }
复制代码
- \1 a0 L* _) w# Q n: J91.4.4 函数HAL_FDCAN_ConfigFifoWatermark
! A# a- u' |# Q' k3 ?函数原型:1 ?$ r: p! k+ T2 L
/ d$ C f3 j- Z U% k1 {
- HAL_StatusTypeDef HAL_FDCAN_ConfigFifoWatermark(FDCAN_HandleTypeDef *hfdcan, uint32_t FIFO, uint32_t Watermark)
2 k4 Q: y' ~$ |1 K! u& H - {9 D2 ]$ l" H) j# M1 v: L
- /* 检测参数 */* ^, |+ u* }+ s
- assert_param(IS_FDCAN_FIFO_WATERMARK(FIFO));/ I _$ x, }$ Q5 `. U) q
- if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
4 ^# | z' N1 f - {
& c/ G5 T5 H. }$ b6 G3 o# | - assert_param(IS_FDCAN_MAX_VALUE(Watermark, 32U));- r/ g. z7 P7 {. Y3 O
- }
9 R/ J; }1 J# e, h0 V* h2 B- C - else /* (FIFO == FDCAN_CFG_RX_FIFO0) || (FIFO == FDCAN_CFG_RX_FIFO1) */
' h9 h/ V9 g, V9 u# u1 [ - {
' u1 u* |: T( w: T2 e - assert_param(IS_FDCAN_MAX_VALUE(Watermark, 64U));* V! R- i4 Y: y S& q& y6 ]4 A) }: H. @
- }
$ ~- ?% @0 R/ F8 W
; m" u% [" ]+ y3 G$ n- if (hfdcan->State == HAL_FDCAN_STATE_READY)
! Y; @0 E! _) b8 \2 ~$ M - {7 N! f" J7 B8 B5 |% |
- /* 设置发送事件FIFO */: {4 u' u$ ?0 B- L( E9 N! C x
- if (FIFO == FDCAN_CFG_TX_EVENT_FIFO)
% p8 K$ D. r8 m& _ - {4 C4 f* u! L4 R1 N( T* _& o
- MODIFY_REG(hfdcan->Instance->TXEFC, FDCAN_TXEFC_EFWM, (Watermark << FDCAN_TXEFC_EFWM_Pos));" J- f. a, _ r) D' Q6 x! o
- }
) L6 M3 d3 C" C+ o1 H& O$ v - /* 设置接收FIFO0 */
O0 j1 ^! F% I) d/ p - else if (FIFO == FDCAN_CFG_RX_FIFO0)7 k5 x/ ]3 o% P6 x* h$ d! R; }
- {/ Y; E* }( S9 X( q) E* z. F. }
- MODIFY_REG(hfdcan->Instance->RXF0C, FDCAN_RXF0C_F0WM, (Watermark << FDCAN_RXF0C_F0WM_Pos));. u0 x+ B4 T* i- t+ p" [' [- ~
- }' l$ E# o; }& k8 E0 e$ N! C' r n; C
- /* 设置接收FIFO1 *// r$ L4 h! e0 [6 _
- else
- I1 f3 H! k7 A - {: T5 Y/ X# |2 I6 p0 q! b1 S' c0 V
- MODIFY_REG(hfdcan->Instance->RXF1C, FDCAN_RXF1C_F1WM, (Watermark << FDCAN_RXF1C_F1WM_Pos));4 f& M! @ C- t2 c2 E7 B. r
- }
( }. r# I! u7 s+ a1 T% h - 7 p9 v! G) l5 W# u" M3 @8 D
- /* 返回状态 */
- [4 e2 u0 O' x4 m - return HAL_OK;; ]1 u( C* L" i1 Q* x7 ?* D
- }
( f. f( Q' ]' e: s - else; f* N% ^% l, [$ M& h) M
- {: R7 H5 [ n& Y: h/ r) {7 h
- /* 更新错误码 */; t/ h3 u' e& Z. T0 G' E9 I
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;" _; c2 x! O7 t: d
( p2 C* |4 c) F" f& M- return HAL_ERROR;
) y/ e5 | E, z. { - }
, _+ ~8 u( r/ F8 j - }
复制代码 , z' q/ v% T9 }2 o* k. i5 y
函数描述:
. r) D `& `5 V( P7 l0 s- D' V% m! }, X( J5 E$ V% J( E
此函数主要用于配置FIFO Watermark
0 C- R; k, Y" ^
9 d& v! K s X- c8 C- f, I函数参数:
) K8 a2 d. `' ?9 t
' u" d8 `* s! a1 x8 I7 b7 [0 E( Z$ D 第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
3 U, n& F& t6 J: ^' o 第2个参数是FDCAN FIFO Watermark
. Y4 l* u% X' z3 |- D- #define FDCAN_CFG_TX_EVENT_FIFO ((uint32_t)0x00000000U) /*!< Tx event FIFO */! ?) b7 `+ F+ y- }3 D
- #define FDCAN_CFG_RX_FIFO0 ((uint32_t)0x00000001U) /*!< Rx FIFO0 */
; m2 f0 M$ _% N8 K - #define FDCAN_CFG_RX_FIFO1 ((uint32_t)0x00000002U) /*!< Rx FIFO1 */
复制代码
5 }& q' i, S; R8 q& R! T 第3个参数FIFO Watermark 中断位置,如果是FDCAN_CFG_TX_EVENT_FIFO,范围0到32,如果是FDCAN_CFG_RX_FIFO0 或FDCAN_CFG_RX_FIFO1,范围0到64。
4 B9 D4 A. F- v9 `8 @ 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
, z4 P9 H+ d; D; N使用举例:# \! N! e1 g# K% F2 Y- K
8 Q7 c) O. Y$ L% }4 X; D* d. B
- FDCAN_HandleTypeDef hfdcan1;8 K! @8 y; ~3 r( [+ d* m! ?
, U8 E' ?. ?8 A Z$ o- /* 设置Rx FIFO0的wartermark为1 */
1 f$ X& _9 P2 h$ r - HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
复制代码 4 F- p+ g5 g/ x$ i: l
91.4.5 函数HAL_FDCAN_ActivateNotification
1 E; Y8 e2 `$ E6 I5 c函数原型:
" ~$ L/ W! I- P, a/ ]- o
+ R5 z# v- n5 w! e7 ~- HAL_StatusTypeDef HAL_FDCAN_ActivateNotification(FDCAN_HandleTypeDef *hfdcan, uint32_t ActiveITs, uint32_t BufferIndexes)
# t/ q- [% x. I2 F2 H7 G - {& x# J% {; z) o( z% K$ B
- HAL_FDCAN_StateTypeDef state = hfdcan->State;) C- a/ c0 V3 z
- 8 k4 T) k7 _3 G* G; _
- /* 检测函数形参 */
, {2 E. `, C+ G9 W; b# G0 n - assert_param(IS_FDCAN_IT(ActiveITs));
' i; |4 t( l7 m - / D% d, [3 _+ b' o
- if ((state == HAL_FDCAN_STATE_READY) || (state == HAL_FDCAN_STATE_BUSY))
+ C+ d& A; b: d# P5 ^5 c1 H7 q - {
! i, p* G: @0 m- t, J2 z( \ - /* 使能中断行 */
" E" \! b: q" F" d! k& K/ f/ G - if ((ActiveITs & hfdcan->Instance->ILS) == 0U)
( X( O3 L. i6 S# ? - {
! Q4 e5 V+ {) ~( ?! g - /* 使能中断行0 */
% ]" H# f; g, t, n - SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE0);
: c, ]7 f2 `5 ?5 x" U - } K$ x: F! u- q
- else if ((ActiveITs & hfdcan->Instance->ILS) == ActiveITs) |* b9 m5 Y+ |+ Y0 K& E/ U5 b8 q: f
- {) W4 O4 k G7 M+ ]0 f. G
- /* 使能中断行1 */
# w1 [ {; S/ w( w2 }9 W - SET_BIT(hfdcan->Instance->ILE, FDCAN_INTERRUPT_LINE1);
; b2 Q3 A# e! V% `* M - }' M1 o3 b4 @% M) M2 O' z
- else
4 ~6 { Q$ c* ?+ x* g. w1 E `3 [- z- X - {, W# N! x, A/ D8 ^1 M
- /* 使能中断行0和中断行1 */8 q. x. c0 J$ V* F0 F
- hfdcan->Instance->ILE = (FDCAN_INTERRUPT_LINE0 | FDCAN_INTERRUPT_LINE1);' \7 M4 C: s: |) K+ F) w! c h5 @
- }
6 m% N% b$ \" B; `1 h - \: t' N" r: Y
- if ((ActiveITs & FDCAN_IT_TX_COMPLETE) != 0U)/ G- j8 V% F% _( v& K% B
- {! F% w. ?1 u( y v
- /* 使能Tx Buffer Transmission 中断 */
2 [) P: d2 r) U S# U# i - SET_BIT(hfdcan->Instance->TXBTIE, BufferIndexes);* M. h) a9 Q* J; b' h4 z$ v, b
- }! H$ z# {9 s7 A: l0 T" m( T
7 q6 C' _- X5 _+ ~. {$ P- if ((ActiveITs & FDCAN_IT_TX_ABORT_COMPLETE) != 0U)3 G3 G& @+ _5 v; p
- {* i, w) O! h/ c$ A
- /* 使能 Tx Buffer Cancellation Finished 中断 */
3 M7 v7 @! V8 `& k - SET_BIT(hfdcan->Instance->TXBCIE, BufferIndexes);+ b0 A& i; H) d L+ d$ ~# W' C
- }$ T5 C7 s# f1 R3 q% s: t
- - A2 s. `7 `4 V2 M* F% a C
- /* 使能选择的中断 */& n' t- t5 l& A' m# M' A
- __HAL_FDCAN_ENABLE_IT(hfdcan, ActiveITs);3 b) n& m2 q8 W D5 i p! |
0 r9 |0 U: L8 ?& H- /* 返回函数状态 */( U0 g7 E! s$ b" B& [
- return HAL_OK;! C3 m! ?& S4 f, {/ B8 O
- }
7 B% V& R9 p6 w - else1 ?8 E2 h0 r0 F+ _
- {0 K5 |2 T" r4 n( U; h5 e$ s/ T
- /* 更新错误码 */& g( I! u4 {; t! t: w4 _
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_INITIALIZED;
6 i" g) F" p# P% b3 t; o, l; g - # N! }$ n+ N$ E2 o2 `
- return HAL_ERROR;3 d8 f- s$ K* _+ a. H
- }, Z- v8 Y, f, R- p* @; ?: w
- }
复制代码
$ ]7 l' J! d5 r2 O" j函数描述:
- P" ~) c, b9 l& n( u1 ]3 `% l5 H v1 }7 _0 V# H7 C
此函数主要用于使能中断。2 ^' a* c5 ]9 o4 l1 L0 q, Q" L1 [
3 r/ m% Q, N- m- ~. \+ x4 W0 ~# o
函数参数:
: Z4 f- A1 c7 l( ?4 k( m8 e
5 ]3 U- t( a* Z5 M) l 第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。
- T* ]- `5 @: C$ v 第2个参数用于设置要使能的中断,支持的参数如下:' a# H8 g$ c& t y# v
- #define FDCAN_IT_TX_COMPLETE FDCAN_IE_TCE /*!< Transmission Completed
) k# @; C, b7 P5 _5 ` - #define FDCAN_IT_TX_ABORT_COMPLETE FDCAN_IE_TCFE /*!< Transmission Cancellation Finished */
* a& }; Z, o1 }) D$ C* E* \) H - #define FDCAN_IT_TX_FIFO_EMPTY FDCAN_IE_TFEE /*!< Tx FIFO Empty
3 _3 }0 y& J0 u& W. C - #define FDCAN_IT_RX_HIGH_PRIORITY_MSG FDCAN_IE_HPME /*!< High priority message received */
" X0 Q+ [1 q* Y m2 } - #define FDCAN_IT_RX_BUFFER_NEW_MESSAGE FDCAN_IE_DRXE /*!< At least one received message stored into a Rx Buffer 5 {8 f' O2 R! F
- #define FDCAN_IT_TIMESTAMP_WRAPAROUND FDCAN_IE_TSWE /*!< Timestamp counter wrapped around */
! D3 z7 F" O+ D% d# u' F3 M - #define FDCAN_IT_TIMEOUT_OCCURRED FDCAN_IE_TOOE /*!< Timeout reached */) D" G7 }2 u9 I. Y! e, y0 Z7 b/ A
- ! L( u% H7 }8 K6 o9 g
- #define FDCAN_IT_CALIB_STATE_CHANGED (FDCANCCU_IE_CSCE << 30) /*!< Clock calibration state changed */
2 y I! y3 V+ j5 e - #define FDCAN_IT_CALIB_WATCHDOG_EVENT (FDCANCCU_IE_CWEE << 30) /*!< Clock calibration watchdog event occurred 9 k# Q: I# |- W
- #define FDCAN_IT_TX_EVT_FIFO_ELT_LOST FDCAN_IE_TEFLE /*!< Tx Event FIFO element lost */3 v" f- L* ?: s6 J5 h: {
- #define FDCAN_IT_TX_EVT_FIFO_FULL FDCAN_IE_TEFFE /*!< Tx Event FIFO full */& G) S s$ {1 E- a
- #define FDCAN_IT_TX_EVT_FIFO_WATERMARK FDCAN_IE_TEFWE /*!< Tx Event FIFO fill level reached watermark */2 P! ?+ U) U2 [# m
- #define FDCAN_IT_TX_EVT_FIFO_NEW_DATA FDCAN_IE_TEFNE /*!< Tx Handler wrote Tx Event FIFO element */
( s! a7 U8 v: X. G: F$ J7 _
7 g7 c3 q; _; _( ~/ {5 d- #define FDCAN_IT_RX_FIFO0_MESSAGE_LOST FDCAN_IE_RF0LE /*!< Rx FIFO 0 message lost */9 \* _: c7 ]$ v7 ], d$ y4 z
- #define FDCAN_IT_RX_FIFO0_FULL FDCAN_IE_RF0FE /*!< Rx FIFO 0 full */
& z8 h" M9 R; l: ?/ L - #define FDCAN_IT_RX_FIFO0_WATERMARK FDCAN_IE_RF0WE /*!< Rx FIFO 0 fill level reached watermark */
" J5 E6 Z' B9 a7 d - #define FDCAN_IT_RX_FIFO0_NEW_MESSAGE FDCAN_IE_RF0NE /*!< New message written to Rx FIFO 0 */
: c M# \; P; L. q" q: \6 m2 n - 3 ^ n( H+ V) R6 ?* Q
- #define FDCAN_IT_RX_FIFO1_MESSAGE_LOST FDCAN_IE_RF1LE /*!< Rx FIFO 1 message lost */
6 A2 ]6 z3 t, @! B( d' f+ M- _ - #define FDCAN_IT_RX_FIFO1_FULL FDCAN_IE_RF1FE /*!< Rx FIFO 1 full */
4 d1 V+ {2 u1 f - #define FDCAN_IT_RX_FIFO1_WATERMARK FDCAN_IE_RF1WE /*!< Rx FIFO 1 fill level reached watermark */' x9 O0 U$ u% R+ n
- #define FDCAN_IT_RX_FIFO1_NEW_MESSAGE FDCAN_IE_RF1NE /*!< New message written to Rx FIFO 1 */% }* f6 _7 I& D
- % {: `% u, {8 l+ _$ ?7 p+ s
- #define FDCAN_IT_RAM_ACCESS_FAILURE FDCAN_IE_MRAFE /*!< Message RAM access failure occurred
) E, R+ R- Y' ^" M( p - #define FDCAN_IT_ERROR_LOGGING_OVERFLOW FDCAN_IE_ELOE /*!< Overflow of FDCAN Error Logging Counter occurred
) K/ t% a y n6 ~3 [ - #define FDCAN_IT_RAM_WATCHDOG FDCAN_IE_WDIE /*!< Message RAM Watchdog event due to missing READY 2 @& i! D3 s) F$ V
- #define FDCAN_IT_ARB_PROTOCOL_ERROR FDCAN_IE_PEAE /*!< Protocol error in arbitration phase detected 6 P4 G& W w J
- #define FDCAN_IT_DATA_PROTOCOL_ERROR FDCAN_IE_PEDE /*!< Protocol error in data phase detected % ~$ X& O1 r. R7 U' l; e. z
- #define FDCAN_IT_RESERVED_ADDRESS_ACCESS FDCAN_IE_ARAE /*!< Access to reserved address occurred
/ f- y1 S! [. t - #define FDCAN_IT_ERROR_PASSIVE FDCAN_IE_EPE /*!< Error_Passive status changed */
/ D3 X4 y5 ]( X" ]0 L* E- b/ C - #define FDCAN_IT_ERROR_WARNING FDCAN_IE_EWE /*!< Error_Warning status changed */2 G& W ^* y2 r! X4 n
- #define FDCAN_IT_BUS_OFF FDCAN_IE_BOE /*!< Bus_Off status changed */
复制代码
( W5 A x4 L: g5 W# y! w$ O4 n3 n 第3个参数是Tx Buffer Indexes,可以如下参数的任意组合:% J9 l* f, m1 W$ U$ B9 A. ^
- #define FDCAN_TX_BUFFER0 ((uint32_t)0x00000001U) /*!< Add message to Tx Buffer 0 */( ]4 X t+ i* c
- #define FDCAN_TX_BUFFER1 ((uint32_t)0x00000002U) /*!< Add message to Tx Buffer 1 */5 J* Z. f) l/ } ~! z* v) \/ J
- #define FDCAN_TX_BUFFER2 ((uint32_t)0x00000004U) /*!< Add message to Tx Buffer 2 */; I# K1 p! w. m
- #define FDCAN_TX_BUFFER3 ((uint32_t)0x00000008U) /*!< Add message to Tx Buffer 3 */6 F3 | c/ ^% H5 W
- #define FDCAN_TX_BUFFER4 ((uint32_t)0x00000010U) /*!< Add message to Tx Buffer 4 */' V% @3 P- B, Z: o- j$ m7 x3 C
- #define FDCAN_TX_BUFFER5 ((uint32_t)0x00000020U) /*!< Add message to Tx Buffer 5 */
, Z. f+ H( s# K: I( q - #define FDCAN_TX_BUFFER6 ((uint32_t)0x00000040U) /*!< Add message to Tx Buffer 6 */
% c& B# T8 Z& i3 } - #define FDCAN_TX_BUFFER7 ((uint32_t)0x00000080U) /*!< Add message to Tx Buffer 7 */
; g4 C2 M! ^8 b( b, ]) V) q6 \0 ^ - #define FDCAN_TX_BUFFER8 ((uint32_t)0x00000100U) /*!< Add message to Tx Buffer 8 */
: G9 e: K& k) x+ G: u - #define FDCAN_TX_BUFFER9 ((uint32_t)0x00000200U) /*!< Add message to Tx Buffer 9 */
I. R& a0 w9 w - #define FDCAN_TX_BUFFER10 ((uint32_t)0x00000400U) /*!< Add message to Tx Buffer 10 */( {5 l( P- d- [
- #define FDCAN_TX_BUFFER11 ((uint32_t)0x00000800U) /*!< Add message to Tx Buffer 11 */
: C( q! }/ g8 f - #define FDCAN_TX_BUFFER12 ((uint32_t)0x00001000U) /*!< Add message to Tx Buffer 12 */
0 W0 F- X, y# h( c - #define FDCAN_TX_BUFFER13 ((uint32_t)0x00002000U) /*!< Add message to Tx Buffer 13 */% g& w! ^ a* G. @! D
- #define FDCAN_TX_BUFFER14 ((uint32_t)0x00004000U) /*!< Add message to Tx Buffer 14 */9 n/ B B) W& O) B. s
- #define FDCAN_TX_BUFFER15 ((uint32_t)0x00008000U) /*!< Add message to Tx Buffer 15 */+ f& \; O( ^, g0 S
- #define FDCAN_TX_BUFFER16 ((uint32_t)0x00010000U) /*!< Add message to Tx Buffer 16 */
8 s3 ^! B8 K9 b2 ], _0 f# [5 a - #define FDCAN_TX_BUFFER17 ((uint32_t)0x00020000U) /*!< Add message to Tx Buffer 17 */
- R) n7 Y" X0 S, T - #define FDCAN_TX_BUFFER18 ((uint32_t)0x00040000U) /*!< Add message to Tx Buffer 18 */ N8 ` m$ }4 {: t+ P
- #define FDCAN_TX_BUFFER19 ((uint32_t)0x00080000U) /*!< Add message to Tx Buffer 19 */% v2 S' a7 A3 ?7 z
- #define FDCAN_TX_BUFFER20 ((uint32_t)0x00100000U) /*!< Add message to Tx Buffer 20 */
3 D, e0 {$ _+ b - #define FDCAN_TX_BUFFER21 ((uint32_t)0x00200000U) /*!< Add message to Tx Buffer 21 */2 ~, u0 G. p! k5 @) K
- #define FDCAN_TX_BUFFER22 ((uint32_t)0x00400000U) /*!< Add message to Tx Buffer 22 */: ?( K1 n9 U9 ?$ ~) N) _; S9 y! b+ q
- #define FDCAN_TX_BUFFER23 ((uint32_t)0x00800000U) /*!< Add message to Tx Buffer 23 */" U6 ?9 g% \- z* u+ u
- #define FDCAN_TX_BUFFER24 ((uint32_t)0x01000000U) /*!< Add message to Tx Buffer 24 */
! |5 U; b3 k2 F. {. Z8 G" N: ?, F - #define FDCAN_TX_BUFFER25 ((uint32_t)0x02000000U) /*!< Add message to Tx Buffer 25 */: e1 ]9 m. e; q0 u- B/ x
- #define FDCAN_TX_BUFFER26 ((uint32_t)0x04000000U) /*!< Add message to Tx Buffer 26 */
3 {$ J9 G. t$ E* X0 E, m) E1 N! ] - #define FDCAN_TX_BUFFER27 ((uint32_t)0x08000000U) /*!< Add message to Tx Buffer 27 */$ s$ E1 Y) L. q) X1 v$ _
- #define FDCAN_TX_BUFFER28 ((uint32_t)0x10000000U) /*!< Add message to Tx Buffer 28 */4 D( s6 m4 b. X! D
- #define FDCAN_TX_BUFFER29 ((uint32_t)0x20000000U) /*!< Add message to Tx Buffer 29 */- y6 v0 K( }4 i( D
- #define FDCAN_TX_BUFFER30 ((uint32_t)0x40000000U) /*!< Add message to Tx Buffer 30 */
, Q4 X8 h/ o1 s( ~7 v - #define FDCAN_TX_BUFFER31 ((uint32_t)0x80000000U) /*!< Add message to Tx Buffer 31 */
复制代码 6 P0 | ?! U9 H1 L+ N. B, i7 \$ H
如果第2个参数不包括FDCAN_IT_TX_COMPLETE或FDCAN_IT_TX_ABORT_COMPLETE,此参数将被忽略。6 d/ a1 O1 u7 Y9 }
4 W, e7 X6 H5 h8 F" d4 I6 @, p! R" R 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。1 G1 S e5 X E
使用举例:( C% _, V) k; l5 @; ?
8 z1 c; x# _! VFDCAN_HandleTypeDef hfdcan1;
' I3 c0 w% w" }4 O3 n
( E/ {, {6 ~/ v' T* Z/* 激活RX FIFO0的watermark通知中断,位开启Tx Buffer中断*/: ]+ [: U5 b+ h7 D' X
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);( B7 e+ ?' ]% `; l) R, U6 l
91.4.6 函数HAL_FDCAN_Start" }) L* e" x& ]
函数原型:
- n3 z* s) D @, w0 I
, W' P6 P; L8 A7 L& z( z) T- HAL_StatusTypeDef HAL_FDCAN_Start(FDCAN_HandleTypeDef *hfdcan)2 k8 n& P& |3 ]
- {
4 r+ y8 b3 R* E. b7 X5 T5 n - if (hfdcan->State == HAL_FDCAN_STATE_READY)
; n8 D$ b+ h0 t( E0 I- Q. A Z - {
2 W/ z8 P/ j8 H4 v! j% l - /* 设置FDCAN外设状态 */
/ \: k9 Y& C7 G0 x - hfdcan->State = HAL_FDCAN_STATE_BUSY;
) l: I, ~) _9 e5 t! K8 |* a
+ x9 Y* g9 D. W! [5 @- /* 请求离开初始化状态 */, I( [2 @7 b" [$ i9 f9 c! w7 b
- CLEAR_BIT(hfdcan->Instance->CCCR, FDCAN_CCCR_INIT);. `; l, S( d9 Q5 _; G
- ! `& b: K* `5 F0 R3 |
- /* 设置错误码 */
! D) }7 y9 E# T) q - hfdcan->ErrorCode = HAL_FDCAN_ERROR_NONE;( x7 T m. i5 }- H
- % a# ?4 S! T% F% C" v8 a1 Z1 }
- return HAL_OK;
. u9 n1 d0 [3 J { - }
* k4 d$ a' i7 d; M' j% V5 d - else7 U) @9 d+ N4 b( I) O5 s
- {1 e7 M4 b$ ?: Q; f- r: h
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_READY;& ?0 i$ L1 U" j3 D/ D4 a# Q5 ~
2 K2 }" M. B' N3 S8 o5 ~; Y- return HAL_ERROR;
% U5 e; \ i% F - }
; h4 g* r$ R9 P - }
复制代码
, Z% `! g6 T& x0 S j8 }函数描述:, }- b+ |. w: H1 Y
$ }+ i+ p( l- Q1 J" O! }3 i: ?; @% Z此函数主要用于启动FDCAN。 |# Z9 }8 p3 `5 [% [; D0 k
( Y. q$ \; W/ j9 C
函数参数:0 }7 K/ ~% `% `' O
8 ?" q! ^3 A( @; x 第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。3 R& U/ G, r/ }1 |1 v3 O7 N( U
返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
% k$ Q6 H/ \' {' i; G+ A6 I使用举例:
7 A! R/ _* L+ b( @$ K1 X5 I& G- S( m9 I/ E7 F% }
- /**. a% M& M& w0 Y7 n6 c
- * @brief Writes block(s) to a specified address in an SD card, in DMA mode.5 [* @8 }4 O, A! S
- * @param pData: Pointer to the buffer that will contain the data to transmit6 A% s, n* B- Q
- * @param WriteAddr: Address from where data is to be written8 U, S& D+ F. z. f4 \$ N; Z! L# J
- * @param NumOfBlocks: Number of SD blocks to write! Q: J; D" ^; S) d
- * @retval SD status
, p6 e% G* M3 S# G9 J - */
! k$ g0 h" d# W1 P- ? - uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); S. M* S9 M, t% n) C0 H9 w' F: K
- {, b- \: \+ ~3 ] ~+ u
- 8 ?% M6 J) U. h2 O
- if( HAL_SD_WriteBlocks_DMA(&uSdHandle, (uint8_t *)pData, WriteAddr, NumOfBlocks) == HAL_OK)$ G9 ]" k' l( s2 |4 S9 \
- {
) G4 X/ n" ?% I; H0 }0 K - return MSD_OK;' N. w! H5 o7 m N# `+ s/ R
- }
8 G9 z- t( ~+ x: ?& a5 V0 k$ U; M - else- t) {8 D* |" m0 V
- {) D/ t! U) n/ V# {- u
- return MSD_ERROR;
+ N7 p8 @0 b8 F/ Z+ `/ Y$ G/ j - }- b3 w% ?* g3 u1 ]8 c
- }
复制代码
2 E9 G! k+ o3 ~+ a3 w& F0 [91.4.7 函数HAL_FDCAN_AddMessageToTxFifoQ
, P* B& T- F: r! H9 o函数原型:% `; } |7 [" k6 v
, n- ^) t) P! ^7 o
- HAL_StatusTypeDef HAL_FDCAN_AddMessageToTxFifoQ(FDCAN_HandleTypeDef *hfdcan, FDCAN_TxHeaderTypeDef *pTxHeader, uint8_t *pTxData)# W: u. L5 }) a) T$ k) ~! G" y
- {4 P; p- l }) n! }' b, x
- uint32_t PutIndex;
2 ]7 l' K4 w4 J3 X - + x4 v: q+ p% K5 `& A$ ~
- /* 检查函数形参 */
9 f! r: k7 L' d& k - assert_param(IS_FDCAN_ID_TYPE(pTxHeader->IdType));
0 ?$ {$ [8 F; w% C' B) ^ - if (pTxHeader->IdType == FDCAN_STANDARD_ID)
4 M, R' Z+ I0 E) f - {
% [2 q) X1 U8 e4 s9 S - assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x7FFU));5 C6 a7 R) `# g0 Q, W" Z/ Z+ K
- }
1 u* U8 }7 Y6 P) y j! E - else /* pTxHeader->IdType == FDCAN_EXTENDED_ID */5 w( Y: r/ v1 ^: n7 d! i( S
- {0 A) C+ E* C2 a
- assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->Identifier, 0x1FFFFFFFU));3 n! F m6 x, n/ H, N/ ?$ ?( D
- }
3 j0 B- `" S" b0 B- }, n - assert_param(IS_FDCAN_FRAME_TYPE(pTxHeader->TxFrameType));
1 T( a. o J$ u - assert_param(IS_FDCAN_DLC(pTxHeader->DataLength));
1 \- ^. Y4 V2 T- L# z' g, r - assert_param(IS_FDCAN_ESI(pTxHeader->ErrorStateIndicator));9 x. z+ g/ l# t: s( Y; K7 ]
- assert_param(IS_FDCAN_BRS(pTxHeader->BitRateSwitch));1 ^2 S* C# N3 W: R
- assert_param(IS_FDCAN_FDF(pTxHeader->FDFormat));, }& T M* a" W; \
- assert_param(IS_FDCAN_EFC(pTxHeader->TxEventFifoControl));4 G& _" z+ c# a. H# E
- assert_param(IS_FDCAN_MAX_VALUE(pTxHeader->MessageMarker, 0xFFU));% t, F6 B3 U/ [/ B
0 z6 E/ [7 y" @& b8 P- if (hfdcan->State == HAL_FDCAN_STATE_BUSY)
+ {7 Y+ k. K; W( \ - {* M7 ?% Z0 k4 X# H9 v
- /* 检测Tx FIFO/Queue 是否在RAM中分配到空间 */, j- R* N+ N$ S4 i; O: ^
- if ((hfdcan->Instance->TXBC & FDCAN_TXBC_TFQS) == 0U)# e) A. z+ Z( ^/ i0 |9 U/ y' u
- {1 m5 {* |& ^( Z
- /* 更新错误码 */* p2 }4 V0 J" j- N% ~: _) f
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;& u9 m' B6 N# J$ t' N/ p# L9 B8 |
- $ f e8 n; _& W$ ]+ G" H& `% U6 g
- return HAL_ERROR;2 H, Z. o2 z! r# T Q
- }
5 f* \$ G9 \& b; Q; _ - 8 R. q3 c* q8 h! ?8 ~2 g
- /* 检查Tx FIFO/Queue 是否满 */; J6 E l9 |8 e
- if ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0U)4 \: b. ~/ s" {9 ]0 H$ Z$ W
- {
* B, P+ p. j0 N1 c8 f/ _5 ? - /* 更新错误码 */7 F4 [. G( |. v8 Z4 O# T% A3 ?
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_FULL;
' ^/ Q9 B8 C0 }- Z6 _) d& x- ~% w - , U q% n m' E! Z! C) l# \
- return HAL_ERROR;
; A+ h# c* H$ E' ~: x, U. ]7 P - }
5 B1 `$ a2 ?# g$ l( Z9 f - else
( e i# U2 m D3 q! [0 x+ j - {! K# Q9 ?' I4 _2 i! N* i
- /* 获取Tx FIFO PutIndex */
- Q& N3 `# F+ z5 b7 a& r- L( [ - PutIndex = ((hfdcan->Instance->TXFQS & FDCAN_TXFQS_TFQPI) >> FDCAN_TXFQS_TFQPI_Pos);
- W7 P; H* |- _" K) H/ o - & R/ s- j% B9 |" k
- /* 添加消息到Tx FIFO/Queue */
. `0 _* U$ V3 c3 x - FDCAN_CopyMessageToRAM(hfdcan, pTxHeader, pTxData, PutIndex);( L$ \- E, {( b0 {6 F
" r4 y: X5 l: H$ M% X/ T: B2 ?- /* 激活相应的传输请求 */! n* h; d: M+ @6 Y4 Q
- hfdcan->Instance->TXBAR = ((uint32_t)1 << PutIndex);" E) ^# @4 u8 Q7 Z
- 6 i4 h; o" @/ A' }
- /* 存储最近的Tx FIFO/Queue Request Buffer Index */
+ k& }& A- g1 c+ S, C0 N - hfdcan->LatestTxFifoQRequest = ((uint32_t)1 << PutIndex);
0 g8 ^0 m3 A% R5 ~" }; U( b - }
. W. A; w, ~, O( z' _ - # g" v3 [% X9 p, m2 c9 O5 `
- /* 返回错误状态 */- W, c7 P4 S0 }3 q/ S, g7 R
- return HAL_OK;2 B+ l2 F" C# w- h+ o' q: C( x7 `
- }/ z+ V$ b- j8 S' _
- else% e8 v! ~3 v* `7 P. Y7 _ ^
- {
8 r/ v/ ? x9 g4 a - /* 更新错误码 */; @, \( c" A1 m6 A4 r: d5 W5 R l
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;/ ^2 O$ D; U: `/ f, d( O0 k
- , l9 n" S( O2 p; q! }
- return HAL_ERROR;8 q7 R i; i( x z7 w6 F
- }+ @* W6 c9 Y/ ~
- }
复制代码 % |5 o5 y% M/ J& Y+ g/ z
函数描述:8 x, f; M0 Q! n7 R
1 [" W- }0 |1 ~" s2 p- m" q" B此函数用于添加消息到Tx FIFO/Queue并激活相应的传输请求。
# s# K8 V& a' M: D( j% P
0 @; ~$ q. F! J: V5 c函数参数:2 g6 r' W7 F, P( S
$ T2 Y/ ~0 U/ `7 E" | 第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。2 J. ?# h; S: N, ~& Q
第2个参数是FDCAN_TxHeaderTypeDef类型结构体变量,用于消息发送。
& e! n: o/ ]' Y2 B, W 第3个参数是要发送的数据地址。程序里面会将数据复制到发送缓冲区。
# i C4 M8 c4 u- z! G 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
# ?1 o, X! n6 T4 @! \使用举例:
3 F1 I' Y- n$ q5 d8 ~# a0 d1 s) ]2 _' B4 F7 A$ W; s3 {4 M
- /*: {5 c1 p) M |1 ]" v
- *********************************************************************************************************! u' z8 C8 C+ u6 I; a
- * 函 数 名: can1_SendPacket5 U# G" Q e! x; _
- * 功能说明: 发送一包数据, Z1 J3 L4 J4 h8 U
- * 形 参:_DataBuf 数据缓冲区/ t! |( @/ J+ i I* Y
- * _Len 数据长度, 支持8,12,16,20,24,32,48或者64字节; n. k* n6 `# T" G3 l! Z- x4 n+ {5 E
- * 返 回 值: 无) C4 w( H; p; I$ G2 Z8 p5 ~
- *********************************************************************************************************, l$ [+ R* ?, h1 ?/ w
- */- d8 y6 n* E7 [) E
- void can1_SendPacket(uint8_t *_DataBuf, uint8_t _Len)* d7 b# Q& x7 _/ |3 w4 C& l# s
- { 5 O3 K& h6 B' w8 o6 |2 }$ o
- FDCAN_TxHeaderTypeDef TxHeader = {0};5 B& L/ n* E$ b& C, e0 E/ p+ H a' d
-
) x; b7 g9 @+ \& [+ w - /* 配置发送参数 */
/ e! d; b2 z& R - TxHeader.Identifier = 0x222; /* 设置接收帧消息的ID */
! [. A6 b& |& }2 N0 t. f) a - TxHeader.IdType = FDCAN_STANDARD_ID; /* 标准ID */
" N7 K. h: H% D k# Q8 ?% }) u - TxHeader.TxFrameType = FDCAN_DATA_FRAME; /* 数据帧 */
5 {% a* `" \2 g) x9 n - TxHeader.DataLength = (uint32_t)_Len << 16; /* 发送数据长度 */3 G/ P" i1 w* a0 E
- TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; /* 设置错误状态指示 */
+ H" X: `3 _/ z l% S - TxHeader.BitRateSwitch = FDCAN_BRS_ON; /* 开启可变波特率 */
1 @* E# n+ U/ f# p j) _# A - TxHeader.FDFormat = FDCAN_FD_CAN; /* FDCAN格式 */1 u% s' s; C. n/ u/ m
- TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;/* 用于发送事件FIFO控制, 不存储 */5 [+ X3 @/ g- g$ H) Z
- TxHeader.MessageMarker = 0; /* 用于复制到TX EVENT FIFO的消息Maker来识别消息状态,范围0到0xFF */; Z, i, d4 }6 z) s. b* p0 J
- $ w0 O, I& A% J6 ~2 y
- /* 添加数据到TX FIFO */
2 O. z' w7 h" E6 V - HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, _DataBuf);
1 d) Z! }$ `+ I - }
复制代码 % i# `/ T8 t9 y+ z) b9 T
91.4.8 函数HAL_FDCAN_GetRxMessage
* x( D: t, Y' n6 V) \函数原型:# z; [5 b3 x7 ?; l! d
9 z3 ?1 M T" r- D9 B
- HAL_StatusTypeDef HAL_FDCAN_GetRxMessage(FDCAN_HandleTypeDef *hfdcan, uint32_t RxLocation, FDCAN_RxHeaderTypeDef *pRxHeader, uint8_t *pRxData)* ]+ u7 I. I2 o- @0 {/ V4 X G& p
- {& S) K7 N* H, O( p+ Q
- uint32_t *RxAddress;
4 x6 }# M! y4 k; }6 l - uint8_t *pData;3 w8 X8 P, c6 ^" N
- uint32_t ByteCounter;% d0 q" R3 }- j3 v
- uint32_t GetIndex = 0;9 {& u* J7 S; f. m/ L
- HAL_FDCAN_StateTypeDef state = hfdcan->State;' B% b3 Q, ]7 B0 d
9 z3 B3 @. U- N( g- if (state == HAL_FDCAN_STATE_BUSY)
) h+ O0 d4 O- P: M7 k. a! h - {
9 p4 d- j" @6 _5 p - if (RxLocation == FDCAN_RX_FIFO0) /* Rx element分配到 Rx FIFO 0 */7 G% e% |# k2 y0 N" ?" g& [ I) T/ K$ q
- {
( o0 c$ E& M0 }. E- n2 F - /* 检查Rx FIFO 0 分配了RAM空间 */3 f7 E p' w# m& w- y+ j
- if ((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0S) == 0U)
) n/ @+ k9 O( i' b2 C* g - {
3 Y' Y* ^" F8 h( n3 x0 z* O - /* 更新错误码*/' p' C4 j' M1 ?! a4 T W! _
- hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
. {, d0 r* [/ f, _! y+ X, H9 h - n4 t+ q* } W; j
- return HAL_ERROR;4 n* _/ L l6 M2 L, [ ]( i
- }% v6 r* K# q4 z% g3 w
+ @: O& ]4 u0 a! W8 W- /* 检查Rx FIFO 0 非空 */
, C6 c1 p% w7 {$ @4 ` - if ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0FL) == 0U)
, @ D+ @5 M3 k R4 g- K1 o+ ^ - {! {( Y4 M5 }. y! N/ l
- /* 更新错误码*/
/ U5 u- Y+ ^8 h& ^ E9 s - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;, V& G# g5 z) ~/ t1 X. {- l* f
- , I5 m/ @' N0 o- R0 H
- return HAL_ERROR;
7 N- o, ]! n& m7 z8 x. Y5 E- v - }9 z6 z; h) x, r8 D) W% t# R
- else
. D) T" Q; ]$ U% O [ - {
( W. y0 P% D1 `7 j/ G, I. W - /* 检查Rx FIFO 0 满且开了覆盖模式 */1 E: R! b" Y0 u
- if(((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0F) >> FDCAN_RXF0S_F0F_Pos) == 1U)
+ |. k2 {- _4 U+ \; Y4 b7 k# | - {1 N$ Y b8 K: D* i5 J! z
- if(((hfdcan->Instance->RXF0C & FDCAN_RXF0C_F0OM) >> FDCAN_RXF0C_F0OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)) h. t: T( o* v* j9 U! m5 m. I0 y) w
- {" R( i# A6 a1 n
- /* 开启了覆盖模式,丢弃第1个数据 */6 m6 ^ M( N9 l' T/ k
- GetIndex = 1U;
/ }; P& K" @# T# Q: f$ a - }# K3 X' C* k( E I
- }
4 |/ h4 m3 r( m* m% ?6 D; y4 ~' ^ - , I9 ?. B2 Y+ h; k% S
- /* 计算Rx FIFO 0 element 索引 */9 S2 v! P4 E4 R$ ~4 o2 ]: F: H# ?
- GetIndex += ((hfdcan->Instance->RXF0S & FDCAN_RXF0S_F0GI) >> FDCAN_RXF0S_F0GI_Pos);
/ b8 S( M, | \( W; F0 q7 N' p: X; m: I - , E; `4 E; | I- i8 f
- /* 计算 Rx FIFO 0 element 地址 */ P, ^$ ?' ` y1 }# O8 _
- RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO0SA + (GetIndex * hfdcan->Init.RxFifo0ElmtSize * 4U));2 s R' y# W/ u9 q. w+ [9 n
- }2 T @) ~& w! {" L, s
- }
" T0 p3 O5 E& z* l. W. R - else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */
& L/ I0 A8 L& U- c- A% q - {
9 f) |$ P) ^2 x g2 E - /* 检查Rx FIFO 1 分配了RAM空间 */
9 U) B" Z3 f# _: d9 w: h - if ((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1S) == 0U)8 J/ K* Z* M2 s6 |
- {
& n0 o* d! e l0 `% w- }2 I" z - /* 更新错误码 */
* X$ K6 \" N# l1 { - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;% Z$ z# G3 v* M2 U" b1 x, p
; h0 x9 m! i+ Q% P* `! H$ C, ]& w7 m- return HAL_ERROR;
7 n+ X/ P. V5 `' k - }* B3 A) g- N$ w1 s k
- 5 P5 J( w2 b7 A3 [' p/ M
- /* 检查 Rx FIFO 0 非空 */2 h* p) J5 x7 X' O8 n7 Q; c
- if ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1FL) == 0U)2 ]5 A7 v% z5 }) I1 j3 s9 l
- {
; m0 y$ p' Z. U; ]# e - /* 更新错误码 */
' s1 O( C$ f+ i% c - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_FIFO_EMPTY;5 L( F+ A7 r2 |' `0 u. c' y
B% H% \6 _. U, H- return HAL_ERROR;
& x- ?+ e6 K8 X2 a8 j - }
) D% n, }0 D8 p0 A+ A9 g - else6 K t1 Y P7 U& A5 @4 A( \
- {
: C2 k7 ~/ j/ [! U% ` - /* 检查Rx FIFO 1 满且开了覆盖模式 */
1 E/ ^1 K1 {# a H; U+ T - if(((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1F) >> FDCAN_RXF1S_F1F_Pos) == 1U)1 C1 L9 Q+ K+ q& K7 m- ?- [& ]
- {
1 ]# S: m' A) V5 x - if(((hfdcan->Instance->RXF1C & FDCAN_RXF1C_F1OM) >> FDCAN_RXF1C_F1OM_Pos) == FDCAN_RX_FIFO_OVERWRITE)8 Z7 P0 p( r3 c( N1 T% M
- {
/ a: _1 H. t& ~ - /* 开启了覆盖模式,丢弃第1个数据 */
0 n% u2 @) {. s. ? - GetIndex = 1U;
6 C$ C8 E5 } F7 g4 p - }; q O D4 E$ L& T( e: S
- }+ d4 ~7 U# G8 {5 _- m o
- 6 v- A, {* {+ o3 ~; D0 `3 v
- /* 计算 Rx FIFO 1 element 索引 */
& X8 L, V v# J! q9 K6 K1 H# J - GetIndex += ((hfdcan->Instance->RXF1S & FDCAN_RXF1S_F1GI) >> FDCAN_RXF1S_F1GI_Pos);2 F" D0 Y/ A0 ]* t7 \
- $ R1 a" x- z2 Y* D$ U1 O4 h
- /* 计算 Rx FIFO 1 element 地址 */$ o0 \' H) H. V( E
- RxAddress = (uint32_t *)(hfdcan->msgRam.RxFIFO1SA + (GetIndex * hfdcan->Init.RxFifo1ElmtSize * 4U));
$ c% u, _% L" u% D* S - }
; _' t8 T3 O& X1 ^ - }
' c7 D3 j M# X0 w - else /* Rx element 分配了专用 Rx buffer */" n) R5 g& L3 |) t; b Y8 G
- {
4 S/ o2 I% Q5 }/ [0 m8 J3 v - /* 检查选择的buffer分配了RAM空间 */; R% i$ n% }7 \( G
- if (RxLocation >= hfdcan->Init.RxBuffersNbr)
5 @- A. O0 V- A1 }5 J - {5 K4 q6 g8 _8 O
- /* 更新错误码 */
% R$ D5 h, D% ?7 \ - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_PARAM;
# B4 J9 }& v2 D4 y& q - 7 ~+ ^* _& E* O
- return HAL_ERROR;; L4 Q9 G% h T" s- G+ b2 p. {
- }
) N' ~2 \8 `: p8 j - else0 m( L6 y5 y# K! N
- {. c" S: l/ @% g) s" P7 T
- /* 计算Rx buffer 地址 */
: h2 {: y. \6 u6 c5 C5 \) K - RxAddress = (uint32_t *)(hfdcan->msgRam.RxBufferSA + (RxLocation * hfdcan->Init.RxBufferSize * 4U));0 r! n9 s! L6 q
- }
5 w& n- y# D2 P! q+ Q8 D5 O' z - }
. d) Z1 l" @8 G8 R! c- \: P6 n; d - 3 d7 Q! n; J+ f1 f1 o
- /* 接收IdType */# [. S7 v# B) d: H0 V- ~( Z
- pRxHeader->IdType = *RxAddress & FDCAN_ELEMENT_MASK_XTD;& K7 i1 T$ M' X- P) e, Z
- 3 }# d$ F3 P/ ~
- /* 接收Identifier */
8 i0 f5 f' p" H4 T - if (pRxHeader->IdType == FDCAN_STANDARD_ID) /* Standard ID element */- W. N8 c2 Z9 L4 v& N
- {# t7 R! k6 G' _0 E* K' a
- pRxHeader->Identifier = ((*RxAddress & FDCAN_ELEMENT_MASK_STDID) >> 18);7 O+ S1 v H# V; o! w! ?/ H0 ^
- }
( G5 K; i E9 y3 @. P - else /* Extended ID element */1 G7 @! i) u& q
- {1 m9 E( W5 ~* v
- pRxHeader->Identifier = (*RxAddress & FDCAN_ELEMENT_MASK_EXTID); L* v8 g8 m# k
- }5 J4 P3 } G% Q" Q, V1 k
- 7 H+ g8 F) }' L0 h+ o
- /* 接收RxFrameType */
5 n7 u5 d7 X: I: D$ I V - pRxHeader->RxFrameType = (*RxAddress & FDCAN_ELEMENT_MASK_RTR);
: K3 f/ E. W! ?5 A) ^2 X1 w& b - & e8 U: m$ n# ~, Q* Y/ h
- /* 接收ErrorStateIndicator */
: y3 n7 A$ v9 Q% N3 W9 ^ - pRxHeader->ErrorStateIndicator = (*RxAddress & FDCAN_ELEMENT_MASK_ESI);: G+ g8 a9 r* z+ ]5 R+ c
- 5 s. ? F9 f* @7 b
- /* Increment RxAddress pointer to second word of Rx FIFO element */
& c5 d6 m; M4 m9 I5 g - RxAddress++;
H7 u4 C! z% f1 B% V, M6 m( {+ ` - ! ?5 K, q$ i- S! A, n9 }4 p, U" m" o
- /* 接收RxTimestamp */
$ I! P4 i" X& g1 }% I1 x# ? - pRxHeader->RxTimestamp = (*RxAddress & FDCAN_ELEMENT_MASK_TS);
" B% X: ?; n: _4 \3 D - $ N8 T4 q8 ^2 i9 d9 o
- /* 接收DataLength */* b( c# J k& E2 v ?* i7 ]
- pRxHeader->DataLength = (*RxAddress & FDCAN_ELEMENT_MASK_DLC);
9 \- u, S. L/ w" d6 P - 1 S0 A1 O; ~1 ?+ k' X
- /* 接收BitRateSwitch */
& D6 ^, M' i* p - pRxHeader->BitRateSwitch = (*RxAddress & FDCAN_ELEMENT_MASK_BRS);6 p( s) i; u8 B/ Q. ^
- + L, `; I+ x+ `3 O" K" o! v
- /* 接收FDFormat *// A! u+ d8 f- S4 w, }0 N( k3 U
- pRxHeader->FDFormat = (*RxAddress & FDCAN_ELEMENT_MASK_FDF);3 X2 ?8 n# y* h( i6 `
: Z8 ~7 c( O) m" z& P- /* 接收FilterIndex */
2 U5 [( {8 v1 r g! z& f - pRxHeader->FilterIndex = ((*RxAddress & FDCAN_ELEMENT_MASK_FIDX) >> 24);- i" m# }6 I& {, }3 V$ w8 G9 A; E3 ^5 ~
N. i* F3 j. v, I* {/ e- /* 接收NonMatchingFrame */
- K" T' [& W! z m8 | - pRxHeader->IsFilterMatchingFrame = ((*RxAddress & FDCAN_ELEMENT_MASK_ANMF) >> 31);/ f% {) S/ v7 [( x- z
- ; X8 z' W* a$ i( K
- /* 增加地址,指向Rx FIFO element的payload */' R+ O1 }$ [% _4 i& v9 g
- RxAddress++;, e) q6 O3 @0 e1 N- Q0 d& Y$ x- }
- % S4 m9 N" I: {3 E& k6 d) R( A
- /* 接收 Rx payload */
- m6 ~. p0 d! \* ]' W5 p0 B - pData = (uint8_t *)RxAddress;4 K' h0 p5 p, q5 K5 M8 y
- for (ByteCounter = 0; ByteCounter < DLCtoBytes[pRxHeader->DataLength >> 16]; ByteCounter++)
1 f- F3 p$ L4 g - {
2 n5 c6 D2 j4 F - pRxData[ByteCounter] = pData[ByteCounter];* L! k8 ]; C4 u1 J( ^/ M' G
- }
- I! W3 i# }) A5 w, y+ G
; @7 j+ @ S T8 M# }0 C- if (RxLocation == FDCAN_RX_FIFO0) /* Rx element is assigned to the Rx FIFO 0 */
: `$ R9 q0 M7 E6 A+ z4 d - {
' g+ \9 M3 e! o5 B/ l) n - /* 确认Rx FIFO 0先进的数据已经读出 */# y9 _0 g! k# n7 `
- hfdcan->Instance->RXF0A = GetIndex;
1 e8 |" L0 d; p2 F9 A- o) q4 L - }( Y! `1 t. }3 V8 a8 q
- else if (RxLocation == FDCAN_RX_FIFO1) /* Rx element is assigned to the Rx FIFO 1 */. Q+ \6 G$ {# Y
- {/ k5 f, K P# ~3 G. ~0 B) l" A6 d
- /* 确认Rx FIFO 1先进的数据已经读出 */
- ^1 B# Y* T5 P6 i* v - hfdcan->Instance->RXF1A = GetIndex;
" I7 H& j9 u' b* U - } w& D4 @8 K5 e6 u/ [+ T4 Q9 r4 o
- else /* Rx element is assigned to a dedicated Rx buffer */7 k4 C) |6 M4 K/ i! R% I
- {
1 e. a6 B/ w0 B3 k G2 G6 S' B( b. j - /* 清除当前Rx buffer的新数据标志 */" R- u9 ?7 T d# @
- if (RxLocation < FDCAN_RX_BUFFER32)" N% l( A# [4 a- v
- {
N, e' g4 d* _' D2 r) t8 A- ?9 [ - hfdcan->Instance->NDAT1 = ((uint32_t)1 << RxLocation);) s; y# {1 s" N6 E! y6 M* k
- }
4 A$ ?. f3 A" x5 ^8 p2 S% }. x - else /* FDCAN_RX_BUFFER32 <= RxLocation <= FDCAN_RX_BUFFER63 */
0 Q1 ]4 ~+ k9 c - {
( |9 n* V( P/ f G' [; j - hfdcan->Instance->NDAT2 = ((uint32_t)1 << (RxLocation & 0x1FU));
8 v' b9 @' T1 f. G, l - }! P4 o: ^& N1 v0 b
- }7 u A& s* @/ {7 C* x
: k u4 C0 B y/ r- /* 返回状态 */- F9 j6 ^& G% K& |& k) ?
- return HAL_OK;
% a" L' e# F/ o& q1 U5 S - }
/ M9 N& s9 v+ M - else
5 ^0 i5 N ?- K4 x* O7 ^7 N, F - {
* e/ ^2 E: C: g2 B - /* 更新错误码 */
/ X" ~& d4 x9 B2 x4 b - hfdcan->ErrorCode |= HAL_FDCAN_ERROR_NOT_STARTED;& y( t4 I% Z( H* P) d
1 ?" ^% }- A5 `3 X( Y3 l1 _- return HAL_ERROR;5 s; r$ S% a6 n: e2 `
- }/ t$ K" b9 ]3 h) C5 v: p3 z
- }
复制代码
O3 }9 s1 z" _* i, r函数描述:
$ X9 m1 L I8 m* P' r* F* N) t2 E% |- F2 Z* A
此函数主要用于获取接收到的数据。, E# S) z3 n; ]0 R
" ~6 S) Z4 m! ~$ [
函数参数:8 ?+ y& F& }( k" g
+ B1 T n4 G1 ~; E( `
第1个参数是FDCAN_HandleTypeDef类型结构体指针变量。3 l- c! f. Y2 D. ]& e# t- F6 e
第2个参数是读取位置,支持如下几种参数:
6 ?' X- {+ g) ^( f; X- #define FDCAN_RX_FIFO0 ((uint32_t)0x00000040U) /*!< Get received message from Rx FIFO 0 */
2 w' H3 X) _: |$ Z) \ - #define FDCAN_RX_FIFO1 ((uint32_t)0x00000041U) /*!< Get received message from Rx FIFO 1 */
% `8 I8 i5 U7 A! m0 l& Q - #define FDCAN_RX_BUFFER0 ((uint32_t)0x00000000U) /*!< Get received message from Rx Buffer 0 */
% ^5 C3 y8 I' a' \. S& B$ V - #define FDCAN_RX_BUFFER1 ((uint32_t)0x00000001U) /*!< Get received message from Rx Buffer 1 */% Y1 u! R. c( s
- #define FDCAN_RX_BUFFER2 ((uint32_t)0x00000002U) /*!< Get received message from Rx Buffer 2 */
- A" g: D1 f- ?) Z5 x - #define FDCAN_RX_BUFFER3 ((uint32_t)0x00000003U) /*!< Get received message from Rx Buffer 3 */
* q5 J e) V% u8 c0 P/ w - #define FDCAN_RX_BUFFER4 ((uint32_t)0x00000004U) /*!< Get received message from Rx Buffer 4 */0 E- Y# R8 q0 F5 y
- #define FDCAN_RX_BUFFER5 ((uint32_t)0x00000005U) /*!< Get received message from Rx Buffer 5 */
5 B9 m! O5 s; r5 C - #define FDCAN_RX_BUFFER6 ((uint32_t)0x00000006U) /*!< Get received message from Rx Buffer 6 */
( k4 i% r3 {/ J - #define FDCAN_RX_BUFFER7 ((uint32_t)0x00000007U) /*!< Get received message from Rx Buffer 7 */
6 l$ u8 ]; I9 n. f- u - #define FDCAN_RX_BUFFER8 ((uint32_t)0x00000008U) /*!< Get received message from Rx Buffer 8 */
" O- C5 Q% F1 ?" q9 v - #define FDCAN_RX_BUFFER9 ((uint32_t)0x00000009U) /*!< Get received message from Rx Buffer 9 */
Y0 @) `' `9 s" z, b# S6 | - #define FDCAN_RX_BUFFER10 ((uint32_t)0x0000000AU) /*!< Get received message from Rx Buffer 10 */$ D: `7 p4 n) }3 W
- #define FDCAN_RX_BUFFER11 ((uint32_t)0x0000000BU) /*!< Get received message from Rx Buffer 11 */6 X2 }: i. j& Z B; A
- #define FDCAN_RX_BUFFER12 ((uint32_t)0x0000000CU) /*!< Get received message from Rx Buffer 12 */- p7 }9 N9 |# n( b. n9 s, d
- #define FDCAN_RX_BUFFER13 ((uint32_t)0x0000000DU) /*!< Get received message from Rx Buffer 13 */1 n. p! m# O" r9 j, u
- #define FDCAN_RX_BUFFER14 ((uint32_t)0x0000000EU) /*!< Get received message from Rx Buffer 14 */. y1 p( `4 U/ C8 E E
- #define FDCAN_RX_BUFFER15 ((uint32_t)0x0000000FU) /*!< Get received message from Rx Buffer 15 */) {: R6 F$ q% V: Z1 L
- #define FDCAN_RX_BUFFER16 ((uint32_t)0x00000010U) /*!< Get received message from Rx Buffer 16 */0 {2 O/ {. S: c. L$ N; o
- #define FDCAN_RX_BUFFER17 ((uint32_t)0x00000011U) /*!< Get received message from Rx Buffer 17 */
& z9 x6 d9 I: u! k6 ? - #define FDCAN_RX_BUFFER18 ((uint32_t)0x00000012U) /*!< Get received message from Rx Buffer 18 */ e4 D% D3 I6 J, K' X8 P/ [9 b9 n
- #define FDCAN_RX_BUFFER19 ((uint32_t)0x00000013U) /*!< Get received message from Rx Buffer 19 */$ C* I+ @# V5 Y! e: P# ]/ k
- #define FDCAN_RX_BUFFER20 ((uint32_t)0x00000014U) /*!< Get received message from Rx Buffer 20 */$ m7 M5 Q' e- a
- #define FDCAN_RX_BUFFER21 ((uint32_t)0x00000015U) /*!< Get received message from Rx Buffer 21 */
9 e" T5 J7 `! Z; [3 Y4 p" o - #define FDCAN_RX_BUFFER22 ((uint32_t)0x00000016U) /*!< Get received message from Rx Buffer 22 *// a z* P! I& k
- #define FDCAN_RX_BUFFER23 ((uint32_t)0x00000017U) /*!< Get received message from Rx Buffer 23 */
9 j$ B( T) H7 p2 k0 s2 {) b# B - #define FDCAN_RX_BUFFER24 ((uint32_t)0x00000018U) /*!< Get received message from Rx Buffer 24 */
2 L2 u9 H) `2 Q8 [' h - #define FDCAN_RX_BUFFER25 ((uint32_t)0x00000019U) /*!< Get received message from Rx Buffer 25 */- o! L+ M3 E6 s5 o8 U3 }" z
- #define FDCAN_RX_BUFFER26 ((uint32_t)0x0000001AU) /*!< Get received message from Rx Buffer 26 */
+ `7 M/ c# @5 o - #define FDCAN_RX_BUFFER27 ((uint32_t)0x0000001BU) /*!< Get received message from Rx Buffer 27 */
" ?& r {7 h, J, \ - #define FDCAN_RX_BUFFER28 ((uint32_t)0x0000001CU) /*!< Get received message from Rx Buffer 28 */
, o4 b, A# [" H7 s. F8 j+ w - #define FDCAN_RX_BUFFER29 ((uint32_t)0x0000001DU) /*!< Get received message from Rx Buffer 29 */4 A- ?7 G; |; T
- #define FDCAN_RX_BUFFER30 ((uint32_t)0x0000001EU) /*!< Get received message from Rx Buffer 30 */
6 T" a; E' `# j! \+ \, P - #define FDCAN_RX_BUFFER31 ((uint32_t)0x0000001FU) /*!< Get received message from Rx Buffer 31 */; W) ?) Z( e' B! K& m
- #define FDCAN_RX_BUFFER32 ((uint32_t)0x00000020U) /*!< Get received message from Rx Buffer 32 */
1 I% \# H0 V5 `: i- U - #define FDCAN_RX_BUFFER33 ((uint32_t)0x00000021U) /*!< Get received message from Rx Buffer 33 */3 [# l0 v# i8 K1 u$ t+ J7 O
- #define FDCAN_RX_BUFFER34 ((uint32_t)0x00000022U) /*!< Get received message from Rx Buffer 34 */
. m0 e$ V' I' f" G# l - #define FDCAN_RX_BUFFER35 ((uint32_t)0x00000023U) /*!< Get received message from Rx Buffer 35 */: H8 z7 [, Z$ e6 I( G) a' m+ q4 h
- #define FDCAN_RX_BUFFER36 ((uint32_t)0x00000024U) /*!< Get received message from Rx Buffer 36 */. _0 O0 f+ f; R; a1 d+ W
- #define FDCAN_RX_BUFFER37 ((uint32_t)0x00000025U) /*!< Get received message from Rx Buffer 37 */
& f/ r, m% @" F7 s2 [ - #define FDCAN_RX_BUFFER38 ((uint32_t)0x00000026U) /*!< Get received message from Rx Buffer 38 */: v4 a9 `- k: _2 L- \9 X
- #define FDCAN_RX_BUFFER39 ((uint32_t)0x00000027U) /*!< Get received message from Rx Buffer 39 */0 P: r5 q0 E) h- e8 w0 `! ]- }. N5 j
- #define FDCAN_RX_BUFFER40 ((uint32_t)0x00000028U) /*!< Get received message from Rx Buffer 40 */6 L) y+ i# w% y' G
- #define FDCAN_RX_BUFFER41 ((uint32_t)0x00000029U) /*!< Get received message from Rx Buffer 41 */
4 m# |. X5 ~6 z, N/ o2 R4 s5 ]% Y9 y - #define FDCAN_RX_BUFFER42 ((uint32_t)0x0000002AU) /*!< Get received message from Rx Buffer 42 */8 ^, X7 T+ @0 o: I5 m; ]
- #define FDCAN_RX_BUFFER43 ((uint32_t)0x0000002BU) /*!< Get received message from Rx Buffer 43 */
. ]/ U0 `; O/ j# P1 W - #define FDCAN_RX_BUFFER44 ((uint32_t)0x0000002CU) /*!< Get received message from Rx Buffer 44 */2 _, B2 c: L6 U! P
- #define FDCAN_RX_BUFFER45 ((uint32_t)0x0000002DU) /*!< Get received message from Rx Buffer 45 */
4 |4 q" l. m2 z* S- \# n6 a - #define FDCAN_RX_BUFFER46 ((uint32_t)0x0000002EU) /*!< Get received message from Rx Buffer 46 */
6 \3 [( C4 f; J' } - #define FDCAN_RX_BUFFER47 ((uint32_t)0x0000002FU) /*!< Get received message from Rx Buffer 47 */2 \) {/ Q& P% k
- #define FDCAN_RX_BUFFER48 ((uint32_t)0x00000030U) /*!< Get received message from Rx Buffer 48 */& O, a- X5 D* s& g1 K5 D/ s' Z. {
- #define FDCAN_RX_BUFFER49 ((uint32_t)0x00000031U) /*!< Get received message from Rx Buffer 49 */8 F9 A/ E% F0 O. B1 i1 b, K& [
- #define FDCAN_RX_BUFFER50 ((uint32_t)0x00000032U) /*!< Get received message from Rx Buffer 50 */) R8 z' `4 L) |2 H5 }4 ?, d
- #define FDCAN_RX_BUFFER51 ((uint32_t)0x00000033U) /*!< Get received message from Rx Buffer 51 */
& q1 ]! ?2 ^( i! u2 Q - #define FDCAN_RX_BUFFER52 ((uint32_t)0x00000034U) /*!< Get received message from Rx Buffer 52 */
$ B* K8 L" U4 K( a - #define FDCAN_RX_BUFFER53 ((uint32_t)0x00000035U) /*!< Get received message from Rx Buffer 53 */% h* M5 x8 D& O% w' D/ s1 C% X5 ?
- #define FDCAN_RX_BUFFER54 ((uint32_t)0x00000036U) /*!< Get received message from Rx Buffer 54 */
! m# W+ t/ y, |. G* a0 L$ d3 C - #define FDCAN_RX_BUFFER55 ((uint32_t)0x00000037U) /*!< Get received message from Rx Buffer 55 */
" `0 U7 ^ ^1 ~. r) x0 E - #define FDCAN_RX_BUFFER56 ((uint32_t)0x00000038U) /*!< Get received message from Rx Buffer 56 */4 H) F4 E [$ s4 g" M2 k$ R1 {3 D
- #define FDCAN_RX_BUFFER57 ((uint32_t)0x00000039U) /*!< Get received message from Rx Buffer 57 */- y# O9 o# J2 p# w% [
- #define FDCAN_RX_BUFFER58 ((uint32_t)0x0000003AU) /*!< Get received message from Rx Buffer 58 */* N8 q2 F1 E+ l' D5 ]" u4 b
- #define FDCAN_RX_BUFFER59 ((uint32_t)0x0000003BU) /*!< Get received message from Rx Buffer 59 */5 A3 n% S x* b4 k, M! S2 e/ \2 u3 f
- #define FDCAN_RX_BUFFER60 ((uint32_t)0x0000003CU) /*!< Get received message from Rx Buffer 60 */
0 Y7 C# n5 @8 g' j' T5 [# S. t q8 V - #define FDCAN_RX_BUFFER61 ((uint32_t)0x0000003DU) /*!< Get received message from Rx Buffer 61 */9 R$ I) h. S2 ^+ W2 q% k! n! C# |" _
- #define FDCAN_RX_BUFFER62 ((uint32_t)0x0000003EU) /*!< Get received message from Rx Buffer 62 */) s& d' A x$ r* _. Z u0 J
- #define FDCAN_RX_BUFFER63 ((uint32_t)0x0000003FU) /*!< Get received message from Rx Buffer 63 */
复制代码
; b8 `8 \+ b% i# A: X/ _. v 第3个参数是FDCAN_RxHeaderTypeDef类型结构体变量,主要用于消息接收。% l) E, N2 V# w) n, F" Q9 k
第4个参数是数据接收缓冲地址。
5 Y" a) {1 _9 H7 @, V 返回值,返回HAL_TIMEOUT表示超时,HAL_ERROR表示参数错误,HAL_OK表示发送成功,HAL_BUSY表示忙,正在使用中。
7 ?: O w* Y" u. _9 ]8 p2 [( f. j使用举例:2 {) c" u( N- J3 B0 Q+ Z$ K7 a
& [) z2 v: i) D" e) h. k1 V
- /*
5 c+ K, h% Q, f! T0 E - ********************************************************************************************************* L0 w9 |/ a8 @& p
- * 函 数 名: HAL_FDCAN_RxFifo0Callback) b9 i& H1 W% o, x$ f
- * 功能说明: CAN中断服务程序-回调函数
/ a) v' Q3 o( j6 V, E4 m4 ~ - * 形 参: hfdcan
$ d9 K4 `# c+ Y1 y% t - * 返 回 值: 无
" {1 \: h3 |) {9 l( ` - *********************************************************************************************************
5 ?1 i: Q3 _& l7 A - */9 P! |( @+ i; G( g; w
- void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
# m/ U' r0 R) K3 j) K1 e" p4 A/ k - {% J* g& N; e+ x* x" E% b$ N
- if (hfdcan == &hfdcan1)
& Z: H9 t j& l% t+ L$ f& ]. G - {
. z( e" T% K, Y% I$ Q9 V9 G. w+ x - if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_WATERMARK) != RESET)
5 x( p" Z: C! U8 ^9 n4 y - {
. F$ ?4 }7 A4 F# U& K+ D7 } - /* 从RX FIFO0读取数据 */
" ^ @; u, q- F - HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &g_Can1RxHeader, g_Can1RxData);
- Z g' Z! n: m4 m7 E" ]
$ b* `# w% P8 q8 |1 M6 i+ f" U- /* 激活Rx FIFO0 watermark notification */: K: y5 H- D( n- L- ]8 ?3 z2 c
- HAL_FDCAN_ActivateNotification(hfdcan, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
7 F# ], d. f+ e7 O" F+ g - 6 L* d. r: I8 p3 E
- if (g_Can1RxHeader.Identifier == 0x111 && g_Can1RxHeader.IdType == FDCAN_STANDARD_ID)( j% E K' _6 C( w# N- o" X
- {
" A* r- @6 N9 U" V - bsp_PutMsg(MSG_CAN1_RX, 0); /* 发消息收到数据包,结果在g_Can1RxHeader, g_Can1RxData */. R( C7 X, c/ z! x2 F, N2 }8 u
- }, G% Z; a6 G/ P& ~' f
- }
, o7 x: ?4 s; P5 b - }+ j$ H" c/ @0 c$ B6 t' }; a+ N+ H
- }
复制代码 1 G; |+ h* B, v: G; N, ?/ M
91.5 总结' |* P: n5 P4 e" T/ k0 y$ N8 y; U
本章节就为大家讲解这么多,更多FDCAN知识可以看本教程的第90章。9 @/ q/ y. j: \" q) a9 y0 }/ E; k
0 s7 @9 B' I: ~4 l
1 Q: ^! s+ A0 A! `: n7 M7 g( S
|