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