1 前言4 Y B% i- N; Y0 n/ W# K' z
本文将针对客户在使用 Cube 库时 CAN2 不能产生接收中断进行分析。
( S8 S3 z9 h- h' a! K- b$ @+ }* y2 问题描述
# Y8 l8 A3 N1 f# {# r! B0 {客户使用的是 STM32F105,同时用到了 CAN1 与 CAN2,使用 cube 库,但有个奇怪的现象,CAN1能正常工作,CAN2 却无法正常产生接收中断,CAN1 与 CAN2 的代码几乎没有什么差别。: w2 O: y- J5 Q/ g
3 x7 c" ` Z+ n1 |, v3 重现问题
# j& ]3 h8 B1 T4 {. V实验使用 STM3210C-EVAL 评估板,这款板子有同时将 CAN1 和 CAN2 引出,此板上的 MCU 为STM32F107VC,与客户所用到的 STM32F105 只多了个 Ethernet 外设,其他无差别,正适合用来验证此问题。3 L6 f0 X7 R' C$ a% r- z& P; ~+ g
# n& r$ }8 ~, x1 l3 P2 D3.1 工程制作( b* u: k. x6 e" J& _
使用 cubemx 生成工程,cubemx 得配置如下图:
~7 K+ R4 m5 `) g( Y- d
" T4 e. ?$ f" j( E4 g7 ]
; F( m* I$ R1 F$ m% H z2 g
8 j& t; b* {; Z% B& l
) t C @; @! ]( k
" x5 j; e% W K# v3 e
" k2 G/ ]: M5 Z2 \" P1 q6 l! E
- z5 @+ e6 ]0 M: c s/ i配置波特率为 500K,自动离线使能。( n' P l/ o% u; a
点击生产代码,在 main 函数内的/* USER CODE BEGIN 2 */与/* USER CODE END 2 */添加:& m+ ` Y) E5 R, U6 w( h/ ?
- /* USER CODE BEGIN 2 */
0 O P1 U8 u+ E) a& _. i0 d - sFilterConfig.FilterNumber = 0;
; L7 J" C: u8 ` j# }: @8 q - sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
9 E9 d9 |- E( R. [2 W) V - sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;4 w1 w0 u9 Z0 X; N
- sFilterConfig.FilterIdHigh = 0x0000;0 E1 }, l7 P: j
- sFilterConfig.FilterIdLow = 0x0000;
2 v7 Y3 w" N! S; D/ R* w! `4 ~; n: X - sFilterConfig.FilterMaskIdHigh = 0x0000;) D A# I) @3 Y
- sFilterConfig.FilterMaskIdLow = 0x0000;. Y. k9 V; K& y, M& \& k, U8 {& \
- sFilterConfig.FilterFIFOAssignment = 0;
' j& R4 S* H, E1 }- U p - sFilterConfig.FilterActivation = ENABLE;' b' g+ T" d3 o8 A9 u
- sFilterConfig.BankNumber = 14;
1 ^( S; j+ |6 f$ y$ T - & {& O) \) @9 F0 b: s
- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //为 CAN1 配置过滤器2 e+ E) y* X+ G( Z
- {
, H! A2 h1 J: r/ v+ j. D6 @) g/ L - /* Filter configuration Error */
1 ~1 k- w' C! @) m% R - Error_Handler();
) e& P3 G* g3 |1 Z& ?+ | - }% @* N5 [# v: _" {
- sFilterConfig.FilterNumber = 14; Q& w* K- F5 P" [( J7 ~+ f
- sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;& a% z$ d {. j/ m# U
- sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;5 t7 w( X# b1 a' q
- sFilterConfig.FilterIdHigh = 0x0000;
4 I i5 f% `! e - sFilterConfig.FilterIdLow = 0x0000;3 y7 L, `5 q( y! B$ j
- sFilterConfig.FilterMaskIdHigh = 0x0000;* Q% M6 M0 H& R1 v5 |9 t
- sFilterConfig.FilterMaskIdLow = 0x0000;5 O! ~ U+ B, l& }: k
- sFilterConfig.FilterFIFOAssignment = 0;1 ^" @% ~0 i1 T" ^
- sFilterConfig.FilterActivation = ENABLE;5 p% h( h& m& D, X* h( w
- sFilterConfig.BankNumber = 14;
8 \7 | S9 ]7 K8 X - if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) //为 CAN2 配置过滤器,请留意这
) D, V+ G1 Y& N, r - 行代码3 \5 e' _: ]% u3 \9 c
- {
; m6 S" a9 T& ]. K, [- @7 } - /* Filter configuration Error */
4 i1 d' L) G5 @6 C - Error_Handler();
7 _8 w8 L& _/ W p/ V1 h6 i7 e% l - }5 D/ ?+ `8 r4 G9 E3 B9 y; e
- hcan1.pTxMsg = &TxMessage1;; G* ^0 o2 D0 k. E
- hcan1.pRxMsg = &RxMessage1;
' t" t- G2 B! a6 n. C# f - hcan1.pTxMsg->StdId = 0x321;
/ u) T+ ]* `! w2 ]6 \! W( ]" J# l - hcan1.pTxMsg->ExtId = 0x01;
8 L1 Z/ e1 m- E1 {" d - hcan1.pTxMsg->RTR = CAN_RTR_DATA;
0 x8 f4 j# E. V# B* c9 B8 J8 L - hcan1.pTxMsg->IDE = CAN_ID_STD;3 X+ J6 }3 O6 O$ t5 i, Z
- hcan1.pTxMsg->DLC = 8;
+ I$ D* b! `$ f7 B, s0 e: B9 q - hcan1.pTxMsg->Data[0] =0x01;) M$ I* t$ k8 H4 U
- hcan1.pTxMsg->Data[1] =0x02;
2 ?+ Z# L. h% x* [# ^% ~6 d. X. Z - hcan1.pTxMsg->Data[2] =0x03;
1 T6 F' ]4 V! X- K - hcan1.pTxMsg->Data[3] =0x04;& @7 c# T% G" k' ^6 J2 O* o/ J3 m1 n
- hcan1.pTxMsg->Data[4] =0x05;9 A j# e7 t# i }3 Z$ [( g" ?
- hcan1.pTxMsg->Data[5] =0x06;# ?8 D y" {4 r5 _. j( a
- hcan1.pTxMsg->Data[6] =0x07;! l8 f* W# W- f: V$ }8 y& C+ _1 [
- hcan1.pTxMsg->Data[7] =0x08;
' p y2 J) y0 u0 t4 ] - hcan2.pTxMsg = &TxMessage2;$ c& ?. O& q8 l0 e
- hcan2.pRxMsg = &RxMessage2;
1 K/ e2 z6 S Z5 E: B- v - hcan2.pTxMsg->StdId = 0x322;
& g/ S4 o6 F0 Z" t - hcan2.pTxMsg->ExtId = 0x01;
w9 [7 m7 Q( U7 C- |4 {' ? - hcan2.pTxMsg->RTR = CAN_RTR_DATA;2 @$ z, K, k) W! @" C$ V1 E7 z
- hcan2.pTxMsg->IDE = CAN_ID_STD;% v+ m2 }! X& P; D3 u# M3 s! t U
- hcan2.pTxMsg->DLC = 6;
5 Z: r5 t. P6 M - hcan2.pTxMsg->Data[0] =0x01;# J6 d8 B/ z3 t( M# h3 u
- hcan2.pTxMsg->Data[1] =0x02;7 M7 Y, g; U- c" k4 T& M2 c% l. y
- hcan2.pTxMsg->Data[2] =0x03;8 i* b, h6 O9 N
- hcan2.pTxMsg->Data[3] =0x04;
) @: o2 {' T' z; U; T, ~ - hcan2.pTxMsg->Data[4] =0x05;/ v! [) |( l ~0 A
- hcan2.pTxMsg->Data[5] =0x06;
1 {1 }3 Y# A3 j* `7 w5 @ w - hcan2.pTxMsg->Data[6] =0x07;
, p1 Y' ~$ J/ U% A) b6 x% ? - hcan2.pTxMsg->Data[7] =0x08;
6 {% X* |4 m5 s* y$ u7 q6 y - if (HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0) != HAL_OK) //CAN1 开始接收/ w2 O& p: ^- R0 K$ L2 v. |5 i G4 H$ Q
- {
) N$ N S& {) \3 f6 M# i - /* Reception Error */3 v0 [2 @+ J) F8 l' a, [- z
- Error_Handler();
/ X' r, V' d9 B: g8 H* V - }, G: p: H2 S( A, ?
- if (HAL_CAN_Receive_IT(&hcan2, CAN_FIFO0) != HAL_OK)//CAN2 开始接收
0 G. A+ N! R1 k# F% B+ z$ x$ J - {
- d1 p8 z8 b1 {) S - /* Reception Error */0 F& j) F0 r6 g* Z: \
- Error_Handler();
4 r$ J1 X0 {3 A" b1 k - }
9 h/ T) p6 H0 X! ~ - /* USER CODE END 2 */
复制代码 : a2 R! }! F2 G9 X5 a4 X
在 main 函数内的/* USER CODE BEGIN 3 */与/* USER CODE END 3 */添加:: S4 s1 m4 ? C& J
- while (1)
" W. `; q& L6 s5 w. Y& m/ I - {5 N e- P' h, W7 X1 c$ y& W
- /* USER CODE END WHILE */# R: K, v9 b" a. @5 k" y
- /* USER CODE BEGIN 3 */$ M% b8 W' h7 q3 A
- if (HAL_CAN_Transmit(&hcan1, 100) != HAL_OK) //CAN1 发送数据# v6 n: B* v6 _; |; @' H! J X
- {
8 [' Z- C9 { W* }) U - /* Transmition Error */
. g" d/ Q* X4 U8 x0 a% e# z- e- R - //Error_Handler();- Y" C D# Z6 H& E/ ]2 N3 C) K3 o( h. [
- }; g( z* p1 N( p. d
- HAL_Delay(10);1 X/ q' K. h t. N
- if (HAL_CAN_Transmit(&hcan2, 100) != HAL_OK) //CAN2 发送数据
- w" c, J% x* |/ j+ A; v - {/ [. b: `, @7 A8 w9 A
- /* Transmition Error */
! |4 w/ E" V: V9 U7 u - //Error_Handler();
! v l2 N$ I+ z7 f - }3 K# O+ z1 x: e# q- B
- HAL_Delay(1000);$ n6 O9 E* ^ }+ \# X
- }+ T7 r7 d7 V- k2 b
- /* USER CODE END 3 */
复制代码
+ C* O/ W6 k. a# D! y6 X$ P3.2 测试重现问题现象
( |( R/ \3 @8 u5 q* ~! o$ Y使用 ZLG 的 USBCAN-2E-U 盒子与 STM3210C-EVAL 评估板以及 PC 连接进行测试:
* a. _) T6 @6 a; B: q% Z% z4 f7 `. O
7 T. o' Q/ c% ?' A' e% j- K
& _5 G& M1 d9 s( E6 \7 A
& y/ `5 _$ _; `8 O6 b
在调试下,在 PC 端软件 CANTest 下都能看到 CAN1 与 CAN2 发送的数据,这说明连接上是完全没有问题的,但是,在调试 CAN 接收时,在 CAN2 的接收中断处设置断点,使用 PC 端软件 CAN_Test 向CAN2 发送数据发现并不能产生中断,而对比 CAN1 时,发现 CAN1 却可以产生接收中断。; Y$ _$ M2 A( a" q Q
( J2 h+ p6 G' F, _( p, l/ @
4 问题分析0 p2 u0 {- }2 M2 E% ~4 {
仔细对比 CAN1 与 CAN2 的代码,发现并没有什么不同之处。仔细思考一下,由于 CAN 接收中断是与CAN 过滤器有关,因此,着重对比 CAN1 与 CAN2 设置过滤器时的代码差异。7 C6 z' O0 f) T4 Q6 T0 n+ f& T8 W% y
CAN1 设置过滤器代码如下:
5 a( c7 b0 b/ u7 m0 [- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)8 }, K; b+ C& a! N4 x- @% [; k
- {
8 s% C0 J! P0 i, Q - /* Filter configuration Error */3 u. ?/ P `7 z: N4 k6 [7 I
- Error_Handler();. y% t: s4 S8 Z7 a
- }
复制代码
( q2 A0 e# _* A$ u0 j: W" [而 CAN1 设置过滤器代码如下:
^% H( q& T2 |: h; X- if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
) V1 c4 R& Z9 U5 V - {
9 x- r q6 q8 |! ^: ` - /* Filter configuration Error */
$ t7 c, e* m8 G) k - Error_Handler();
Q& |$ X1 _* S5 z" k6 e# B& l - }
复制代码
5 P* c+ S, a* R, P# ^6 R看来好像没有什么不妥的地方,基本差不多,只不过过调用 HAL_CAN_ConfigFilter 函数配置过滤器传入的第一个参数一个是&hcan1,一个是&hcan2,
* j$ g( v. E' C0 y查看参考手册,对比 CAN1 与 CAN2 的差别:' w4 W6 J/ h& `' g( k2 a. B
在参考手册的 24.4 节中对 CAN 的功能介绍时有下面一段话:
: z! P; k- B) E8 T/ l) `9 g/ l# Q6 N. K! X) K* P& C( }" _
& g7 D ~* I/ q! w' b
9 ?' B* _- C' J" j8 ]
上面一段话的意思是说,CAN1 是作为主,而 CAN2 做为从,做为从的 CAN2 不能直接访问这个专用的 512bytes 的 SRAM,而只能通过作为主的 CAN1 来间接访问,且 CAN1 与 CAN2 是共享这个专用的 512bytes 的 SRAM。打开图 222,如下所示:+ k0 X! i' ~; A, b% }3 ~
0 ~# Z& ^! [( H3 Y
; U; K! ?: F( R) L
; m( E1 `9 o; W4 z0 |& v3 K如上图可知,CAN1 与 CAN2 共用过滤器(Acceptance Filters),CAN2 是通过 CAN1 的 Memory Access Controler 来访问过滤器的。过滤器共有 28 个,占用 512 专用字节其中一部分。
" }+ ~2 s7 t5 L8 o- o3 U) n接着在数据手册中查下内存映射,如下图所示:
' E- T6 t* ]" A; a; |: d" M7 {+ B
, c% |' E: L5 Y- Z4 n
( d$ s7 F! c1 w# r% h4 u& [ K" k
可知,CAN1 的地址为:
! b5 p8 C, J) @: x& x
1 R2 `7 q$ B+ \1 i
! g$ B% p: q+ Y. A' N, l) K
) V! _- \8 k/ Y$ C" e, [! x. a然后查看 bxCAN 的寄存器,在参考手册的 24.9.5 节中,发现有这么一段话:
7 l% l% z. C* r8 T$ p& W. C. q, t: ]/ S, H" p
; }: P7 V, Z" D3 O
2 _# m- Z$ l( [1 V3 ?7 }
也就是说,从偏移地址 0x200 开始到 0x31C 之间的寄存器只存在于 CAN1 中,在 CAN2 中并不存在,那么这些都是些什么寄存器呢?5 ~$ e7 V$ F5 \& W
查看参考手册的 CAN 寄存器映射表,如下内容所示:* v- G- r% O: P2 `1 F: S
. \ @. R! r) E; E
' }+ p7 {' v4 w+ X$ J
0 z4 u: S1 A, |* ?9 D4 T" n, L
) T- }# F2 b% H9 Y6 A+ I
$ o* w8 B7 r! b可知这些都是 CAN 过滤器相关的寄存器,可知离 CAN1 起始地址 0x4000 6400 偏移 0x200~0x320 之间是 CAN 过滤器寄存器的地址,且这些过滤器由 CAN1 和 CAN2 共享,且最重要的一点信息是,离CAN2 起始地址 0x4000 6800 偏移 0x200~0x320 之间是没有寄存器的,这个非常重要!5 W; q7 H% o- i" j X6 \/ f) e5 P
再回过头来看 CAN2 过滤器的设置代码:7 R( l6 [- y3 N8 a
- if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)4 T/ r' I5 j. v+ D) D ?$ w
- {9 T' D' ~9 n5 x& o0 w8 H1 r
- /* Filter configuration Error */8 h0 N2 c+ C# ?6 ^2 U# {! A' y2 q" y
- Error_Handler();5 ]. p9 M; V1 J
- }
复制代码
6 B5 T% H/ L0 t) E+ T& h& c. q' V这几行设置过滤器的代码到底是将参数设置到 CAN1 偏移 0x200~0x320 之间还是 CAN2 偏移的0x200~0x320 之间?这个问题要弄清楚,非常重要的!继续看 HAL_CAN_ConfigFilter 函数内:" j8 l- ^6 g ^6 G0 a" M
- if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)% r0 C* @- K1 K* ]# F e
- {
5 G$ s0 s% F- m. E - /* 32-bit scale for the filter */
4 y" M: X: H: {; Y3 n) \ - SET_BIT(hcan->Instance->FS1R, filternbrbitpos);
% p$ R& E; M; Y6 u" }6 |0 K7 k9 T - /* 32-bit identifier or First 32-bit identifier */
; V8 o- }: t! r2 u9 \% i - hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
; G( a. ?, k5 A0 |! z - ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) FilterIdLow);. o9 W) N; Q+ b- U+ Y k* P
- /* 32-bit mask or Second 32-bit identifier */6 P: ]/ D! E+ p6 _9 C
- hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =+ n% ^' {& [* B
- ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) FilterMaskIdLow);
3 _3 P9 u! X+ D! C: m - }
复制代码
9 @" g% A5 ~4 V5 `& q4 \% c% g4 O- B由上代码可知,设置的参数实际上是设置到传入的句柄 hcan 的示例 Instance 下的成员 FS1R,sFilterRegister[]中去了,查看这些成员的定义:: X9 m4 t2 d+ c% g2 q
- typedef struct" S: M: p2 K8 Q, F! k) V! D9 x
- {5 r* H# v5 f M9 _/ A7 H' Q6 ?
- __IO uint32_t MCR;
3 X! G8 w& \3 Z' w6 y6 _/ D - __IO uint32_t MSR;9 B8 e; v5 m: T
- __IO uint32_t TSR;
! Y6 D" k/ @+ C$ ^3 k& ^ - __IO uint32_t RF0R;
. K0 p& ^9 `$ X - __IO uint32_t RF1R;' N2 E8 T4 y: L; Q, e& J. T( M8 T J
- __IO uint32_t IER;
1 ^, B1 F: B9 O - __IO uint32_t ESR;+ \2 k! q! {: ~% t6 `4 @" V4 R4 Y
- __IO uint32_t BTR;
0 c8 F3 ?: t1 o$ a - uint32_t RESERVED0[88];* B( ]! s* [) h" m$ _# y3 V, m/ j
- CAN_TxMailBox_TypeDef sTxMailBox[3];' i7 s) E3 S U( V. N
- CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];+ W4 O9 p: v4 e
- uint32_t RESERVED1[12];
" D, P# Y) d5 J7 a9 \% J5 E* f - __IO uint32_t FMR; //过滤器主寄存器
% Q8 c6 e3 o& m - __IO uint32_t FM1R; //过滤器模式寄存器
& z1 |8 z+ P5 N: R$ b' i - uint32_t RESERVED2;
( X* Y5 {* A( o" U- q% H - __IO uint32_t FS1R; //过滤器位宽寄存器
! H7 H2 K, i- @: E5 V* z1 l! F - uint32_t RESERVED3;5 E! p7 o& R3 C
- __IO uint32_t FFA1R; //过滤器 FIFO 分配寄存器! y' c l# g+ G, C: d( d
- uint32_t RESERVED4;! E) u. D3 l# m. Q, l
- __IO uint32_t FA1R; //过滤器使能寄存器
7 U+ F8 \/ ~( \, ^4 _6 N8 x - uint32_t RESERVED5[8];
: {8 Y- E. [ D - CAN_FilterRegister_TypeDef sFilterRegister[28]; //过滤器( j' n1 @3 ~$ J! [6 H K ?
- } CAN_TypeDef;
复制代码 3 m9 ?1 }. `% M# z5 R1 i
由以上代码可知,HAL_CAN_ConfigFilter 函数实际上就是对传入的 CAN 起始地址偏移 0x200~0x320之间的过滤器相关寄存器进行参数设置,但是,对于 CAN2 来说,实际并不存在这个这些寄存器,因此不会生效。这个可以在调试过程中查看 CAN2 寄存器值来验证,如下图:3 {$ f" H, r# ], _- x& J4 O' T
2 s5 G4 i7 N* N3 L9 h+ o
/ s) E, V* v; ~
2 x7 {& O) p7 ~; a9 t# f9 R# W在运行过 HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig)之后,CAN2 相关的过滤器还是没有变化,进一步说明此函数对于 CAN2 来说是无效的。% _( L5 C- ]* a' k7 Y1 d
那么要解决这个问题,该如何修改呢?很明显,通过 CAN1 来设置即可。CAN1 和 CAN2 共享过滤器,但设置过滤器时可以通过 CAN1 的偏移来访问过滤器,这么说来,也可以将这个理解为 CAN1 作为“主”的确切含义吧。
5 Y, t8 w& ?4 s& D% g修改后如下:
4 e7 R' h5 n" Y3 d; D( S- if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //使用 CAN1 作为参数
$ p& V- ?7 b% Y- o - {
& i$ k4 b* d: I+ Z5 c X! [ - /* Filter configuration Error */% ~; j+ z0 [$ }6 O/ |
- Error_Handler();
8 t0 `$ Q/ u' D7 s - }4 A: }5 X0 n4 P f4 ~( p
- sFilterConfig.FilterNumber = 14;
7 S s) r1 Y9 `$ j# F, P* H& R! P - sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;2 ~6 G) X/ v! R' H0 q" j4 l
- sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;1 H4 J! V/ j$ ~5 K' h
- sFilterConfig.FilterIdHigh = 0x0000;/ q/ o2 ^" q) G; r3 n2 j' Z
- sFilterConfig.FilterIdLow = 0x0000;
; D8 B' p/ S R1 x+ J - sFilterConfig.FilterMaskIdHigh = 0x0000;
) o: q" p8 E6 A% _ - sFilterConfig.FilterMaskIdLow = 0x0000;
: L" o3 j3 d# c! O - sFilterConfig.FilterFIFOAssignment = 0;
- b6 f9 `8 b2 ` - sFilterConfig.FilterActivation = ENABLE;& S" H3 p R7 k( v$ D& V6 F; G
- sFilterConfig.BankNumber = 14;
9 T+ ?- p8 j. E2 Y/ k; y5 I7 W" w% u - if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //还是使用 CAN1 来作为参数4 j* T; o4 m; l; B0 M, V* e, |6 O
- {/ C- D4 E% W, v7 `3 h
- /* Filter configuration Error */
4 E) P0 {+ l, I9 ~) [ - Error_Handler();% a" |2 `4 B9 Q! y
- }
复制代码
0 `( R9 R# d! t& x+ }9 d在 CAN2 中断设置断点,使用 PC 端软件 CANTest 向 STM3210C-EVAL 评估板的 CAN2 通道发送数
+ U, a* V- M5 ?! g# p2 A据进行测试验证:
6 X( r2 R$ i2 o% n4 E8 y9 d) x- k3 q6 B# V) e( V
% D; F2 U2 r! Z! L& d0 b- }5 a$ a
+ B+ T* H% ?# y/ h5 F如上图可见,CAN2 的接收中断已经可以正常捕获到了。
2 N+ R( N5 G+ S$ r
8 M9 I* j f0 c z; f; f8 k5 横向扩展1 c2 Q* e6 S9 \# M& ^
此问题是在使用 Cube 库下时发现的,那么标准库是否也会存在同样的问题?
0 S( @% n9 k& \) ^$ G+ H其实,在使用标准库下,在设置过滤器时,并不需要传入 CAN1 或 CAN2 的句柄,因此也就不会这这种问题,如下基于标准库的示例代码:& Y. h1 _- U; M. w: h5 I
- void CANFilter_Config(void)
7 r4 E. ?2 I/ @# _4 Z - {
( I7 I9 ]& @5 I! N- n2 _ - #ifdef __CAN1_USED__
' ^% j! I4 }4 w/ Q9 s3 X& s9 [# I4 @ - /* CAN filter init */
% R( u# D+ u( Z2 v1 r* |* e - CAN_FilterInitStructure.CAN_FilterNumber = 0;
2 ?7 |, m- O& h# h' L- ~' [( T - CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;- |* A" Z) e3 M
- CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
/ e$ {# O1 S! c' `% O. } - CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;" K2 T% c. W7 w/ Q# t
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
5 ~. q5 L# V4 M7 t - CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;( e& n6 f5 W' Y/ e. F q
- CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
9 }, ~! X( ?: R& h - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;' {- X/ ?: A( ]+ O4 U2 I+ Q/ y, q: M
- CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
' S Y: F1 d3 S - CAN_FilterInit(&CAN_FilterInitStructure);
. N$ u0 x+ ~6 a' D9 v/ F, ?, i - #endif
2 s0 X- @$ e: E* L2 c1 _ - #ifdef __CAN2_USED__/ X: I! d5 i" F2 E* T( P. t
- CAN_SlaveStartBank(14);' D$ b- m* }( C* s0 \: e: V" z7 ?5 `
- /* CAN filter init *// T9 t; T7 w, s' Z( g6 u. q
- CAN_FilterInitStructure.CAN_FilterNumber = 14;6 j! P' V# `8 U: I8 i
- CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;, y6 I4 v) |0 K3 u2 x
- CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
8 a- H3 _: n* P: O$ [, U3 i - CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;( \0 Z4 m# t" P, Q4 {/ U8 @$ g7 s
- CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
$ ^% t1 m3 b9 R. W# w8 Y - CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
8 ~1 K" f" i$ f( L0 l - CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
$ _# V. s8 `5 b/ C4 P4 U - CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;$ n {' ^9 P3 D% D
- CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;* g P5 R. p N
- CAN_FilterInit(&CAN_FilterInitStructure);
) M2 z# e( ?2 o7 u$ v - #endif
" {% {$ Z. G% Z5 ^% L - }
复制代码 " u8 }; y8 h6 C% Y+ s+ a
在函数 CAN_FilterInit 中,内部自始至终操作的都是 CAN1,如下所示:" m3 x" g0 W8 x9 i& b* v6 m W2 A
- //…5 q5 Y/ L$ s9 ]' l0 v) C: a
- if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)& b2 P( b3 a. P
- {3 D4 @3 ?7 Y% H* C; S1 M$ h m
- /* 32-bit scale for the filter */% a. a2 e: ~% I4 l( I! P; G2 B
- CAN1->FS1R |= filter_number_bit_pos; //操作的是 CAN1 的偏移地址
" q' C" Z2 `. B: t- u" F - /* 32-bit identifier or First 32-bit identifier */5 v2 r4 o5 r3 G. ?! A) J
- CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =# f, X" { o# | U4 h$ T
- ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) CAN_FilterIdLow);
( i+ V. D: w0 d - /* 32-bit mask or Second 32-bit identifier */
/ C) L$ S& p. v9 V& a# G, [; V - CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =
4 l" Y+ y3 l9 V4 e& e+ ^7 I - ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) CAN_FilterMaskIdLow);
# u1 Z* v# D4 e5 W& T - }
9 {) }3 y1 k0 P) G, J( G" |+ F8 e - //…
复制代码 0 u u0 i2 D" u9 @$ n- c: @% x* [ v8 ?
因此,不会出现在 Cube 库下出现的问题。
L" W8 T0 }; `$ Z+ y* A8 }* V5 i; b. m. o2 V& O5 H) C- `
6 总结; G, l! `9 a+ ~ [3 _; U' ^
此文所描述的问题之会出现在使用 Cube 库的情况下,且基本覆盖包含双 CAN 的所有系列,在使用HAL 函数 HAL_CAN_ConfigFilter 配置过滤器时,将第一个参数固定指向 CAN1 的句柄就可以了。
3 n' e/ S( Q( N" I+ B2 [- s7 y) ^7 }. l2 C
|