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

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

[复制链接]
qintian0303 发布时间:2025-5-4 00:05
      控制器局域网总线(CAN,Controller Area Network)作为一种专为实时应用设计的串行通讯协议总线,在工业及自动化领域占据着举足轻重的地位。它凭借简单的双绞线即可实现信号的高效传输,凭借出色的性能与广泛的适用性,已然成为世界上应用最为普遍的现场总线之一。实际上在我的应用场景并没有实际使用过这种借口,接下来我们也是主要学习一下STM32这方面的的具体使用方法。
/ s0 F7 B  G# ^0 f/ C      本次测试的C092是支持FDCAN的,CAN FD(CAN with Flexible Data rate),即“可变速率的 CAN”,可视为传统 CAN 协议的升级版。值得注意的是,此次升级主要聚焦于协议层面,物理层并未发生改变。CAN 与 CAN FD 在多个关键方面存在显著差异:
1 h3 D# r* [, U/ |1 a- [" C0 b7 {4 L      传输速率不同:传统 CAN 的传输速率相对固定,而 CAN FD 引入了可变速率机制,能够根据实际需求灵活调整传输速率。在数据量较大或对实时性要求较高的场景下,CAN FD 可以提高传输速率,从而更快地完成数据传输任务;* h, @9 ?7 j7 s& U  {
      数据域长度不同:传统 CAN 的数据域长度有限,限制了每次传输的数据量。而 CAN FD 扩展了数据域的长度,使得在一次通信中可以传输更多的数据,减少了通信次数,提高了通信效率;+ F3 p; F( Q1 k. L, \
      帧格式不同:为了适应可变速率和数据域长度的变化,CAN FD 对帧格式进行了相应的优化和改进。新的帧格式能够更好地支持可变速率传输和大数据量传输,同时保持了与传统 CAN 协议的兼容性;* J( C4 b' K  v
      ID 长度不同:CAN FD 不仅在数据域长度上进行了扩展,还对标识符(ID)的长度进行了调整。更长的 ID 长度提供了更多的寻址空间,使得系统能够支持更多的节点,进一步增强了系统的扩展性和灵活性。
) b  s- p* i+ I9 E  p      我们看一下班次开发板的原理图:
" Z: i2 x$ j: h
1.png 5 C; R: d! _: N: g2 w! ?* F
- p/ k3 [$ t# [7 ^7 K& ]& P
      实物接口如下:2 {" z3 o; d, \, `5 o
2.png 3 a' Z3 W( \' _6 O9 G0 _; Y  V) ~
) k# f+ l* G1 Q9 j: e
      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。, a5 w9 O0 k! ?2 e- N! U* K
      那么如何实现FDCAN的配置呢?
9 u: v- q2 `. u( j      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:3 `8 P% _! I5 x5 ^2 K2 X- K0 G
3.png

# q! ?( q9 k! P/ f( ~' q6 p" c      启动FDCAN:. g% g2 t* ?2 V& E/ M9 G: m; c5 H
5 F* G1 {: ]( D$ c1 C. h
4.png 9 `( z4 O+ {: K: d
% \/ {4 n( J! K# L' ?# z
      这里没有过多的模式和配置,直接启用就好;) F' @1 D6 r1 y
      注意修改默认引脚:
( u! x: N% p- z' K
5.png , {: z. B$ J5 A9 l0 M

! Y% s8 ^2 d+ u      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:
5 L$ l) R' w2 P" h# K0 G            
基本参数
7 S; C! ]2 U: w# M
Clock Divider  y' J8 ^; o2 M4 C- W  Y6 C; D
时钟分频8 ~  n9 U1 N" ^. B7 K
Frame Format: I% n( ~/ I5 z4 i5 z; `/ k" H
CANFD模式, ~& j# o6 G, m$ z) C* o
Mode
$ q2 D7 {) D6 z$ [; \% D
正常工作模式
$ I3 v; A$ I2 l
Auto Retransmission. H3 V) ^8 l( k3 Q" l
自动重传+ a9 L4 d5 l' R4 e9 d. u
Transmit Pause) n8 H; t0 j. C
传输暂停$ j( {  n# d* K
Protocol Exception% O$ |6 z) A/ C, F' K1 G3 \% F  f
协议异常处理& s' H# L! P* Q9 U2 l4 D6 e
Nominal Sync Jump Width  M( @% Q7 G, F: ]1 r1 E) d
裁决段同步跳转段宽度) K8 N$ [( k/ s' S4 }1 g
Data Prescaler& }$ ?4 M2 U9 u0 a+ O( x: I  @
数据段分频系数
7 _' Y$ }3 V5 F. M$ L; v8 H
Data Sync Jump Width1 A, Z: g0 L" n5 m
数据段同步跳转段宽度
; W5 ?; U* o) P  @+ {
Data Time Seg1
) U+ @8 M2 S- [( K! U5 h3 F
数据段时间段1
. k2 u# q  M4 _5 K) f
Data Time Seg2
' D; D( u, @6 J$ Y; Q+ {' U4 {
数据段时间段2) w, ?3 |' D2 i3 \" m
Std Filters Nbr
8 s' y0 I5 d: }/ a- a
标准滤波器数量
4 |% D- c9 o5 z3 T3 W7 m
Ext Filters Nbr
6 o# k' l0 v  a
拓展滤波器数量
& T7 o7 t; ?9 Z$ c. h2 K& m1 L
Tx Fifo Queue Mode
4 D! G) y9 W; v2 |/ j: W
发送模式. v, P; O) c2 h0 K7 }  L% w
              我们按照例程中的配置参数进行一下配置:) n7 c! Y$ j- ?; ?; j8 }$ q
6.png
8 C) J* A* M( ^3 F/ m  m4 [+ x

8 [; S( Y( A, z$ Q      接下来进行比特率的配置,如下图:
  a% L: D8 O' n
7.png
# e2 n) T7 A8 o5 ^8 I

) I: X% x1 Y' S' T9 F& C( D5 C# @      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。
- ?! |% R4 _/ M/ _& `: {      依然是回环测试,我们将CAN接头短接:
! C: ^$ l6 K1 u. `1 B
8.png " R( y+ Q5 a, N. D, j. B% Z

3 W; s* W& z5 c4 Y& U) n  `: O  K      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:
0 Q/ W) G0 s; o) _$ X/ R
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */6 Y* {0 O( P7 E5 {8 h, k: m
  2.   FDCAN_FilterTypeDef        sFilterConfig;; ?' ~" g! C' ^
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;- V& ]7 ?$ k! n4 M% Q) Q# @
  4.   sFilterConfig.FilterIndex  = 0U;4 \3 q0 r$ i8 j2 }6 z
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;
    $ c! o4 m: S4 }2 K% l, F
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;" o/ h# C  }7 T7 C, e0 y2 j
  7.   sFilterConfig.FilterID1    = 0x444;
    " m( T+ V9 V, n/ k7 I6 ^
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */
    5 j( A& }" h7 m2 v# w; R" e
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)2 q: o" B9 U! S, S# P
  10.   {
    0 K5 J# g/ z" s: p& j
  11.     Error_Handler();
    ' h0 j/ _! |/ G' r4 j( f
  12.   }
    ; W/ Q. Y- A4 Q& I

  13. : q  i2 J& V: q! O8 F
  14.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */' d! T5 _; V. q5 e+ H8 ~
  15.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;
    & a2 i) V. C" @' u3 A/ ^, h9 ~$ L
  16.   sFilterConfig.FilterIndex  = 0U;
    0 a2 c. Y: Y5 A; e* D
  17.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;" ]( e6 B: e4 [
  18.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;$ v+ x& d5 \" ?
  19.   sFilterConfig.FilterID1    = 0x1111111;
    ) N# S* h9 ]+ ]4 L: H( E
  20.   sFilterConfig.FilterID2    = 0x2222222;
    / H' M; T# }4 u9 H
  21.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
    " @9 K# k1 }) o2 W
  22.   {5 ~; _( n9 t/ B" Q. ]0 m
  23.     Error_Handler();7 E) M6 _$ z% Y
  24.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:
* R, }( m+ \. }2 l$ I% c& y
  1. FDCAN_TxHeaderTypeDef        txHeader;) X% [- B4 }8 b' f. l1 Z) @

  2. ; j# T) l  I4 W3 D
  3.   /* Add message to Tx FIFO */0 \( n: a/ l0 A" H
  4.   txHeader.Identifier          = 0x444;) a* E" ?' k( L& y% O
  5.   txHeader.IdType              = FDCAN_STANDARD_ID;, v6 w, Z+ i% o4 ?3 J" ]
  6.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;4 R6 j3 A# X$ v" b
  7.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    % b4 m4 ]9 U; n& b  B& w+ h
  8.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;/ ?; N8 V% u% w" ~+ {0 }
  9.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
    7 x6 y9 i! x+ e( e+ q% `2 P
  10.   txHeader.FDFormat            = FDCAN_FD_CAN;! ?- G2 v  w& }2 y) l
  11.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    6 e2 S+ S+ P! `: I
  12.   txHeader.MessageMarker       = 0x52U;' y$ N6 U. n& o$ S9 U
  13.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)
    " h, b7 E2 P6 n+ R% U
  14.   {8 I! x/ M) b4 ^, f2 Y
  15.     Error_Handler();
    7 e6 ^1 G) E+ ?8 r3 H4 u( h, X+ r
  16.   }$ S# @4 X% \. I' T: B( u- `' F

  17. " p: z6 }6 r( q
  18.   /* Add second message to Tx FIFO */
    ( T" J" {- D% |' |( @" j, ]  K
  19.   txHeader.Identifier          = 0x1111112;+ s! D, S3 |7 t9 |4 [; G
  20.   txHeader.IdType              = FDCAN_EXTENDED_ID;$ J1 N, {5 f6 m- |: w
  21.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;" b+ o5 }, b0 P( [+ Q# |7 S
  22.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    , R/ |% Z% T$ V/ K0 m! P1 Q" }
  23.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;- ]" k2 e7 S# y6 L7 M
  24.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;& g  c: k# ]5 y, \% I. A
  25.   txHeader.FDFormat            = FDCAN_FD_CAN;
    5 I( j* Y! ^' h, Y/ ~6 n: }
  26.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    4 O" Y  ~7 U( T( }3 G- \
  27.   txHeader.MessageMarker       = 0xCCU;
    ( n  q. R2 J5 k0 Y4 a
  28.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)
    ) x+ p. I/ ]1 S" ^
  29.   {# r# P7 L8 p: r" y+ E! W- Y7 t, h
  30.     Error_Handler();4 L$ y" w  U7 V! r  n
  31.   }
    2 E, N( Y$ ^( N' O5 d  E

  32. * C/ O4 O& \7 W1 ^: I" A
  33.   /* Add third message to Tx FIFO */& b: L" s6 ^+ |' m) J9 A
  34.   txHeader.Identifier          = 0x1111113;; B6 c) |8 [, Y5 l; E0 G
  35.   txHeader.IdType              = FDCAN_EXTENDED_ID;* Y/ b3 P5 i+ e* g' Q! J, Z
  36.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
      A7 S& U) E: Q* |3 R
  37.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;0 \( b) p% }& N) ~: P+ U) p
  38.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;4 e  z2 T3 K2 S" c: E( n* A0 ^
  39.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;! A* U4 V6 q2 z" q( ~
  40.   txHeader.FDFormat            = FDCAN_FD_CAN;+ C1 ?& Z3 X8 Z9 {& C8 C
  41.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    - v. l# i' Z( X8 n( p, p: N
  42.   txHeader.MessageMarker       = 0**U;" O* I' c8 ]6 o) j, Y- s
  43.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)9 E* j. V0 ~. F% S; S& b
  44.   {$ x6 w( C' s7 a7 B+ A/ X
  45.     Error_Handler();$ h2 E2 m7 B% C9 X, ~) L; H" A
  46.   }% I9 k' q( H0 c; x
  47.     ! R9 _+ w7 X; s! F
  48.     /* Get tick */
    $ A& @' R7 w/ F5 j
  49.   uint32_t tickstart = HAL_GetTick();
    $ \% z! C- o8 ~: M: Q

  50. ) E+ p  R% c2 Z! [6 ~
  51.   /* Wait transmission complete */
    3 U% ^5 z# p* h; K" E: v0 z
  52.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)
    6 O* M6 ?: Q9 T" d
  53.   {
    " L; q+ \+ w+ v7 j  e
  54.     /* Timeout handling */
    % n8 Y4 U! n3 h* q+ }/ L
  55.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT); q- \3 E# B& D  p
  56.     {2 Y) ?$ L" |" ^# T" t
  57.       Error_Handler();
    ( t5 C9 c& r+ a3 ~0 |; _/ B. @
  58.     }8 p' J/ \( u0 g/ e" t0 q
  59.   }% h) O# H, Y3 I, F6 P  \. U
  60.    
    / z* y9 x# B3 \  ~
  61.     /*##-4 Receive messages ###################################################*/
    $ Y4 \& B$ Y$ n. [# N1 U

  62.   ^  p' g+ F! M; t  ^5 b9 j  ?
  63.   /* Check one message is received in Rx FIFO 0 */
    3 o* z, a& w& \8 @& N: G
  64.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)" s9 j/ E6 X' Y+ S! l
  65.   {
    5 W" W$ I; }$ ^4 _. Q2 U+ V* R' H
  66.     Error_Handler();8 T9 D  i8 M9 g
  67.   }
    7 q: {7 X" t' ~, a0 U/ g( X

  68. ( `+ p" k9 N8 A: n5 F# E6 n
  69.   /* Retrieve message from Rx FIFO 0 */0 @- {: E  x; L; ~3 ]
  70.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)
    : F9 d+ I0 Z2 O' r) n$ K( ^
  71.   {
    : z/ K" l$ d5 d
  72.     Error_Handler();
    . h% f. @# }' e- M
  73.   }
    * s# g3 q9 r, `3 k/ O

  74. 8 W) m9 o  O1 g$ X9 r! o6 r9 f
  75.   /* Compare received RX message to expected data */
    : w1 c; G7 {+ `  C  E
  76.   if ((rxHeader.Identifier != 0x444) ||
    9 A6 s* I# ]' m* n& E
  77.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||
    7 J) |  K# }" }
  78.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    ! \" H, @1 C( E" d& _5 c, M. Y
  79.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U))
    1 T1 o7 P% U: R4 [* S# P
  80.   {
    # M5 w1 u7 T, j4 s
  81.     Error_Handler();" G0 Y/ ~4 v6 c( s, P7 M# g
  82.   }
    % H+ E! S# A6 ?+ K0 d
  83.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);' R, F1 N3 Y1 r7 A, T/ ~: ~: V
  84.   /* Check two messages are received in Rx FIFO 1 */
    + d" T. U8 \" J* d  K
  85.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)
    $ H+ N5 {1 Y8 ~* v8 ^
  86.   {% C% W. W* j; A+ Y; E6 L
  87.     Error_Handler();
    % x( \4 {) k, V$ Q! m
  88.   }
    , F3 V: d  Q% l) m2 L9 @( e
  89. $ H. g4 |! w& E) [
  90.   /* Retrieve message from Rx FIFO 1 */4 ]5 m" u) e. P! b) {- i
  91.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)- H# L  F+ [# F; W8 J% C
  92.   {' o. q2 `4 G$ d: u, J5 ?8 ]# ~+ h
  93.     Error_Handler();/ J6 ^  x/ D/ b
  94.   }# u% e- X/ J+ X5 |
  95. ( t0 W5 Z% \- w; l
  96.   /* Compare received RX message to expected data */8 n, M* t  x" Y% h9 b/ s
  97.   if ((rxHeader.Identifier != 0x1111112) ||
    / n6 \& d1 t, z8 _% B+ }7 H& r7 n# b
  98.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||
    . `  l: p' M" R( l1 ~
  99.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    ' t& ?  P# K# n) S# p% _
  100.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))% z1 z; }- F  r7 l; D; q" i* }
  101.   {1 y' ]; ]+ \) P3 ~3 c1 [5 H; K
  102.     Error_Handler();
    4 [3 F$ t4 g& w2 w
  103.   }$ ~& ~' J; b/ R: i9 F
  104.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
    : Z- d/ S% u# ~; K6 Q
  105. % m' E. ^9 |7 d: b. ?% w9 H
  106.   /* Retrieve next message from Rx FIFO 1 */
    4 @) q) g& T- t+ `
  107.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    + [* U9 R3 r- t- [
  108.   {) j+ x) S% J% j* ?
  109.     Error_Handler();/ X. z# V, p, H9 V) }% t, L
  110.   }
    0 E" `2 k+ w6 N1 A, Q4 h

  111. : h2 F+ v" U* P8 k# y6 n. ^( a4 Z1 M
  112.   /* Compare received RX message to expected data */+ {2 r8 {0 j  G$ W
  113.   if ((rxHeader.Identifier != 0x1111113) ||& {) e& A2 V- d3 \- W
  114.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||: r4 Y( m8 ]5 P* f1 {
  115.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    * s: c6 v7 y$ D) }" R4 Y
  116.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))
    & a7 M6 C- Z- J' [
  117.   {$ V/ B3 e: c( O  _- O6 z& y$ o6 Z
  118.     Error_Handler();+ X% U# P# y( j2 ?( W
  119.   }1 g5 D8 e) k3 y7 a
  120.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:
2 g  N* [. m' B% h8 N! T( i
9.png
* B" |* k5 `5 q+ L- v

& |( r& o; m4 U" K7 d" }* a/ d      这里多了一个C8,应该是串口出现的问题。' B) E' J! j9 E$ v: D$ G8 f6 G/ s

& \5 t( }8 ?5 a& i
! Z2 A- t* @: Y1 o" J- g
  _7 T/ p+ m. w- Q0 s
) x! A) i  b' U7 i" l
9 [( {1 H' ]2 a" |5 i" K9 D' _3 M3 r$ P! Q" R: P/ Y
3 a6 n1 H$ T: @. \
# P7 S1 I4 e/ k6 \- K: _

5 l% O( e; x8 y, z9 Y$ e7 D( i5 u
7 v5 q% J2 J  z0 W  ]% Q6 A% \: N1 r, S
& j) O/ D$ t+ v" k* G% v% N
! I6 J6 q( A7 G: c! g2 a
收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似分享

官网相关资源

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