1 前言
6 |* c" s; B, j: I5 j, j5 Y本文将针对客户在使用 Cube 库时 CAN2 不能产生接收中断进行分析。 O7 z6 z8 l6 m- W
2 问题描述! y; K$ |& E0 ]+ m
客户使用的是 STM32F105,同时用到了 CAN1 与 CAN2,使用 cube 库,但有个奇怪的现象,CAN1能正常工作,CAN2 却无法正常产生接收中断,CAN1 与 CAN2 的代码几乎没有什么差别。3 I3 H4 z$ G% U4 z
& _$ B: `' M- F
3 重现问题6 \' i! B; x; U+ K
实验使用 STM3210C-EVAL 评估板,这款板子有同时将 CAN1 和 CAN2 引出,此板上的 MCU 为STM32F107VC,与客户所用到的 STM32F105 只多了个 Ethernet 外设,其他无差别,正适合用来验证此问题。9 g1 }6 [7 v- \. [
" X0 C4 E$ x. J( {3.1 工程制作
& P( e0 w* K( \7 q/ W0 _使用 cubemx 生成工程,cubemx 得配置如下图:9 W- q! r' B$ p: G
4 J& y4 C/ p# r, f0 Z7 \
+ F) p! ?3 [5 {0 ~0 F2 \1 n: d+ V i
8 v6 I8 y+ }- h! u
" l. ^) {4 x- `. }' G1 s& {
) Z+ n. `# e6 \# o1 Q) O. i
0 K8 k) R5 I& T' P/ [: [$ T2 u" M3 |6 M% s2 a1 U; b3 u
配置波特率为 500K,自动离线使能。
) M7 {8 m9 a& D点击生产代码,在 main 函数内的/* USER CODE BEGIN 2 */与/* USER CODE END 2 */添加:+ u" H- I9 K) H4 S
- /* USER CODE BEGIN 2 */
k1 A$ ]( C" V" h- Y - sFilterConfig.FilterNumber = 0;1 F$ ^- f" k* }* ]
- sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
( { [, Q3 a( S- K* ]& _ v! z: @ - sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;- p/ t& i! t7 D) q6 T/ p
- sFilterConfig.FilterIdHigh = 0x0000;" ?! Y: u/ [- m- z
- sFilterConfig.FilterIdLow = 0x0000;
' D; l( b2 f& l: s/ [ - sFilterConfig.FilterMaskIdHigh = 0x0000;3 Z" Q3 q4 v' Z8 ^3 f/ L
- sFilterConfig.FilterMaskIdLow = 0x0000;0 V+ e, H1 f) Y% W1 [# f4 a
- sFilterConfig.FilterFIFOAssignment = 0;
9 G' h# i! ?5 O* v3 O6 G - sFilterConfig.FilterActivation = ENABLE;
y8 t1 d/ z7 ~2 X& m6 o - sFilterConfig.BankNumber = 14;
6 {& M% b; B: J/ E% M& { [: v
( v8 p D- d2 n+ [4 e+ ?+ A: P5 j- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //为 CAN1 配置过滤器- ?) }0 F4 c; _* E- S
- {9 ]3 E2 N5 i6 [0 F
- /* Filter configuration Error */
" n3 d6 V$ n9 Z a+ c - Error_Handler();
) v1 e c( T( c: J - }
& Z' t" ?" o" z: c" g - sFilterConfig.FilterNumber = 14;3 _( B2 ]; G$ e0 c3 N
- sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
N: v: N" a+ u8 @ - sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
/ g: }! N* ?4 N" ? - sFilterConfig.FilterIdHigh = 0x0000;3 l7 K L: n Z) q3 \
- sFilterConfig.FilterIdLow = 0x0000;
* D/ e: D/ ^/ w. ]- ~ - sFilterConfig.FilterMaskIdHigh = 0x0000;
) Q0 U; L ?' l" U0 J. e6 a4 X - sFilterConfig.FilterMaskIdLow = 0x0000;
j+ k" B0 h, A! Z( U5 g - sFilterConfig.FilterFIFOAssignment = 0;
4 F2 g; o9 i# { C - sFilterConfig.FilterActivation = ENABLE;
+ G, h+ I" L. B - sFilterConfig.BankNumber = 14;0 V, z: N; A1 K* v% e- j) C$ T
- if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) //为 CAN2 配置过滤器,请留意这: d0 ~: g; A. G5 W2 R
- 行代码
9 G% G) C) a( Q5 W4 x - {0 |( D9 K1 ?" R
- /* Filter configuration Error */
" I* S9 l' ~- C' F7 H3 W- ~9 j - Error_Handler(); `$ H$ A9 X9 O& f" E
- }2 O& V! [. j: D7 S+ @4 ^9 q
- hcan1.pTxMsg = &TxMessage1;! w6 y$ t: Z; K, z7 M1 n
- hcan1.pRxMsg = &RxMessage1;9 E3 ^9 L- T) H0 K1 L
- hcan1.pTxMsg->StdId = 0x321;
. y4 J v7 X; ^! A( ?2 f+ P( q - hcan1.pTxMsg->ExtId = 0x01;
% {2 t7 q* `3 a - hcan1.pTxMsg->RTR = CAN_RTR_DATA;* c- M: u1 F& f: I2 A" t- E
- hcan1.pTxMsg->IDE = CAN_ID_STD;, f; {4 W& l& I: o' y K
- hcan1.pTxMsg->DLC = 8;4 }$ s4 \6 S* a2 }: {0 |% {/ A
- hcan1.pTxMsg->Data[0] =0x01;+ `! R _) U4 @8 c7 L# Q
- hcan1.pTxMsg->Data[1] =0x02;
4 c% C% C! f! k0 [+ s. F0 ^3 ` - hcan1.pTxMsg->Data[2] =0x03;
7 Z8 T7 e7 b: e' d4 ^/ I5 j0 M. g - hcan1.pTxMsg->Data[3] =0x04;
5 g& Z. @" v" C+ `' \6 [ - hcan1.pTxMsg->Data[4] =0x05;
$ W8 G: P1 s( N) T8 t - hcan1.pTxMsg->Data[5] =0x06;
; I! j O$ @" s$ J+ u9 k - hcan1.pTxMsg->Data[6] =0x07;
) X0 `* `% m. P+ Z9 I2 N; f - hcan1.pTxMsg->Data[7] =0x08;
- O' q4 M4 [0 v/ T" ]2 ? - hcan2.pTxMsg = &TxMessage2;
; f6 y* N1 D; N3 c! k) K - hcan2.pRxMsg = &RxMessage2;
9 N+ A$ H7 a5 c0 @0 i! z - hcan2.pTxMsg->StdId = 0x322;& P2 {) g8 i) u9 {: j& X
- hcan2.pTxMsg->ExtId = 0x01;4 F1 J$ V( v% r1 ?6 V0 w3 I. Z
- hcan2.pTxMsg->RTR = CAN_RTR_DATA;
2 G$ ^0 t6 F! ]( E - hcan2.pTxMsg->IDE = CAN_ID_STD;
0 M+ |# ]3 r0 f# M" B& M$ F' ` - hcan2.pTxMsg->DLC = 6;$ Q. m/ G0 E1 z# Q, d, H3 J; v, E
- hcan2.pTxMsg->Data[0] =0x01;
. l3 w2 u0 P$ Z" p5 M - hcan2.pTxMsg->Data[1] =0x02;
" l, L3 n+ _. L/ F! { - hcan2.pTxMsg->Data[2] =0x03;
" T- ^8 s2 t: Z) R - hcan2.pTxMsg->Data[3] =0x04;
7 H% }/ J& @' @4 r8 e - hcan2.pTxMsg->Data[4] =0x05;, k. _# J3 I* E' x5 W
- hcan2.pTxMsg->Data[5] =0x06;# i' K1 @2 _$ e# `# S( g: I
- hcan2.pTxMsg->Data[6] =0x07;: r/ m; Q% p$ A! s+ b$ W: h ^8 g. k
- hcan2.pTxMsg->Data[7] =0x08;
j; }: M% w, D# z8 u+ L - if (HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0) != HAL_OK) //CAN1 开始接收
; m3 ^8 w" ^" H+ e- o. t - {
' o; j- |% `& A - /* Reception Error */ x/ L, l& O$ @, u; D- b' l" [
- Error_Handler();
7 y4 M {& C' B. \- p - }
4 q4 }3 Y3 k x" @6 P4 } - if (HAL_CAN_Receive_IT(&hcan2, CAN_FIFO0) != HAL_OK)//CAN2 开始接收
' K: }7 P$ a, a7 b& a: P- B - {) X- l5 X* M# G6 D& u ~
- /* Reception Error */& w4 }- t$ s, s/ ?7 n" O1 r! ^- w
- Error_Handler();
% {1 r, D: b8 x' A6 D - }
7 [" ]* v* ~! \/ M4 h- s% D1 ^ - /* USER CODE END 2 */
复制代码 ' D( g0 ?5 Q' |, r
在 main 函数内的/* USER CODE BEGIN 3 */与/* USER CODE END 3 */添加:
8 Q# z' G: ~$ v- while (1)0 L: x8 ~6 s8 a( n$ s* G+ ^/ e0 r
- {# y9 v/ Y8 e% e8 r w
- /* USER CODE END WHILE */* o* m% K' [3 F. s
- /* USER CODE BEGIN 3 */1 Y$ s. G. \, y; e {5 T, X, g
- if (HAL_CAN_Transmit(&hcan1, 100) != HAL_OK) //CAN1 发送数据7 v7 m2 T' y" {3 A1 }9 {+ K
- {. H/ s7 C0 a7 K( Q1 s6 z, h
- /* Transmition Error */4 M( W5 p u9 I7 w
- //Error_Handler();3 K( X6 o' R5 h2 @4 K! f5 g2 s
- }
8 b% d% `' g J) Q - HAL_Delay(10);
" j( ?, r1 E" M2 f. f - if (HAL_CAN_Transmit(&hcan2, 100) != HAL_OK) //CAN2 发送数据; m8 P% H) n$ P
- {5 w3 b3 z8 i) r1 r' j" o
- /* Transmition Error */ J3 g. T' I+ g5 F) w# k
- //Error_Handler();2 L4 B5 ?) y" v% k0 _3 A& b- s
- }: l) L, h1 d0 D1 s( Y
- HAL_Delay(1000);8 N) s& E) r0 t- e7 q
- }5 w& C# c, {& f u; A( @7 _
- /* USER CODE END 3 */
复制代码
7 a9 g9 `! i1 M5 X% q# P0 o3.2 测试重现问题现象9 [! D$ J. ` K: C
使用 ZLG 的 USBCAN-2E-U 盒子与 STM3210C-EVAL 评估板以及 PC 连接进行测试:6 N8 }7 K1 ~3 k8 x' b% a
- o# t) U; k. I& [# y& ^+ m; x
0 n3 ?8 f5 T; l2 p5 G3 p
) V, P o% t8 j4 ^% i# Q
在调试下,在 PC 端软件 CANTest 下都能看到 CAN1 与 CAN2 发送的数据,这说明连接上是完全没有问题的,但是,在调试 CAN 接收时,在 CAN2 的接收中断处设置断点,使用 PC 端软件 CAN_Test 向CAN2 发送数据发现并不能产生中断,而对比 CAN1 时,发现 CAN1 却可以产生接收中断。
4 k$ v6 a$ y4 H7 Z$ [8 U6 s N Z' t# _
4 问题分析
q( m) j* S: O7 q% S0 P3 I仔细对比 CAN1 与 CAN2 的代码,发现并没有什么不同之处。仔细思考一下,由于 CAN 接收中断是与CAN 过滤器有关,因此,着重对比 CAN1 与 CAN2 设置过滤器时的代码差异。
+ `" n* f% C; b+ m6 f" F' |6 pCAN1 设置过滤器代码如下:
$ J: B. z' E. b- d- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
0 ^9 p3 n4 r8 ?, W U - {
2 z1 z2 V0 _7 h$ M, u8 m - /* Filter configuration Error */ \3 }- s& M4 N
- Error_Handler();# w, \2 Q6 q- N% u: V2 V# M
- }
复制代码
) z8 o4 F/ L2 }, ~而 CAN1 设置过滤器代码如下:
7 ?3 ^( Q h# D- o" l- if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
) W" u% H9 Q+ p, H1 P - {
& u/ h& I: y7 _6 @ - /* Filter configuration Error */! k T! Z& k2 L: S1 a3 a# j
- Error_Handler();2 _ E0 {! ]( c0 I% z2 F' I) t
- }
复制代码 , Z0 m( x) _% v& }5 M+ e
看来好像没有什么不妥的地方,基本差不多,只不过过调用 HAL_CAN_ConfigFilter 函数配置过滤器传入的第一个参数一个是&hcan1,一个是&hcan2,; O: @/ X8 E: B
查看参考手册,对比 CAN1 与 CAN2 的差别:
X J+ C# Y" O! Y6 E+ C0 M( e在参考手册的 24.4 节中对 CAN 的功能介绍时有下面一段话:4 F# k; f% \5 f$ ^" c, _/ x5 q
Q0 c7 _5 u( W
$ P6 Q- |7 @, L
: o$ K0 Z0 N: K/ P; b1 O上面一段话的意思是说,CAN1 是作为主,而 CAN2 做为从,做为从的 CAN2 不能直接访问这个专用的 512bytes 的 SRAM,而只能通过作为主的 CAN1 来间接访问,且 CAN1 与 CAN2 是共享这个专用的 512bytes 的 SRAM。打开图 222,如下所示:5 E& @% V6 H, f. h6 ?
. ]" I: i. C" Z' k, `4 p6 m; p
9 L# L: F5 ?! g/ m# k
3 g- k" k* t! ?如上图可知,CAN1 与 CAN2 共用过滤器(Acceptance Filters),CAN2 是通过 CAN1 的 Memory Access Controler 来访问过滤器的。过滤器共有 28 个,占用 512 专用字节其中一部分。/ Q! t! O" T2 U7 e9 q
接着在数据手册中查下内存映射,如下图所示:: f. L/ L$ H) B2 ]! J9 I4 x. B
- x7 B9 R' Y* l" K
) G7 \% Y8 Q; M2 g1 f( x, v; r" c, P
可知,CAN1 的地址为:
6 Z' {* q# R0 u( ~, h& k/ B# X" I- j3 [
k/ G/ B/ w1 k
" s$ ^; b0 U6 V. i* i然后查看 bxCAN 的寄存器,在参考手册的 24.9.5 节中,发现有这么一段话:7 r/ r) C9 v. D v( ~. e. v
3 i5 Q4 |+ D: t6 e" a
& Q$ C8 j2 f+ f' I4 e; s' B0 S
' s* V: @: t5 O6 w# I' O i) m也就是说,从偏移地址 0x200 开始到 0x31C 之间的寄存器只存在于 CAN1 中,在 CAN2 中并不存在,那么这些都是些什么寄存器呢?8 U% K% L' v! `6 P3 G t. w
查看参考手册的 CAN 寄存器映射表,如下内容所示:% {: q; f1 y! M% G( n2 }6 E: W
/ `( ?8 E2 @8 n: E6 j0 ^# u. {& v/ U
4 T9 g5 y9 {7 `9 R% g) a
) O) @; ]: r& b) E4 E! X
* d6 H7 L3 l5 U$ \5 q% X
+ e: R1 e `; `+ I& n6 |2 X可知这些都是 CAN 过滤器相关的寄存器,可知离 CAN1 起始地址 0x4000 6400 偏移 0x200~0x320 之间是 CAN 过滤器寄存器的地址,且这些过滤器由 CAN1 和 CAN2 共享,且最重要的一点信息是,离CAN2 起始地址 0x4000 6800 偏移 0x200~0x320 之间是没有寄存器的,这个非常重要!
9 I- i5 l. {( f6 e4 ?2 k- Q4 b# I2 `再回过头来看 CAN2 过滤器的设置代码:+ _! B, q! o9 t- x; A* t7 z
- if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)! q; h0 ]1 C' I4 n5 t
- {; H( k" G/ M- C0 Y
- /* Filter configuration Error */
2 c+ o+ S i9 l2 { - Error_Handler();
8 b6 `2 ~& ?5 [9 o& g+ a+ h7 |6 ]! Q - }
复制代码
+ V' q9 d* D9 R& x( h# b) v这几行设置过滤器的代码到底是将参数设置到 CAN1 偏移 0x200~0x320 之间还是 CAN2 偏移的0x200~0x320 之间?这个问题要弄清楚,非常重要的!继续看 HAL_CAN_ConfigFilter 函数内:
$ k5 I: g" F' {8 M- if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)* c! l4 D: d/ e( I7 T9 z6 B: F. @
- {
2 y, Y) I7 o( M- G$ P% Q0 R8 i - /* 32-bit scale for the filter */
2 y4 v% n9 h2 t) M$ z0 } m - SET_BIT(hcan->Instance->FS1R, filternbrbitpos);1 T' J. Y; o8 ~; j9 c6 C, q
- /* 32-bit identifier or First 32-bit identifier */
% k6 q+ V2 P, Q8 U3 p - hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =! T P2 [- e1 _
- ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) FilterIdLow);( {6 c# d9 p: i; q; U
- /* 32-bit mask or Second 32-bit identifier */
6 V5 R! ^- R8 j& } - hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =1 ]+ z2 F/ g% W8 \% r) t! H& C7 J
- ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) FilterMaskIdLow);
( W. P& G! a3 o$ r5 B - }
复制代码
1 Y0 N3 d5 P6 [0 P) j8 {! G6 Z由上代码可知,设置的参数实际上是设置到传入的句柄 hcan 的示例 Instance 下的成员 FS1R,sFilterRegister[]中去了,查看这些成员的定义:! m( s+ X- @) l6 C n2 I
- typedef struct8 a. B; U6 d4 t- d' j& K
- {. ^" S$ ^4 H6 U' B* I
- __IO uint32_t MCR;
3 p8 S4 W% i2 ~. a0 D( i! H6 f H - __IO uint32_t MSR;' e, r- d' N$ }+ f5 I
- __IO uint32_t TSR;" l0 f! |1 P* k1 b1 C, ^+ R8 H& W
- __IO uint32_t RF0R;
+ S* ~6 U5 i5 @5 C" H7 D - __IO uint32_t RF1R;' J$ M! {/ O! [) M6 M* O/ O
- __IO uint32_t IER;
, v/ N6 x! O% F- Y, q3 @ - __IO uint32_t ESR;
/ c8 m1 y; @" f: E8 ^& g - __IO uint32_t BTR;
5 E1 ?9 U! i9 z3 S' h2 t- a - uint32_t RESERVED0[88];- \1 @" I1 a7 u, x$ H
- CAN_TxMailBox_TypeDef sTxMailBox[3];' e8 O, J$ c% q/ z) s n, E4 i; h4 `$ ]) p
- CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];
4 _! y; Y3 K: F4 `0 I - uint32_t RESERVED1[12];# }: r5 J4 s. A, Y) @& O( D
- __IO uint32_t FMR; //过滤器主寄存器
: ?' q: W' o+ i2 r! w2 ] e) W - __IO uint32_t FM1R; //过滤器模式寄存器
0 b# ^3 Z7 N& V- v9 t - uint32_t RESERVED2;* a7 H7 ]* \; C
- __IO uint32_t FS1R; //过滤器位宽寄存器
/ l" A5 t) `; Q1 m3 @1 h - uint32_t RESERVED3;
5 m2 M5 o$ U! _' d6 x1 } - __IO uint32_t FFA1R; //过滤器 FIFO 分配寄存器
+ k/ N' O2 Z5 k1 g - uint32_t RESERVED4;$ T: J' H) F3 n; j' }
- __IO uint32_t FA1R; //过滤器使能寄存器7 k# U; @1 [2 B/ B/ A" y0 E
- uint32_t RESERVED5[8];* o8 X( t. e; b, A1 t% b! y6 Y$ {5 i
- CAN_FilterRegister_TypeDef sFilterRegister[28]; //过滤器; Y' O; w/ f. c& ~, P# X/ b
- } CAN_TypeDef;
复制代码
: Y3 z$ G* D& n% D; ?! ~由以上代码可知,HAL_CAN_ConfigFilter 函数实际上就是对传入的 CAN 起始地址偏移 0x200~0x320之间的过滤器相关寄存器进行参数设置,但是,对于 CAN2 来说,实际并不存在这个这些寄存器,因此不会生效。这个可以在调试过程中查看 CAN2 寄存器值来验证,如下图:* U3 |$ j& ~/ A: c$ q
6 P; F; I6 U0 ~" ?; s, P
- e- @3 M% I4 V$ F8 r3 d4 a
3 {' s0 N0 r8 ?5 J$ r2 Y在运行过 HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig)之后,CAN2 相关的过滤器还是没有变化,进一步说明此函数对于 CAN2 来说是无效的。/ B- S" w$ r0 g+ [
那么要解决这个问题,该如何修改呢?很明显,通过 CAN1 来设置即可。CAN1 和 CAN2 共享过滤器,但设置过滤器时可以通过 CAN1 的偏移来访问过滤器,这么说来,也可以将这个理解为 CAN1 作为“主”的确切含义吧。/ b& ?) O; t8 o& n
修改后如下:# `- o N6 |$ ^7 X( `
- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //使用 CAN1 作为参数; b4 ^2 ]! i. \4 v( X4 U2 V! i
- {, {5 C# l) E. x- R$ p; e6 A7 M" D
- /* Filter configuration Error */ u( x# w( [9 s5 U8 M% Q& {/ P
- Error_Handler();
) |8 T8 x8 |$ E: x* ^ - }- D. J: U3 Z8 h0 U; J" t
- sFilterConfig.FilterNumber = 14;
' D9 `. ^6 h7 a - sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
0 B1 z* i/ o$ k0 f5 {9 N - sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
1 V- q. a) y# L5 ]2 o4 W5 C - sFilterConfig.FilterIdHigh = 0x0000;+ E1 T- a d/ n4 S( d
- sFilterConfig.FilterIdLow = 0x0000;3 [' \+ { i& s6 w. ^& `% e: c
- sFilterConfig.FilterMaskIdHigh = 0x0000;5 j: t" I& o/ j
- sFilterConfig.FilterMaskIdLow = 0x0000;$ a: K) Y. X @: v2 g
- sFilterConfig.FilterFIFOAssignment = 0;
: w( L9 T) \( H: j - sFilterConfig.FilterActivation = ENABLE;
4 }- S# ]+ b" o% T - sFilterConfig.BankNumber = 14;
: O9 t! F' |6 [ - if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //还是使用 CAN1 来作为参数
& j+ z& x( D8 V - {
* r! s4 x/ A9 s - /* Filter configuration Error */
) w2 [2 U3 r; a- ?" O! G9 i2 X - Error_Handler();
2 |5 `0 y" z0 P1 ~- k& C - }
复制代码
% [. o/ K& E- A在 CAN2 中断设置断点,使用 PC 端软件 CANTest 向 STM3210C-EVAL 评估板的 CAN2 通道发送数. q9 [3 ~' m/ w* x% e: D R& j. u
据进行测试验证:
: W+ P, V: Y8 T( j) ?/ |/ l
% |7 S/ U4 F0 f2 b* H7 ~
w9 R1 `/ @& n. p+ {8 t% Y
' { y( B( q% J% q6 a A如上图可见,CAN2 的接收中断已经可以正常捕获到了。
7 U! }+ g; y% `: r$ D0 N4 u6 q# b! K3 w# H9 ]9 [ t
5 横向扩展
3 {1 }& M% a/ ]6 C$ X2 r此问题是在使用 Cube 库下时发现的,那么标准库是否也会存在同样的问题?$ j9 Y0 I8 k, K4 F+ b* b
其实,在使用标准库下,在设置过滤器时,并不需要传入 CAN1 或 CAN2 的句柄,因此也就不会这这种问题,如下基于标准库的示例代码:+ H4 e2 z9 z6 l: F
- void CANFilter_Config(void)
$ b+ Q& m5 S' F. h0 x - {
" \; n* f6 m) c' B4 D9 b8 D - #ifdef __CAN1_USED__
8 J0 j2 O: Z K+ B! w( f - /* CAN filter init */
" u7 I# q8 P: E/ K. ]* f - CAN_FilterInitStructure.CAN_FilterNumber = 0;* X* [5 s3 z, i
- CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;7 I! X, u! G# U+ E! y2 l; U. Z. w
- CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
1 j1 o+ R3 b0 c - CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;! F: _+ k6 g2 w3 y+ V4 ]* c
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;7 a6 V" f' z4 s- t% X
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
2 G) s) G0 X5 M( y - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
J6 b& s6 C* }# L- Z2 N( Z% |& z; r( V - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
2 X$ r8 W& V" f' ] - CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;' `* |0 H! T+ y6 S5 l# T9 t
- CAN_FilterInit(&CAN_FilterInitStructure);7 B# G! J9 g2 o6 d
- #endif
2 E8 H& ^( Y9 | - #ifdef __CAN2_USED__; c- f. i8 _ M, c( {5 S5 k
- CAN_SlaveStartBank(14);- x' h8 G+ M3 s9 f
- /* CAN filter init */
& c) {+ V( t/ \7 D& n - CAN_FilterInitStructure.CAN_FilterNumber = 14;1 `. l8 A$ a$ @+ J# h3 f8 N
- CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;, h* l5 h( f; M& g6 Y
- CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
8 F B& s8 U' D3 _( q - CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;" q5 _6 }2 w) J
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;* ]( m+ D7 j* X. N. S6 |
- CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
7 O3 y& F) h: S' e& U: a2 n - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
3 w }( B! ~0 r* ^ - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
; U& @5 @0 P# l - CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;2 N/ `0 a% s& L! B
- CAN_FilterInit(&CAN_FilterInitStructure);# W, H X \, e; t$ Q2 z9 N% F
- #endif
" q- D% z$ _7 O; Y H2 h2 O: r - }
复制代码
3 i3 e" P/ ?' k在函数 CAN_FilterInit 中,内部自始至终操作的都是 CAN1,如下所示:
% v( u4 H3 q6 M: Y3 `/ N: b/ k- //…
3 x5 t; [; H7 A - if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)6 D# D" ]) v& V
- {
+ J' q4 \% r* A8 y - /* 32-bit scale for the filter */
- \+ u; s% i. M4 p2 y5 Q* N - CAN1->FS1R |= filter_number_bit_pos; //操作的是 CAN1 的偏移地址' [6 Q( d2 B$ c
- /* 32-bit identifier or First 32-bit identifier */' D* }6 b' ]3 M
- CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =* k' _3 J) D* l6 v! R
- ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) CAN_FilterIdLow);
; C1 f. B; Z8 k2 |5 w - /* 32-bit mask or Second 32-bit identifier */
; V3 w0 K5 U m. r, T5 S+ s - CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =. b) G j6 F6 A( I
- ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) CAN_FilterMaskIdLow);
0 h9 Q5 A! ~# c - }3 @" h; v/ E* c( w1 a, W
- //…
复制代码
0 k0 L% s m+ B0 N5 c因此,不会出现在 Cube 库下出现的问题。; k: a6 [9 x5 K$ A. ^
) j. d2 q; i/ ~, J$ H: Y1 i# n9 f6 总结& s& `: `- U( U
此文所描述的问题之会出现在使用 Cube 库的情况下,且基本覆盖包含双 CAN 的所有系列,在使用HAL 函数 HAL_CAN_ConfigFilter 配置过滤器时,将第一个参数固定指向 CAN1 的句柄就可以了。
( i: q+ s4 d' i# w
: h( L" ^9 N* T. d |