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

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

[复制链接]
STMCU小助手 发布时间:2022-2-14 21:54
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 ] XA(C606K`S}{0B0TSE6`~JJ.png
; F( m* I$ R1 F$ m% H  z2 g
8 j& t; b* {; Z% B& l W)`X4(QJNRY(6PSZB`BW]UJ.png ) t  C  @; @! ]( k

" x5 j; e% W  K# v3 e V2DE`@XDL0Y[K6C`5K$E2.png
" 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/ ?
  1. /* USER CODE BEGIN 2 */
    0 O  P1 U8 u+ E) a& _. i0 d
  2. sFilterConfig.FilterNumber = 0;
    ; L7 J" C: u8 `  j# }: @8 q
  3. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    9 E9 d9 |- E( R. [2 W) V
  4. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;4 w1 w0 u9 Z0 X; N
  5. sFilterConfig.FilterIdHigh = 0x0000;0 E1 }, l7 P: j
  6. sFilterConfig.FilterIdLow = 0x0000;
    2 v7 Y3 w" N! S; D/ R* w! `4 ~; n: X
  7. sFilterConfig.FilterMaskIdHigh = 0x0000;) D  A# I) @3 Y
  8. sFilterConfig.FilterMaskIdLow = 0x0000;. Y. k9 V; K& y, M& \& k, U8 {& \
  9. sFilterConfig.FilterFIFOAssignment = 0;
    ' j& R4 S* H, E1 }- U  p
  10. sFilterConfig.FilterActivation = ENABLE;' b' g+ T" d3 o8 A9 u
  11. sFilterConfig.BankNumber = 14;
    1 ^( S; j+ |6 f$ y$ T
  12. & {& O) \) @9 F0 b: s
  13. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //为 CAN1 配置过滤器2 e+ E) y* X+ G( Z
  14. {
    , H! A2 h1 J: r/ v+ j. D6 @) g/ L
  15. /* Filter configuration Error */
    1 ~1 k- w' C! @) m% R
  16. Error_Handler();
    ) e& P3 G* g3 |1 Z& ?+ |
  17. }% @* N5 [# v: _" {
  18. sFilterConfig.FilterNumber = 14;  Q& w* K- F5 P" [( J7 ~+ f
  19. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;& a% z$ d  {. j/ m# U
  20. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;5 t7 w( X# b1 a' q
  21. sFilterConfig.FilterIdHigh = 0x0000;
    4 I  i5 f% `! e
  22. sFilterConfig.FilterIdLow = 0x0000;3 y7 L, `5 q( y! B$ j
  23. sFilterConfig.FilterMaskIdHigh = 0x0000;* Q% M6 M0 H& R1 v5 |9 t
  24. sFilterConfig.FilterMaskIdLow = 0x0000;5 O! ~  U+ B, l& }: k
  25. sFilterConfig.FilterFIFOAssignment = 0;1 ^" @% ~0 i1 T" ^
  26. sFilterConfig.FilterActivation = ENABLE;5 p% h( h& m& D, X* h( w
  27. sFilterConfig.BankNumber = 14;
    8 \7 |  S9 ]7 K8 X
  28. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK) //为 CAN2 配置过滤器,请留意这
    ) D, V+ G1 Y& N, r
  29. 行代码3 \5 e' _: ]% u3 \9 c
  30. {
    ; m6 S" a9 T& ]. K, [- @7 }
  31. /* Filter configuration Error */
    4 i1 d' L) G5 @6 C
  32. Error_Handler();
    7 _8 w8 L& _/ W  p/ V1 h6 i7 e% l
  33. }5 D/ ?+ `8 r4 G9 E3 B9 y; e
  34. hcan1.pTxMsg = &TxMessage1;; G* ^0 o2 D0 k. E
  35. hcan1.pRxMsg = &RxMessage1;
    ' t" t- G2 B! a6 n. C# f
  36. hcan1.pTxMsg->StdId = 0x321;
    / u) T+ ]* `! w2 ]6 \! W( ]" J# l
  37. hcan1.pTxMsg->ExtId = 0x01;
    8 L1 Z/ e1 m- E1 {" d
  38. hcan1.pTxMsg->RTR = CAN_RTR_DATA;
    0 x8 f4 j# E. V# B* c9 B8 J8 L
  39. hcan1.pTxMsg->IDE = CAN_ID_STD;3 X+ J6 }3 O6 O$ t5 i, Z
  40. hcan1.pTxMsg->DLC = 8;
    + I$ D* b! `$ f7 B, s0 e: B9 q
  41. hcan1.pTxMsg->Data[0] =0x01;) M$ I* t$ k8 H4 U
  42. hcan1.pTxMsg->Data[1] =0x02;
    2 ?+ Z# L. h% x* [# ^% ~6 d. X. Z
  43. hcan1.pTxMsg->Data[2] =0x03;
    1 T6 F' ]4 V! X- K
  44. hcan1.pTxMsg->Data[3] =0x04;& @7 c# T% G" k' ^6 J2 O* o/ J3 m1 n
  45. hcan1.pTxMsg->Data[4] =0x05;9 A  j# e7 t# i  }3 Z$ [( g" ?
  46. hcan1.pTxMsg->Data[5] =0x06;# ?8 D  y" {4 r5 _. j( a
  47. hcan1.pTxMsg->Data[6] =0x07;! l8 f* W# W- f: V$ }8 y& C+ _1 [
  48. hcan1.pTxMsg->Data[7] =0x08;
    ' p  y2 J) y0 u0 t4 ]
  49. hcan2.pTxMsg = &TxMessage2;$ c& ?. O& q8 l0 e
  50. hcan2.pRxMsg = &RxMessage2;
    1 K/ e2 z6 S  Z5 E: B- v
  51. hcan2.pTxMsg->StdId = 0x322;
    & g/ S4 o6 F0 Z" t
  52. hcan2.pTxMsg->ExtId = 0x01;
      w9 [7 m7 Q( U7 C- |4 {' ?
  53. hcan2.pTxMsg->RTR = CAN_RTR_DATA;2 @$ z, K, k) W! @" C$ V1 E7 z
  54. hcan2.pTxMsg->IDE = CAN_ID_STD;% v+ m2 }! X& P; D3 u# M3 s! t  U
  55. hcan2.pTxMsg->DLC = 6;
    5 Z: r5 t. P6 M
  56. hcan2.pTxMsg->Data[0] =0x01;# J6 d8 B/ z3 t( M# h3 u
  57. hcan2.pTxMsg->Data[1] =0x02;7 M7 Y, g; U- c" k4 T& M2 c% l. y
  58. hcan2.pTxMsg->Data[2] =0x03;8 i* b, h6 O9 N
  59. hcan2.pTxMsg->Data[3] =0x04;
    ) @: o2 {' T' z; U; T, ~
  60. hcan2.pTxMsg->Data[4] =0x05;/ v! [) |( l  ~0 A
  61. hcan2.pTxMsg->Data[5] =0x06;
    1 {1 }3 Y# A3 j* `7 w5 @  w
  62. hcan2.pTxMsg->Data[6] =0x07;
    , p1 Y' ~$ J/ U% A) b6 x% ?
  63. hcan2.pTxMsg->Data[7] =0x08;
    6 {% X* |4 m5 s* y$ u7 q6 y
  64. if (HAL_CAN_Receive_IT(&hcan1, CAN_FIFO0) != HAL_OK) //CAN1 开始接收/ w2 O& p: ^- R0 K$ L2 v. |5 i  G4 H$ Q
  65. {
    ) N$ N  S& {) \3 f6 M# i
  66. /* Reception Error */3 v0 [2 @+ J) F8 l' a, [- z
  67. Error_Handler();
    / X' r, V' d9 B: g8 H* V
  68. }, G: p: H2 S( A, ?
  69. if (HAL_CAN_Receive_IT(&hcan2, CAN_FIFO0) != HAL_OK)//CAN2 开始接收
    0 G. A+ N! R1 k# F% B+ z$ x$ J
  70. {
    - d1 p8 z8 b1 {) S
  71. /* Reception Error */0 F& j) F0 r6 g* Z: \
  72. Error_Handler();
    4 r$ J1 X0 {3 A" b1 k
  73. }
    9 h/ T) p6 H0 X! ~
  74. /* 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
  1. while (1)
    " W. `; q& L6 s5 w. Y& m/ I
  2. {5 N  e- P' h, W7 X1 c$ y& W
  3. /* USER CODE END WHILE */# R: K, v9 b" a. @5 k" y
  4. /* USER CODE BEGIN 3 */$ M% b8 W' h7 q3 A
  5. if (HAL_CAN_Transmit(&hcan1, 100) != HAL_OK) //CAN1 发送数据# v6 n: B* v6 _; |; @' H! J  X
  6. {
    8 [' Z- C9 {  W* }) U
  7. /* Transmition Error */
    . g" d/ Q* X4 U8 x0 a% e# z- e- R
  8. //Error_Handler();- Y" C  D# Z6 H& E/ ]2 N3 C) K3 o( h. [
  9. }; g( z* p1 N( p. d
  10. HAL_Delay(10);1 X/ q' K. h  t. N
  11. if (HAL_CAN_Transmit(&hcan2, 100) != HAL_OK) //CAN2 发送数据
    - w" c, J% x* |/ j+ A; v
  12. {/ [. b: `, @7 A8 w9 A
  13. /* Transmition Error */
    ! |4 w/ E" V: V9 U7 u
  14. //Error_Handler();
    ! v  l2 N$ I+ z7 f
  15. }3 K# O+ z1 x: e# q- B
  16. HAL_Delay(1000);$ n6 O9 E* ^  }+ \# X
  17. }+ T7 r7 d7 V- k2 b
  18. /* 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 LQAZTB4Z@52I~WRCHSP[CVQ.png & _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 [
  1. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)8 }, K; b+ C& a! N4 x- @% [; k
  2. {
    8 s% C0 J! P0 i, Q
  3. /* Filter configuration Error */3 u. ?/ P  `7 z: N4 k6 [7 I
  4. Error_Handler();. y% t: s4 S8 Z7 a
  5. }
复制代码

( q2 A0 e# _* A$ u0 j: W" [而 CAN1 设置过滤器代码如下:
  ^% H( q& T2 |: h; X
  1. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
    ) V1 c4 R& Z9 U5 V
  2. {
    9 x- r  q6 q8 |! ^: `
  3. /* Filter configuration Error */
    $ t7 c, e* m8 G) k
  4. Error_Handler();
      Q& |$ X1 _* S5 z" k6 e# B& l
  5. }
复制代码

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( }" _
5VG](@WM5EZV002R%9~{)VW.png & 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
A_N4{(~WCJC4RX)C8IMK~}5.png ; 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
XZ]QKL6KUZ)27@35L2JDIQO.png , 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 YS)V@HBBVU_%{3FK(3F7{KS.png ! 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
]IXZUCWY9I){Q25{A`PS(WB.png ; }: 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 ~(R%G0YAMA5ZV][WV{WLP5D.png
' }+ p7 {' v4 w+ X$ J
0 z4 u: S1 A, |* ?9 D4 T" n, L TKMH2{ZY7EKL6~A{J{J2R.png
) 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
  1. if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)4 T/ r' I5 j. v+ D) D  ?$ w
  2. {9 T' D' ~9 n5 x& o0 w8 H1 r
  3. /* Filter configuration Error */8 h0 N2 c+ C# ?6 ^2 U# {! A' y2 q" y
  4. Error_Handler();5 ]. p9 M; V1 J
  5. }
复制代码

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
  1. if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)% r0 C* @- K1 K* ]# F  e
  2. {
    5 G$ s0 s% F- m. E
  3. /* 32-bit scale for the filter */
    4 y" M: X: H: {; Y3 n) \
  4. SET_BIT(hcan->Instance->FS1R, filternbrbitpos);
    % p$ R& E; M; Y6 u" }6 |0 K7 k9 T
  5. /* 32-bit identifier or First 32-bit identifier */
    ; V8 o- }: t! r2 u9 \% i
  6. hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
    ; G( a. ?, k5 A0 |! z
  7. ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) FilterIdLow);. o9 W) N; Q+ b- U+ Y  k* P
  8. /* 32-bit mask or Second 32-bit identifier */6 P: ]/ D! E+ p6 _9 C
  9. hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =+ n% ^' {& [* B
  10. ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) FilterMaskIdLow);
    3 _3 P9 u! X+ D! C: m
  11. }
复制代码

9 @" g% A5 ~4 V5 `& q4 \% c% g4 O- B由上代码可知,设置的参数实际上是设置到传入的句柄 hcan 的示例 Instance 下的成员 FS1R,sFilterRegister[]中去了,查看这些成员的定义:: X9 m4 t2 d+ c% g2 q
  1. typedef struct" S: M: p2 K8 Q, F! k) V! D9 x
  2. {5 r* H# v5 f  M9 _/ A7 H' Q6 ?
  3. __IO uint32_t MCR;
    3 X! G8 w& \3 Z' w6 y6 _/ D
  4. __IO uint32_t MSR;9 B8 e; v5 m: T
  5. __IO uint32_t TSR;
    ! Y6 D" k/ @+ C$ ^3 k& ^
  6. __IO uint32_t RF0R;
    . K0 p& ^9 `$ X
  7. __IO uint32_t RF1R;' N2 E8 T4 y: L; Q, e& J. T( M8 T  J
  8. __IO uint32_t IER;
    1 ^, B1 F: B9 O
  9. __IO uint32_t ESR;+ \2 k! q! {: ~% t6 `4 @" V4 R4 Y
  10. __IO uint32_t BTR;
    0 c8 F3 ?: t1 o$ a
  11. uint32_t RESERVED0[88];* B( ]! s* [) h" m$ _# y3 V, m/ j
  12. CAN_TxMailBox_TypeDef sTxMailBox[3];' i7 s) E3 S  U( V. N
  13. CAN_FIFOMailBox_TypeDef sFIFOMailBox[2];+ W4 O9 p: v4 e
  14. uint32_t RESERVED1[12];
    " D, P# Y) d5 J7 a9 \% J5 E* f
  15. __IO uint32_t FMR; //过滤器主寄存器
    % Q8 c6 e3 o& m
  16. __IO uint32_t FM1R; //过滤器模式寄存器
    & z1 |8 z+ P5 N: R$ b' i
  17. uint32_t RESERVED2;
    ( X* Y5 {* A( o" U- q% H
  18. __IO uint32_t FS1R; //过滤器位宽寄存器
    ! H7 H2 K, i- @: E5 V* z1 l! F
  19. uint32_t RESERVED3;5 E! p7 o& R3 C
  20. __IO uint32_t FFA1R; //过滤器 FIFO 分配寄存器! y' c  l# g+ G, C: d( d
  21. uint32_t RESERVED4;! E) u. D3 l# m. Q, l
  22. __IO uint32_t FA1R; //过滤器使能寄存器
    7 U+ F8 \/ ~( \, ^4 _6 N8 x
  23. uint32_t RESERVED5[8];
    : {8 Y- E. [  D
  24. CAN_FilterRegister_TypeDef sFilterRegister[28]; //过滤器( j' n1 @3 ~$ J! [6 H  K  ?
  25. } 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 OTFV~}307SU6RTO_P4~D12S.png / 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
  1. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //使用 CAN1 作为参数
    $ p& V- ?7 b% Y- o
  2. {
    & i$ k4 b* d: I+ Z5 c  X! [
  3. /* Filter configuration Error */% ~; j+ z0 [$ }6 O/ |
  4. Error_Handler();
    8 t0 `$ Q/ u' D7 s
  5. }4 A: }5 X0 n4 P  f4 ~( p
  6. sFilterConfig.FilterNumber = 14;
    7 S  s) r1 Y9 `$ j# F, P* H& R! P
  7. sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;2 ~6 G) X/ v! R' H0 q" j4 l
  8. sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;1 H4 J! V/ j$ ~5 K' h
  9. sFilterConfig.FilterIdHigh = 0x0000;/ q/ o2 ^" q) G; r3 n2 j' Z
  10. sFilterConfig.FilterIdLow = 0x0000;
    ; D8 B' p/ S  R1 x+ J
  11. sFilterConfig.FilterMaskIdHigh = 0x0000;
    ) o: q" p8 E6 A% _
  12. sFilterConfig.FilterMaskIdLow = 0x0000;
    : L" o3 j3 d# c! O
  13. sFilterConfig.FilterFIFOAssignment = 0;
    - b6 f9 `8 b2 `
  14. sFilterConfig.FilterActivation = ENABLE;& S" H3 p  R7 k( v$ D& V6 F; G
  15. sFilterConfig.BankNumber = 14;
    9 T+ ?- p8 j. E2 Y/ k; y5 I7 W" w% u
  16. if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) //还是使用 CAN1 来作为参数4 j* T; o4 m; l; B0 M, V* e, |6 O
  17. {/ C- D4 E% W, v7 `3 h
  18. /* Filter configuration Error */
    4 E) P0 {+ l, I9 ~) [
  19. Error_Handler();% a" |2 `4 B9 Q! y
  20. }
复制代码

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
B0OH_3X0B2_L%CUTIZL{{5R.png
% 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
  1. void CANFilter_Config(void)
    7 r4 E. ?2 I/ @# _4 Z
  2. {
    ( I7 I9 ]& @5 I! N- n2 _
  3. #ifdef __CAN1_USED__
    ' ^% j! I4 }4 w/ Q9 s3 X& s9 [# I4 @
  4. /* CAN filter init */
    % R( u# D+ u( Z2 v1 r* |* e
  5. CAN_FilterInitStructure.CAN_FilterNumber = 0;
    2 ?7 |, m- O& h# h' L- ~' [( T
  6. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;- |* A" Z) e3 M
  7. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    / e$ {# O1 S! c' `% O. }
  8. CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;" K2 T% c. W7 w/ Q# t
  9. CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    5 ~. q5 L# V4 M7 t
  10. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;( e& n6 f5 W' Y/ e. F  q
  11. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    9 }, ~! X( ?: R& h
  12. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;' {- X/ ?: A( ]+ O4 U2 I+ Q/ y, q: M
  13. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
    ' S  Y: F1 d3 S
  14. CAN_FilterInit(&CAN_FilterInitStructure);
    . N$ u0 x+ ~6 a' D9 v/ F, ?, i
  15. #endif
    2 s0 X- @$ e: E* L2 c1 _
  16. #ifdef __CAN2_USED__/ X: I! d5 i" F2 E* T( P. t
  17. CAN_SlaveStartBank(14);' D$ b- m* }( C* s0 \: e: V" z7 ?5 `
  18. /* CAN filter init *// T9 t; T7 w, s' Z( g6 u. q
  19. CAN_FilterInitStructure.CAN_FilterNumber = 14;6 j! P' V# `8 U: I8 i
  20. CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;, y6 I4 v) |0 K3 u2 x
  21. CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
    8 a- H3 _: n* P: O$ [, U3 i
  22. CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;( \0 Z4 m# t" P, Q4 {/ U8 @$ g7 s
  23. CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    $ ^% t1 m3 b9 R. W# w8 Y
  24. CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
    8 ~1 K" f" i$ f( L0 l
  25. CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
    $ _# V. s8 `5 b/ C4 P4 U
  26. CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;$ n  {' ^9 P3 D% D
  27. CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;* g  P5 R. p  N
  28. CAN_FilterInit(&CAN_FilterInitStructure);
    ) M2 z# e( ?2 o7 u$ v
  29. #endif
    " {% {$ Z. G% Z5 ^% L
  30. }
复制代码
" u8 }; y8 h6 C% Y+ s+ a
在函数 CAN_FilterInit 中,内部自始至终操作的都是 CAN1,如下所示:" m3 x" g0 W8 x9 i& b* v6 m  W2 A
  1. //…5 q5 Y/ L$ s9 ]' l0 v) C: a
  2. if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)& b2 P( b3 a. P
  3. {3 D4 @3 ?7 Y% H* C; S1 M$ h  m
  4. /* 32-bit scale for the filter */% a. a2 e: ~% I4 l( I! P; G2 B
  5. CAN1->FS1R |= filter_number_bit_pos; //操作的是 CAN1 的偏移地址
    " q' C" Z2 `. B: t- u" F
  6. /* 32-bit identifier or First 32-bit identifier */5 v2 r4 o5 r3 G. ?! A) J
  7. CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =# f, X" {  o# |  U4 h$ T
  8. ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) CAN_FilterIdLow);
    ( i+ V. D: w0 d
  9. /* 32-bit mask or Second 32-bit identifier */
    / C) L$ S& p. v9 V& a# G, [; V
  10. CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =
    4 l" Y+ y3 l9 V4 e& e+ ^7 I
  11. ((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) CAN_FilterMaskIdLow);
    # u1 Z* v# D4 e5 W& T
  12. }
    9 {) }3 y1 k0 P) G, J( G" |+ F8 e
  13. //…
复制代码
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
收藏 评论0 发布时间:2022-2-14 21:54

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版