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