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