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