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