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

【STM32C0评测】7、CAN回环测试

[复制链接]
qintian0303 发布时间:2025-5-4 00:05
      控制器局域网总线(CAN,Controller Area Network)作为一种专为实时应用设计的串行通讯协议总线,在工业及自动化领域占据着举足轻重的地位。它凭借简单的双绞线即可实现信号的高效传输,凭借出色的性能与广泛的适用性,已然成为世界上应用最为普遍的现场总线之一。实际上在我的应用场景并没有实际使用过这种借口,接下来我们也是主要学习一下STM32这方面的的具体使用方法。
5 `' X( ^; O% n$ I& X4 V      本次测试的C092是支持FDCAN的,CAN FD(CAN with Flexible Data rate),即“可变速率的 CAN”,可视为传统 CAN 协议的升级版。值得注意的是,此次升级主要聚焦于协议层面,物理层并未发生改变。CAN 与 CAN FD 在多个关键方面存在显著差异:  p9 l- z, V( U8 E3 C1 X' t
      传输速率不同:传统 CAN 的传输速率相对固定,而 CAN FD 引入了可变速率机制,能够根据实际需求灵活调整传输速率。在数据量较大或对实时性要求较高的场景下,CAN FD 可以提高传输速率,从而更快地完成数据传输任务;
% l- ]/ _' I  G( }( i: P9 ?8 n. l      数据域长度不同:传统 CAN 的数据域长度有限,限制了每次传输的数据量。而 CAN FD 扩展了数据域的长度,使得在一次通信中可以传输更多的数据,减少了通信次数,提高了通信效率;
" B. y7 k& o/ S( j& @. @$ C      帧格式不同:为了适应可变速率和数据域长度的变化,CAN FD 对帧格式进行了相应的优化和改进。新的帧格式能够更好地支持可变速率传输和大数据量传输,同时保持了与传统 CAN 协议的兼容性;
- u( F  N, O  `  h  ^% b      ID 长度不同:CAN FD 不仅在数据域长度上进行了扩展,还对标识符(ID)的长度进行了调整。更长的 ID 长度提供了更多的寻址空间,使得系统能够支持更多的节点,进一步增强了系统的扩展性和灵活性。
, r) O1 Z0 d2 j( _- U8 ]6 G2 R4 m      我们看一下班次开发板的原理图:
3 m% l& h$ e7 L& ?4 z
1.png
6 |! w% ]" ~. T

" _" P) n6 i% Q0 ~. \& j      实物接口如下:) Z& l1 |) i# L# f* T% d- H
2.png ( ?% e+ [! O4 _2 a* H

' H$ ]$ B3 g/ ?- K/ R8 w      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。6 @2 C0 a3 w% Z8 G
      那么如何实现FDCAN的配置呢?
5 h7 h: b4 ]0 m; C: e" |5 N      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:+ X' _! F* q% r2 E6 b5 B  L
3.png
; R9 D1 o5 ~2 G; M& i, r
      启动FDCAN:5 `# D, \3 W# @; f

# O4 H$ M3 U' h& O" {
4.png
( |8 C! Y9 n3 _$ \1 s) F* M  ~

+ \; S$ `3 n% P4 n) Y2 ?! x+ H      这里没有过多的模式和配置,直接启用就好;1 _' g7 K6 ~" t. P
      注意修改默认引脚:0 v, F! k0 W9 [' q/ i
5.png " ^6 I; O' N* x
0 Q! F. ?. e% F
      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:
; a3 W2 L7 u+ G6 H2 ]/ `$ _            
基本参数, i, C2 T9 Y; `0 ?) j6 R/ @
Clock Divider
. c- u; }* t: I. B: B7 P- s0 i: n
时钟分频
: a2 G2 m  I# l5 c+ a: ?
Frame Format0 V* X2 F# q! e* n! Y( ]* _0 Q% A
CANFD模式7 o5 r% w. F, C$ Z
Mode
$ P6 m- M7 Z9 |3 P6 p9 V
正常工作模式: S1 l* d' A' R/ B8 V! Q
Auto Retransmission6 |+ Z6 e5 r. f: R
自动重传
$ H- T+ @% Q8 Q2 u; t% \; I
Transmit Pause
  Q/ B; j5 C0 [* U$ `
传输暂停6 N7 F, H) b. M! S6 @/ ^7 U
Protocol Exception; Z% ?$ ]2 w, \& m% k, r. \
协议异常处理
1 `, ^3 T: i9 c5 L
Nominal Sync Jump Width4 l9 C; D, y. D. @* k9 ]
裁决段同步跳转段宽度. Z3 _+ V% F  Q- L0 V. t
Data Prescaler
9 h% W8 Z5 n/ i
数据段分频系数
# @9 e: d7 @. {8 v
Data Sync Jump Width8 p1 v. V# t- G/ z3 s! s# O
数据段同步跳转段宽度
  F% p; O7 X9 w! b. d( @
Data Time Seg1
7 f/ ^, D1 v' P6 F# j
数据段时间段15 P& y/ o7 m: }2 N
Data Time Seg2
! T* q8 c, [. @
数据段时间段2
7 M% X+ ~6 n# l9 |- P, f' F
Std Filters Nbr
( a$ t8 k" q) a4 X" a
标准滤波器数量$ ~- D+ h/ w2 y# m4 D  i
Ext Filters Nbr
3 j! N+ t% ^: I% ~, Y7 o3 c" B/ K
拓展滤波器数量
7 w% ]: v! D' V+ W  j
Tx Fifo Queue Mode
# J% u8 w0 I. s0 f1 t8 y: t8 C& C
发送模式. D# X% ^  h0 [
              我们按照例程中的配置参数进行一下配置:( P! A; g! M7 Z
6.png
1 E0 F) j+ C* J# s7 v  o7 E
- Y- ~" M& I% V
      接下来进行比特率的配置,如下图:
8 t' J% R! e& x" }' z& O# d' O
7.png ! O1 ]' L) j% n3 ?  |) t; e8 E

1 U9 R" }; L- T      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。
; c1 [' C) Y% |( ^      依然是回环测试,我们将CAN接头短接:
' k" e2 U; p* C  L  ]
8.png 8 ^& K6 I( @" s+ v: x

5 P, C/ u6 h1 r      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:
- K8 O, S' F+ s- E( P3 B; ~5 o  m
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */
    ) a" F6 W7 Q1 d8 s) Y" ?( J
  2.   FDCAN_FilterTypeDef        sFilterConfig;
    - V/ Z' q, ?' r; K. I: V
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;6 G8 V1 E1 G' U
  4.   sFilterConfig.FilterIndex  = 0U;) I. m. n  G" s4 `7 o
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;
      N% s4 z! v' O; a0 |# D7 d
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    ! k- j# x. n# k6 p6 I: T
  7.   sFilterConfig.FilterID1    = 0x444;
      n9 g" m) v) o+ M4 D/ i3 H- F
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */4 I# X( b% u! _; `
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)+ c! S3 l* a4 R# ~
  10.   {( ^9 |' c( l2 o
  11.     Error_Handler();0 D$ u7 F1 L. y( p, e
  12.   }
    * E9 {4 Y* ^4 t, D$ y, Z
  13. ) D$ a6 F8 n+ D9 Z" x- G
  14.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */
    , {8 W7 A) v2 F) V/ D
  15.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;
    , E& A! [/ o$ P% r( c. `$ ~
  16.   sFilterConfig.FilterIndex  = 0U;
    1 q7 g9 s" q/ s4 {6 L. Q1 B+ g' w2 j
  17.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;
    ! W" m: q" a9 ^' Q& O3 u6 g
  18.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
    1 k; k/ |( F8 g& B
  19.   sFilterConfig.FilterID1    = 0x1111111;
    * g) C. a  Y) w
  20.   sFilterConfig.FilterID2    = 0x2222222;+ X- A% x8 g# T5 }
  21.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
    / g* N& n: ~# y4 [
  22.   {
    ) L( r" p0 i2 n# Q7 ^: g: p* `
  23.     Error_Handler();& V* s( p  o8 {* G! A( O4 M) \  j
  24.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:
* h, q* M/ Y# e$ |
  1. FDCAN_TxHeaderTypeDef        txHeader;
    ( D( Y2 {: _5 q; l9 z

  2. ) N- N6 R1 E: p; X
  3.   /* Add message to Tx FIFO */3 p8 ^6 X1 p$ d
  4.   txHeader.Identifier          = 0x444;
    2 R2 B: k/ }; k( w
  5.   txHeader.IdType              = FDCAN_STANDARD_ID;3 _6 ?) l3 p% A: b* L! _
  6.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;, N8 y, M3 J  c) C8 u" ]
  7.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    & A+ x  j" i8 A7 `
  8.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;- `: l- n9 ]# Z4 ]# M& T1 ~
  9.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;! {) U$ X7 h( E' `! ?
  10.   txHeader.FDFormat            = FDCAN_FD_CAN;
    6 S9 n( T/ ]  s& U( E$ u- t/ m0 ^9 E
  11.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;: I7 o. B8 U9 Z, L9 R% W- v- @3 X
  12.   txHeader.MessageMarker       = 0x52U;
    & V+ G9 n. R: p' A: V5 L/ P& r3 ~
  13.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)
    0 E& x. ^% G  T6 E2 r+ n% Y! Q4 E9 i
  14.   {2 w" C8 C2 y3 n% [, _
  15.     Error_Handler();  ^2 }* Y0 e& D& U; }
  16.   }( e' I/ ]2 z' d& m4 X! B9 X. y
  17. ( i, B- s# w4 w* A* q
  18.   /* Add second message to Tx FIFO */
    ( g) V6 h) j: |( X) ~' q
  19.   txHeader.Identifier          = 0x1111112;) v5 G" ?! `3 N) N  V9 n: }7 w/ k; e
  20.   txHeader.IdType              = FDCAN_EXTENDED_ID;
    - E) H! J* t+ y, L" t
  21.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    ) Q% e, r3 Q) Q: E# g# ?
  22.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    * G5 ?( ]: A5 B) A# Y1 ?$ p" ?1 K. {
  23.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;1 q7 c- h5 x8 z* U( I5 O& G1 H
  24.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
    & J0 q$ n8 G4 R
  25.   txHeader.FDFormat            = FDCAN_FD_CAN;  U. a- t1 o6 G  o" M  s) J2 ?
  26.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;6 X7 Q: n  B+ D, N+ v* J$ H* s
  27.   txHeader.MessageMarker       = 0xCCU;. ?; W9 \. U% n$ \% s1 x, g# m2 [, {) o5 D
  28.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)
    ! X5 N, V9 L+ ]9 ?! w- B, R( p
  29.   {, `% V" u  t; T
  30.     Error_Handler();
    # b. h$ I) `9 C2 O/ T) h- A
  31.   }
    # u6 }8 ^4 X+ n6 U2 ?3 K) W

  32. 6 F" w, A' d& |3 v6 v
  33.   /* Add third message to Tx FIFO */+ d- u& l5 R- l  q% x- E: `) l6 O% ^
  34.   txHeader.Identifier          = 0x1111113;; R. D; J  s* x; [$ L4 @
  35.   txHeader.IdType              = FDCAN_EXTENDED_ID;
    ) A6 y" s' O. G
  36.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    5 N+ p5 |/ ^. ^5 }& n6 z" Y; \
  37.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
      N0 x2 t# f6 Q" }3 [, a
  38.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;3 Q# g* \" s+ F) z+ D; w+ J' w9 {2 X
  39.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;" ~) t7 a+ r6 i. m- _$ R8 A
  40.   txHeader.FDFormat            = FDCAN_FD_CAN;: c' F! R8 B7 U; G- \
  41.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;' L- V/ V% |# x* v( f- j
  42.   txHeader.MessageMarker       = 0**U;' F9 @. g" X( U% E
  43.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)3 J9 p. M0 T! B& T) Z
  44.   {
    0 `  o( d2 h( h' g6 g8 c+ r
  45.     Error_Handler();
    : \3 o# ^/ t/ B2 {0 s5 u
  46.   }) Z+ c% g1 w6 }6 y+ y7 |
  47.     ; @# o9 H3 u; p+ v  L# H9 L
  48.     /* Get tick */% x. g% s3 v. @. t  f
  49.   uint32_t tickstart = HAL_GetTick();
    ) B% B2 x0 Q) X& m: u- v
  50. 3 G' j) M4 i2 y1 P( @
  51.   /* Wait transmission complete */
    9 ?9 g* x5 G9 {, p' e' V
  52.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)
    6 c& z! Q* j8 v" U8 q; q3 R/ f
  53.   {" O/ g# ]% C8 m. F3 @, ^/ \1 G0 H
  54.     /* Timeout handling */
    $ ]  T- W) l9 g% [8 f4 D1 h
  55.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT)
    # r( J$ ^5 B9 Z' S
  56.     {) ]: @4 ^5 `. m% _2 z
  57.       Error_Handler();
    9 }3 C+ s# d3 P
  58.     }9 N" q' N, \7 l+ Y  n0 ?; i* C
  59.   }6 s9 D; y" V* Y8 f# ?. p7 V+ d, n- P
  60.    
    % e+ @) H! N$ t1 g& G
  61.     /*##-4 Receive messages ###################################################*/
    ! U) u) M8 ]( h4 e% ?! U! F1 s

  62. # G* f( z; I7 A5 y2 s
  63.   /* Check one message is received in Rx FIFO 0 */4 ]# o0 [/ \( e3 s+ u0 f! M  A
  64.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)6 V: V; V3 _1 k" y. U  V
  65.   {
    & ?! H# X# A  A4 @
  66.     Error_Handler();5 _. ], o4 v' _8 N; m; I& S% I  Z
  67.   }# _) t' ~, K/ p% p/ F& g- q' ?% ?
  68. 7 J3 B) k- i+ q4 [4 {
  69.   /* Retrieve message from Rx FIFO 0 */
    5 d; X9 ?9 e) w  g( [2 A/ s
  70.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)
    8 |; v: Q% f0 s, O( c. f! B
  71.   {! f; L0 _7 ]9 K. Z2 U
  72.     Error_Handler();
    ( A2 @3 B) N/ z* t# ?9 U1 I
  73.   }
    2 ?$ I/ h! F% g6 [9 d0 l
  74. 6 ]1 Y2 m3 p& @
  75.   /* Compare received RX message to expected data */
    8 S: K  @, d& i, i: c4 `
  76.   if ((rxHeader.Identifier != 0x444) ||
    4 Z8 i# F- K, l  |0 i; R
  77.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||
    : z8 o& @1 `* w4 Q* F
  78.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||( s) |; v' X" X! X/ d
  79.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U)). M* Y! V% b1 C" J  g& O7 Y
  80.   {
    6 Y7 Y( m( y# a) G8 b$ {6 w
  81.     Error_Handler();' t" d2 P. h/ |0 G# N
  82.   }
    ' G8 V( R5 J2 G+ V  s) G
  83.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);$ s# J1 B" J& q$ d3 ?* H
  84.   /* Check two messages are received in Rx FIFO 1 */, t1 n# y' C0 V$ S: _  N
  85.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)% i6 B% W) Q) w. U
  86.   {& @* {0 p; D' ~" ~8 [" N( w' o: E
  87.     Error_Handler();
    - s# E" B: {3 B7 `( I4 Q3 j
  88.   }
    3 C) l+ f' G8 t, O' Z
  89. 2 i* K0 `) P$ X' i- t
  90.   /* Retrieve message from Rx FIFO 1 */% b, I( Z* j! c1 P/ w% Q
  91.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)3 g( r! A4 _. _; _9 Z
  92.   {! M- _1 D* K" Z* B
  93.     Error_Handler();2 T: O3 K) c6 D: z& m$ Y  ~1 p1 ]
  94.   }
      v! }/ F* i- f1 K' ]% ~
  95. ) C. M& r5 \; C- F: x1 J2 Q' R
  96.   /* Compare received RX message to expected data */
    * D( A0 f4 `) ]8 s1 k( c/ n3 H
  97.   if ((rxHeader.Identifier != 0x1111112) ||  I! P4 i9 l/ @, o/ a- l
  98.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||
    ! H( Y0 {! k2 R7 J
  99.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    . N. v# X& z& v) w3 I7 M1 W
  100.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))
    5 ]) u6 T6 \& B; F7 p7 A1 g
  101.   {
    % ]7 |; n* R. Z$ d1 o/ J0 q
  102.     Error_Handler();
    * ]9 T, ^) n# [2 V5 ~  {
  103.   }
    - E' A# n& L3 i, J0 L
  104.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
    9 R5 Z, R2 u5 }% N
  105. / I7 v/ `& c6 ?1 t9 Q' [4 L9 r
  106.   /* Retrieve next message from Rx FIFO 1 */
    8 Z' z: X8 O3 H' `( L
  107.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    4 W, F) U0 f+ {+ \; m+ A' K
  108.   {; F! e& ^3 z2 Z, Q( |" W
  109.     Error_Handler();2 ]* j) B+ U5 \5 x
  110.   }, N- A7 l0 w7 @: f
  111.   S( s# I9 I4 k7 }
  112.   /* Compare received RX message to expected data */
    4 B- Y: V/ \; t9 I
  113.   if ((rxHeader.Identifier != 0x1111113) ||
    / U& s8 b: A. @5 W( b& f, h( i
  114.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||' b" b1 j- I* c5 C2 `
  115.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    5 G7 R9 E! E" F0 c- B
  116.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))8 W$ D; A" J$ u5 Y3 N
  117.   {- l1 s( Q0 a$ w5 p2 e3 C5 e9 ?4 C) P
  118.     Error_Handler();
      T1 j0 [# T. R) g& [) a
  119.   }
    : I$ W' }( `- t4 ^& G: @0 n9 I
  120.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:1 N4 ^6 S, @2 h8 M
9.png / G3 z) b, D- i: t4 \$ Y
( _# W- ^- b1 c; `( n9 X2 Q
      这里多了一个C8,应该是串口出现的问题。+ q% ~% T5 N% D0 G/ A( b
9 B" M2 ]0 Z0 N  G9 j
! I. i: c6 S# v6 V0 d
8 O- N2 o. K+ y& n, w& S4 p

) X7 s2 `  X- b/ j- f5 t, l* i8 }/ c0 `! P2 b

5 I# r( U0 [& _- t" e" Q& {# L7 p9 j6 C* u! Z% z3 n
# H) f6 y$ [" U. D: {& X

4 O, H/ a$ u2 q7 I( c* o- M
0 B& m1 I) M; x% ~3 `8 A- b
& `9 E! J) ?6 v  o: d- `/ r; H
' E: p, q* s4 y# o* |
! u! Z( o( `2 H% k6 r. u
收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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