你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】基于 Cube 库无法检测 CAN2 的接收中断

[复制链接]
STMCU小助手 发布时间:2022-2-14 21:54
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 \
XA(C606K`S}{0B0TSE6`~JJ.png + F) p! ?3 [5 {0 ~0 F2 \1 n: d+ V  i

8 v6 I8 y+ }- h! u W)`X4(QJNRY(6PSZB`BW]UJ.png
" l. ^) {4 x- `. }' G1 s& {
) Z+ n. `# e6 \# o1 Q) O. i V2DE`@XDL0Y[K6C`5K$E2.png
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
  1. /* USER CODE BEGIN 2 */
      k1 A$ ]( C" V" h- Y
  2. sFilterConfig.FilterNumber = 0;1 F$ ^- f" k* }* ]
  3. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    ( {  [, Q3 a( S- K* ]& _  v! z: @
  4. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;- p/ t& i! t7 D) q6 T/ p
  5. sFilterConfig.FilterIdHigh = 0x0000;" ?! Y: u/ [- m- z
  6. sFilterConfig.FilterIdLow = 0x0000;
    ' D; l( b2 f& l: s/ [
  7. sFilterConfig.FilterMaskIdHigh = 0x0000;3 Z" Q3 q4 v' Z8 ^3 f/ L
  8. sFilterConfig.FilterMaskIdLow = 0x0000;0 V+ e, H1 f) Y% W1 [# f4 a
  9. sFilterConfig.FilterFIFOAssignment = 0;
    9 G' h# i! ?5 O* v3 O6 G
  10. sFilterConfig.FilterActivation = ENABLE;
      y8 t1 d/ z7 ~2 X& m6 o
  11. sFilterConfig.BankNumber = 14;
    6 {& M% b; B: J/ E% M& {  [: v

  12. ( v8 p  D- d2 n+ [4 e+ ?+ A: P5 j
  13. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //为 CAN1 配置过滤器- ?) }0 F4 c; _* E- S
  14. {9 ]3 E2 N5 i6 [0 F
  15. /* Filter configuration Error */
    " n3 d6 V$ n9 Z  a+ c
  16. Error_Handler();
    ) v1 e  c( T( c: J
  17. }
    & Z' t" ?" o" z: c" g
  18. sFilterConfig.FilterNumber = 14;3 _( B2 ]; G$ e0 c3 N
  19. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
      N: v: N" a+ u8 @
  20. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    / g: }! N* ?4 N" ?
  21. sFilterConfig.FilterIdHigh = 0x0000;3 l7 K  L: n  Z) q3 \
  22. sFilterConfig.FilterIdLow = 0x0000;
    * D/ e: D/ ^/ w. ]- ~
  23. sFilterConfig.FilterMaskIdHigh = 0x0000;
    ) Q0 U; L  ?' l" U0 J. e6 a4 X
  24. sFilterConfig.FilterMaskIdLow = 0x0000;
      j+ k" B0 h, A! Z( U5 g
  25. sFilterConfig.FilterFIFOAssignment = 0;
    4 F2 g; o9 i# {  C
  26. sFilterConfig.FilterActivation = ENABLE;
    + G, h+ I" L. B
  27. sFilterConfig.BankNumber = 14;0 V, z: N; A1 K* v% e- j) C$ T
  28. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) //为 CAN2 配置过滤器,请留意这: d0 ~: g; A. G5 W2 R
  29. 行代码
    9 G% G) C) a( Q5 W4 x
  30. {0 |( D9 K1 ?" R
  31. /* Filter configuration Error */
    " I* S9 l' ~- C' F7 H3 W- ~9 j
  32. Error_Handler();  `$ H$ A9 X9 O& f" E
  33. }2 O& V! [. j: D7 S+ @4 ^9 q
  34. hcan1.pTxMsg = &TxMessage1;! w6 y$ t: Z; K, z7 M1 n
  35. hcan1.pRxMsg = &RxMessage1;9 E3 ^9 L- T) H0 K1 L
  36. hcan1.pTxMsg->StdId = 0x321;
    . y4 J  v7 X; ^! A( ?2 f+ P( q
  37. hcan1.pTxMsg->ExtId = 0x01;
    % {2 t7 q* `3 a
  38. hcan1.pTxMsg->RTR = CAN_RTR_DATA;* c- M: u1 F& f: I2 A" t- E
  39. hcan1.pTxMsg->IDE = CAN_ID_STD;, f; {4 W& l& I: o' y  K
  40. hcan1.pTxMsg->DLC = 8;4 }$ s4 \6 S* a2 }: {0 |% {/ A
  41. hcan1.pTxMsg->Data[0] =0x01;+ `! R  _) U4 @8 c7 L# Q
  42. hcan1.pTxMsg->Data[1] =0x02;
    4 c% C% C! f! k0 [+ s. F0 ^3 `
  43. hcan1.pTxMsg->Data[2] =0x03;
    7 Z8 T7 e7 b: e' d4 ^/ I5 j0 M. g
  44. hcan1.pTxMsg->Data[3] =0x04;
    5 g& Z. @" v" C+ `' \6 [
  45. hcan1.pTxMsg->Data[4] =0x05;
    $ W8 G: P1 s( N) T8 t
  46. hcan1.pTxMsg->Data[5] =0x06;
    ; I! j  O$ @" s$ J+ u9 k
  47. hcan1.pTxMsg->Data[6] =0x07;
    ) X0 `* `% m. P+ Z9 I2 N; f
  48. hcan1.pTxMsg->Data[7] =0x08;
    - O' q4 M4 [0 v/ T" ]2 ?
  49. hcan2.pTxMsg = &TxMessage2;
    ; f6 y* N1 D; N3 c! k) K
  50. hcan2.pRxMsg = &RxMessage2;
    9 N+ A$ H7 a5 c0 @0 i! z
  51. hcan2.pTxMsg->StdId = 0x322;& P2 {) g8 i) u9 {: j& X
  52. hcan2.pTxMsg->ExtId = 0x01;4 F1 J$ V( v% r1 ?6 V0 w3 I. Z
  53. hcan2.pTxMsg->RTR = CAN_RTR_DATA;
    2 G$ ^0 t6 F! ]( E
  54. hcan2.pTxMsg->IDE = CAN_ID_STD;
    0 M+ |# ]3 r0 f# M" B& M$ F' `
  55. hcan2.pTxMsg->DLC = 6;$ Q. m/ G0 E1 z# Q, d, H3 J; v, E
  56. hcan2.pTxMsg->Data[0] =0x01;
    . l3 w2 u0 P$ Z" p5 M
  57. hcan2.pTxMsg->Data[1] =0x02;
    " l, L3 n+ _. L/ F! {
  58. hcan2.pTxMsg->Data[2] =0x03;
    " T- ^8 s2 t: Z) R
  59. hcan2.pTxMsg->Data[3] =0x04;
    7 H% }/ J& @' @4 r8 e
  60. hcan2.pTxMsg->Data[4] =0x05;, k. _# J3 I* E' x5 W
  61. hcan2.pTxMsg->Data[5] =0x06;# i' K1 @2 _$ e# `# S( g: I
  62. hcan2.pTxMsg->Data[6] =0x07;: r/ m; Q% p$ A! s+ b$ W: h  ^8 g. k
  63. hcan2.pTxMsg->Data[7] =0x08;
      j; }: M% w, D# z8 u+ L
  64. if (HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0) != HAL_OK) //CAN1 开始接收
    ; m3 ^8 w" ^" H+ e- o. t
  65. {
    ' o; j- |% `& A
  66. /* Reception Error */  x/ L, l& O$ @, u; D- b' l" [
  67. Error_Handler();
    7 y4 M  {& C' B. \- p
  68. }
    4 q4 }3 Y3 k  x" @6 P4 }
  69. if (HAL_CAN_Receive_IT(&hcan2, CAN_FIFO0) != HAL_OK)//CAN2 开始接收
    ' K: }7 P$ a, a7 b& a: P- B
  70. {) X- l5 X* M# G6 D& u  ~
  71. /* Reception Error */& w4 }- t$ s, s/ ?7 n" O1 r! ^- w
  72. Error_Handler();
    % {1 r, D: b8 x' A6 D
  73. }
    7 [" ]* v* ~! \/ M4 h- s% D1 ^
  74. /* USER CODE END 2 */
复制代码
' D( g0 ?5 Q' |, r
在 main 函数内的/* USER CODE BEGIN 3 */与/* USER CODE END 3 */添加:
8 Q# z' G: ~$ v
  1. while (1)0 L: x8 ~6 s8 a( n$ s* G+ ^/ e0 r
  2. {# y9 v/ Y8 e% e8 r  w
  3. /* USER CODE END WHILE */* o* m% K' [3 F. s
  4. /* USER CODE BEGIN 3 */1 Y$ s. G. \, y; e  {5 T, X, g
  5. if (HAL_CAN_Transmit(&hcan1, 100) != HAL_OK) //CAN1 发送数据7 v7 m2 T' y" {3 A1 }9 {+ K
  6. {. H/ s7 C0 a7 K( Q1 s6 z, h
  7. /* Transmition Error */4 M( W5 p  u9 I7 w
  8. //Error_Handler();3 K( X6 o' R5 h2 @4 K! f5 g2 s
  9. }
    8 b% d% `' g  J) Q
  10. HAL_Delay(10);
    " j( ?, r1 E" M2 f. f
  11. if (HAL_CAN_Transmit(&hcan2, 100) != HAL_OK) //CAN2 发送数据; m8 P% H) n$ P
  12. {5 w3 b3 z8 i) r1 r' j" o
  13. /* Transmition Error */  J3 g. T' I+ g5 F) w# k
  14. //Error_Handler();2 L4 B5 ?) y" v% k0 _3 A& b- s
  15. }: l) L, h1 d0 D1 s( Y
  16. HAL_Delay(1000);8 N) s& E) r0 t- e7 q
  17. }5 w& C# c, {& f  u; A( @7 _
  18. /* 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 LQAZTB4Z@52I~WRCHSP[CVQ.png 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
  1. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    0 ^9 p3 n4 r8 ?, W  U
  2. {
    2 z1 z2 V0 _7 h$ M, u8 m
  3. /* Filter configuration Error */  \3 }- s& M4 N
  4. Error_Handler();# w, \2 Q6 q- N% u: V2 V# M
  5. }
复制代码

) z8 o4 F/ L2 }, ~而 CAN1 设置过滤器代码如下:
7 ?3 ^( Q  h# D- o" l
  1. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
    ) W" u% H9 Q+ p, H1 P
  2. {
    & u/ h& I: y7 _6 @
  3. /* Filter configuration Error */! k  T! Z& k2 L: S1 a3 a# j
  4. Error_Handler();2 _  E0 {! ]( c0 I% z2 F' I) t
  5. }
复制代码
, 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 5VG](@WM5EZV002R%9~{)VW.png $ 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 A_N4{(~WCJC4RX)C8IMK~}5.png 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 XZ]QKL6KUZ)27@35L2JDIQO.png
) G7 \% Y8 Q; M2 g1 f( x, v; r" c, P
可知,CAN1 的地址为:
6 Z' {* q# R0 u( ~, h& k/ B# X" I- j3 [
YS)V@HBBVU_%{3FK(3F7{KS.png
  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
]IXZUCWY9I){Q25{A`PS(WB.png & 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
~(R%G0YAMA5ZV][WV{WLP5D.png 4 T9 g5 y9 {7 `9 R% g) a

) O) @; ]: r& b) E4 E! X TKMH2{ZY7EKL6~A{J{J2R.png
* 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
  1. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)! q; h0 ]1 C' I4 n5 t
  2. {; H( k" G/ M- C0 Y
  3. /* Filter configuration Error */
    2 c+ o+ S  i9 l2 {
  4. Error_Handler();
    8 b6 `2 ~& ?5 [9 o& g+ a+ h7 |6 ]! Q
  5. }
复制代码

+ V' q9 d* D9 R& x( h# b) v这几行设置过滤器的代码到底是将参数设置到 CAN1 偏移 0x200~0x320 之间还是 CAN2 偏移的0x200~0x320 之间?这个问题要弄清楚,非常重要的!继续看 HAL_CAN_ConfigFilter 函数内:
$ k5 I: g" F' {8 M
  1. if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)* c! l4 D: d/ e( I7 T9 z6 B: F. @
  2. {
    2 y, Y) I7 o( M- G$ P% Q0 R8 i
  3. /* 32-bit scale for the filter */
    2 y4 v% n9 h2 t) M$ z0 }  m
  4. SET_BIT(hcan->Instance->FS1R, filternbrbitpos);1 T' J. Y; o8 ~; j9 c6 C, q
  5. /* 32-bit identifier or First 32-bit identifier */
    % k6 q+ V2 P, Q8 U3 p
  6. hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =! T  P2 [- e1 _
  7. ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) FilterIdLow);( {6 c# d9 p: i; q; U
  8. /* 32-bit mask or Second 32-bit identifier */
    6 V5 R! ^- R8 j& }
  9. hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =1 ]+ z2 F/ g% W8 \% r) t! H& C7 J
  10. ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) FilterMaskIdLow);
    ( W. P& G! a3 o$ r5 B
  11. }
复制代码

1 Y0 N3 d5 P6 [0 P) j8 {! G6 Z由上代码可知,设置的参数实际上是设置到传入的句柄 hcan 的示例 Instance 下的成员 FS1R,sFilterRegister[]中去了,查看这些成员的定义:! m( s+ X- @) l6 C  n2 I
  1. typedef struct8 a. B; U6 d4 t- d' j& K
  2. {. ^" S$ ^4 H6 U' B* I
  3. __IO uint32_t MCR;
    3 p8 S4 W% i2 ~. a0 D( i! H6 f  H
  4. __IO uint32_t MSR;' e, r- d' N$ }+ f5 I
  5. __IO uint32_t TSR;" l0 f! |1 P* k1 b1 C, ^+ R8 H& W
  6. __IO uint32_t RF0R;
    + S* ~6 U5 i5 @5 C" H7 D
  7. __IO uint32_t RF1R;' J$ M! {/ O! [) M6 M* O/ O
  8. __IO uint32_t IER;
    , v/ N6 x! O% F- Y, q3 @
  9. __IO uint32_t ESR;
    / c8 m1 y; @" f: E8 ^& g
  10. __IO uint32_t BTR;
    5 E1 ?9 U! i9 z3 S' h2 t- a
  11. uint32_t RESERVED0[88];- \1 @" I1 a7 u, x$ H
  12. CAN_TxMailBox_TypeDef sTxMailBox[3];' e8 O, J$ c% q/ z) s  n, E4 i; h4 `$ ]) p
  13. CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];
    4 _! y; Y3 K: F4 `0 I
  14. uint32_t RESERVED1[12];# }: r5 J4 s. A, Y) @& O( D
  15. __IO uint32_t FMR; //过滤器主寄存器
    : ?' q: W' o+ i2 r! w2 ]  e) W
  16. __IO uint32_t FM1R; //过滤器模式寄存器
    0 b# ^3 Z7 N& V- v9 t
  17. uint32_t RESERVED2;* a7 H7 ]* \; C
  18. __IO uint32_t FS1R; //过滤器位宽寄存器
    / l" A5 t) `; Q1 m3 @1 h
  19. uint32_t RESERVED3;
    5 m2 M5 o$ U! _' d6 x1 }
  20. __IO uint32_t FFA1R; //过滤器 FIFO 分配寄存器
    + k/ N' O2 Z5 k1 g
  21. uint32_t RESERVED4;$ T: J' H) F3 n; j' }
  22. __IO uint32_t FA1R; //过滤器使能寄存器7 k# U; @1 [2 B/ B/ A" y0 E
  23. uint32_t RESERVED5[8];* o8 X( t. e; b, A1 t% b! y6 Y$ {5 i
  24. CAN_FilterRegister_TypeDef sFilterRegister[28]; //过滤器; Y' O; w/ f. c& ~, P# X/ b
  25. } 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
OTFV~}307SU6RTO_P4~D12S.png
- 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( `
  1. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //使用 CAN1 作为参数; b4 ^2 ]! i. \4 v( X4 U2 V! i
  2. {, {5 C# l) E. x- R$ p; e6 A7 M" D
  3. /* Filter configuration Error */  u( x# w( [9 s5 U8 M% Q& {/ P
  4. Error_Handler();
    ) |8 T8 x8 |$ E: x* ^
  5. }- D. J: U3 Z8 h0 U; J" t
  6. sFilterConfig.FilterNumber = 14;
    ' D9 `. ^6 h7 a
  7. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    0 B1 z* i/ o$ k0 f5 {9 N
  8. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
    1 V- q. a) y# L5 ]2 o4 W5 C
  9. sFilterConfig.FilterIdHigh = 0x0000;+ E1 T- a  d/ n4 S( d
  10. sFilterConfig.FilterIdLow = 0x0000;3 [' \+ {  i& s6 w. ^& `% e: c
  11. sFilterConfig.FilterMaskIdHigh = 0x0000;5 j: t" I& o/ j
  12. sFilterConfig.FilterMaskIdLow = 0x0000;$ a: K) Y. X  @: v2 g
  13. sFilterConfig.FilterFIFOAssignment = 0;
    : w( L9 T) \( H: j
  14. sFilterConfig.FilterActivation = ENABLE;
    4 }- S# ]+ b" o% T
  15. sFilterConfig.BankNumber = 14;
    : O9 t! F' |6 [
  16. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //还是使用 CAN1 来作为参数
    & j+ z& x( D8 V
  17. {
    * r! s4 x/ A9 s
  18. /* Filter configuration Error */
    ) w2 [2 U3 r; a- ?" O! G9 i2 X
  19. Error_Handler();
    2 |5 `0 y" z0 P1 ~- k& C
  20. }
复制代码

% [. 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 ~ B0OH_3X0B2_L%CUTIZL{{5R.png
  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
  1. void CANFilter_Config(void)
    $ b+ Q& m5 S' F. h0 x
  2. {
    " \; n* f6 m) c' B4 D9 b8 D
  3. #ifdef __CAN1_USED__
    8 J0 j2 O: Z  K+ B! w( f
  4. /* CAN filter init */
    " u7 I# q8 P: E/ K. ]* f
  5. CAN_FilterInitStructure.CAN_FilterNumber = 0;* X* [5 s3 z, i
  6. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;7 I! X, u! G# U+ E! y2 l; U. Z. w
  7. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    1 j1 o+ R3 b0 c
  8. CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;! F: _+ k6 g2 w3 y+ V4 ]* c
  9. CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;7 a6 V" f' z4 s- t% X
  10. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    2 G) s) G0 X5 M( y
  11. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
      J6 b& s6 C* }# L- Z2 N( Z% |& z; r( V
  12. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    2 X$ r8 W& V" f' ]
  13. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;' `* |0 H! T+ y6 S5 l# T9 t
  14. CAN_FilterInit(&CAN_FilterInitStructure);7 B# G! J9 g2 o6 d
  15. #endif
    2 E8 H& ^( Y9 |
  16. #ifdef __CAN2_USED__; c- f. i8 _  M, c( {5 S5 k
  17. CAN_SlaveStartBank(14);- x' h8 G+ M3 s9 f
  18. /* CAN filter init */
    & c) {+ V( t/ \7 D& n
  19. CAN_FilterInitStructure.CAN_FilterNumber = 14;1 `. l8 A$ a$ @+ J# h3 f8 N
  20. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;, h* l5 h( f; M& g6 Y
  21. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    8 F  B& s8 U' D3 _( q
  22. CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;" q5 _6 }2 w) J
  23. CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;* ]( m+ D7 j* X. N. S6 |
  24. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    7 O3 y& F) h: S' e& U: a2 n
  25. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    3 w  }( B! ~0 r* ^
  26. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
    ; U& @5 @0 P# l
  27. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;2 N/ `0 a% s& L! B
  28. CAN_FilterInit(&CAN_FilterInitStructure);# W, H  X  \, e; t$ Q2 z9 N% F
  29. #endif
    " q- D% z$ _7 O; Y  H2 h2 O: r
  30. }
复制代码

3 i3 e" P/ ?' k在函数 CAN_FilterInit 中,内部自始至终操作的都是 CAN1,如下所示:
% v( u4 H3 q6 M: Y3 `/ N: b/ k
  1. //…
    3 x5 t; [; H7 A
  2. if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)6 D# D" ]) v& V
  3. {
    + J' q4 \% r* A8 y
  4. /* 32-bit scale for the filter */
    - \+ u; s% i. M4 p2 y5 Q* N
  5. CAN1->FS1R |= filter_number_bit_pos; //操作的是 CAN1 的偏移地址' [6 Q( d2 B$ c
  6. /* 32-bit identifier or First 32-bit identifier */' D* }6 b' ]3 M
  7. CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =* k' _3 J) D* l6 v! R
  8. ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) CAN_FilterIdLow);
    ; C1 f. B; Z8 k2 |5 w
  9. /* 32-bit mask or Second 32-bit identifier */
    ; V3 w0 K5 U  m. r, T5 S+ s
  10. CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =. b) G  j6 F6 A( I
  11. ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) CAN_FilterMaskIdLow);
    0 h9 Q5 A! ~# c
  12. }3 @" h; v/ E* c( w1 a, W
  13. //…
复制代码

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
赞 收藏 评论0 发布时间:2022-2-14 21:54

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版