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

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

[复制链接]
qintian0303 发布时间:2025-5-4 00:05
      控制器局域网总线(CAN,Controller Area Network)作为一种专为实时应用设计的串行通讯协议总线,在工业及自动化领域占据着举足轻重的地位。它凭借简单的双绞线即可实现信号的高效传输,凭借出色的性能与广泛的适用性,已然成为世界上应用最为普遍的现场总线之一。实际上在我的应用场景并没有实际使用过这种借口,接下来我们也是主要学习一下STM32这方面的的具体使用方法。
$ I' ~1 E: {$ g' [  t& p  R5 ?      本次测试的C092是支持FDCAN的,CAN FD(CAN with Flexible Data rate),即“可变速率的 CAN”,可视为传统 CAN 协议的升级版。值得注意的是,此次升级主要聚焦于协议层面,物理层并未发生改变。CAN 与 CAN FD 在多个关键方面存在显著差异:# l% a% N" H6 L3 H1 {4 H! U
      传输速率不同:传统 CAN 的传输速率相对固定,而 CAN FD 引入了可变速率机制,能够根据实际需求灵活调整传输速率。在数据量较大或对实时性要求较高的场景下,CAN FD 可以提高传输速率,从而更快地完成数据传输任务;) b9 B5 q. C. `' L8 o
      数据域长度不同:传统 CAN 的数据域长度有限,限制了每次传输的数据量。而 CAN FD 扩展了数据域的长度,使得在一次通信中可以传输更多的数据,减少了通信次数,提高了通信效率;
( D6 F4 x1 {) C4 c      帧格式不同:为了适应可变速率和数据域长度的变化,CAN FD 对帧格式进行了相应的优化和改进。新的帧格式能够更好地支持可变速率传输和大数据量传输,同时保持了与传统 CAN 协议的兼容性;
3 K2 b9 m, `: S      ID 长度不同:CAN FD 不仅在数据域长度上进行了扩展,还对标识符(ID)的长度进行了调整。更长的 ID 长度提供了更多的寻址空间,使得系统能够支持更多的节点,进一步增强了系统的扩展性和灵活性。7 k2 R6 F' m  Q6 H, h, ^6 I2 X0 {
      我们看一下班次开发板的原理图:& D# e) z& N# M7 {8 F
1.png % `5 H6 B, U" Z. s0 `
" r/ c: ^4 k5 f& y; \! G
      实物接口如下:
# [, t) R( A0 i9 x1 s1 l# T; t
2.png
7 a- d* F/ s2 t' Q( O3 {
! m' _% i" B5 H) u+ f6 H
      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。
5 D/ f! I% O* q      那么如何实现FDCAN的配置呢?
1 l% L7 \3 U8 c% n& v: R7 Y      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:) q: e/ s' F6 A5 j8 F( @! U
3.png

6 v3 {0 h4 R: C8 g; X$ _      启动FDCAN:' i! A" y4 ^% w; I
' W! f& `1 E( h% K3 \
4.png * S- q: E. U; n6 B; g

( Y7 W9 n0 ?3 U2 J0 X" O      这里没有过多的模式和配置,直接启用就好;
( j5 a6 [. W6 a; c      注意修改默认引脚:
' P+ Z- [1 i2 S5 s! f6 ~( ~1 c6 o
5.png
4 i0 i. c6 r  K' a( n# r5 O/ v

0 B; o7 t2 ?4 c5 n      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:
# T! f8 w( H$ x9 N3 O  F. x' `            
基本参数
, m; g3 s  B0 Q6 c3 D& G% m
Clock Divider
7 K" w; A# J1 O! u# V
时钟分频
6 [, _& l3 ~4 h8 N3 Y
Frame Format+ |: \% y/ X$ H+ y$ x) C
CANFD模式" ^! _1 v* q4 u% Y, S6 z
Mode% \5 p  i9 y; p! u$ S4 [, B: R
正常工作模式
' e+ `+ M8 T' m# Q6 j+ u( _! n! x/ S
Auto Retransmission; I2 V4 h- J6 ?) x
自动重传
6 ~+ d5 R, r* ]/ D0 D
Transmit Pause
! e: q5 p; C8 v
传输暂停1 o. N; R( X/ K  P; h. S
Protocol Exception. z& b( y" C, n" b2 A( G3 ^# I2 b
协议异常处理  R6 r3 }. L' @. ]" x7 ?& c! q
Nominal Sync Jump Width& c1 P# Q  C' X% ?) F# w) d
裁决段同步跳转段宽度+ x5 y0 H' }6 x' _
Data Prescaler1 ~1 R8 D* K. `: \1 @: O4 D
数据段分频系数
; \1 A; D. M, d- p
Data Sync Jump Width0 D! ^3 y8 E/ r0 a" Z- B/ }
数据段同步跳转段宽度
% b' S( r! |# Y2 a9 d
Data Time Seg1
& ^3 p6 @$ Z7 d6 @8 u/ ]# J8 I
数据段时间段10 r: T/ Q' M4 D4 b- ^
Data Time Seg2
- `( x" g# b' u; o0 K
数据段时间段2. Q: ]1 G9 b. G- W
Std Filters Nbr
/ r- T  k% S+ k* Q7 J5 s* V
标准滤波器数量
! p' r/ U6 V& z* N$ y  ~/ c
Ext Filters Nbr
. m7 U5 h9 W8 \+ A/ G) x; Z7 f
拓展滤波器数量6 }) m) u" K0 }- |! ?
Tx Fifo Queue Mode* Q- k: M5 H4 r
发送模式$ a; r" ?0 ^2 p' j0 s$ p0 W
              我们按照例程中的配置参数进行一下配置:2 l* l: s& [0 v# e/ p! q, @
6.png
4 t3 N2 e0 v+ r* g0 w, L1 s

! }; q/ Z2 g2 k- A      接下来进行比特率的配置,如下图:
, _: P9 K5 O5 R
7.png
" a, |3 C0 ]  C* R5 H% N
) h$ _6 l  F3 J
      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。
9 V. |' Z. T+ I9 c& Q      依然是回环测试,我们将CAN接头短接:
8 t: g% O# n# b! G4 Z
8.png ( h/ L( Z/ ~. ~/ m  z: N1 M4 f

8 B3 q0 H( e* m" ~* \5 u9 M9 E      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:8 c) j+ [9 ~0 X
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */0 j3 h8 I+ @7 k2 G! C8 U. S! Z
  2.   FDCAN_FilterTypeDef        sFilterConfig;
    * J: w5 C% O) ^% h
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;0 |$ ~# l# ^( Q" n. N# U' J
  4.   sFilterConfig.FilterIndex  = 0U;2 k" T% X0 I; P+ I0 p3 G
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;+ q( F6 c( a+ F! \) `1 [
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;" |* N5 z- g' g
  7.   sFilterConfig.FilterID1    = 0x444;- P0 b1 d) V7 M. L$ R0 J
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */
    8 {  C7 P( O/ m$ d
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)7 a" ~" k! Y. E3 ^5 S
  10.   {
    0 Y' \3 r$ G: j
  11.     Error_Handler();& P1 V' A  T" @( t. f5 p+ A5 U
  12.   }
    . @4 u# G# S3 M4 [8 P8 R! i

  13. 3 y  g- o" ?* s1 F  U
  14.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */
    3 b( y3 r  u, i3 s) c
  15.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;
    ! @9 J8 |6 [. b1 E6 ~  I
  16.   sFilterConfig.FilterIndex  = 0U;1 K& d. U& L* f8 h* s2 `
  17.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;
    : O7 |% Q, r. ^; ]
  18.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
    : X( C: o4 N7 ~! A2 H$ y9 ?/ w
  19.   sFilterConfig.FilterID1    = 0x1111111;
    . T8 q) J* x, r9 e& w' n8 i
  20.   sFilterConfig.FilterID2    = 0x2222222;
    # e! j2 h' f8 P) v
  21.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)  P7 s6 R4 Y9 N+ v7 C( X; K# Z
  22.   {
    7 f% M/ Q* B, q# ^& u- y& E' p! \
  23.     Error_Handler();& V0 y% L% F3 k- B( n+ i
  24.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:1 k, t; Z6 ^& x) a
  1. FDCAN_TxHeaderTypeDef        txHeader;+ `7 ?* `$ U0 f$ J
  2. ) r, t# h; d  i  O6 q+ c! v
  3.   /* Add message to Tx FIFO */) Z0 x( w' z) E0 W/ ^  C
  4.   txHeader.Identifier          = 0x444;: l6 h$ @: E# B
  5.   txHeader.IdType              = FDCAN_STANDARD_ID;
    ! O( ]  A7 m' i& A$ K8 Q+ }
  6.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    : R& O  p8 y- h+ j8 V
  7.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    ) K9 f0 R/ F6 U, [
  8.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    % m8 @, \. z. w# Q. Q7 B6 V
  9.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;& v9 t$ l2 H8 B- a# a, l4 M, }) O; z
  10.   txHeader.FDFormat            = FDCAN_FD_CAN;
    9 A! t" n* f. C3 ]) `5 R( W
  11.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    ' w5 E# j# z( t- F3 U. V  Q/ k
  12.   txHeader.MessageMarker       = 0x52U;
    0 `& r8 v% ~8 E
  13.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)' I8 ?% T* z1 X5 {
  14.   {' q6 J: {% C3 i( R' ]* N
  15.     Error_Handler();+ k, w) |  ]* S/ _* x4 j
  16.   }9 x' m$ n1 c; E. k- n
  17. 2 o$ y+ ?. q0 v6 J% w4 q
  18.   /* Add second message to Tx FIFO */6 b  v* i8 F: j) ?: i* ?. n$ N# k% c
  19.   txHeader.Identifier          = 0x1111112;
    7 a1 X3 ~. p0 u3 S# A/ u
  20.   txHeader.IdType              = FDCAN_EXTENDED_ID;0 b) k& }& k- Z; N6 s& c$ z* b
  21.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    ' q; j. k6 f) f* v/ e3 h4 W  J
  22.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;; U$ j$ x! r$ o
  23.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
    ( k0 \2 O! B  X/ _0 v, M2 V* {
  24.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
    4 P. C# A5 [1 h* W7 _6 X, g! N( m
  25.   txHeader.FDFormat            = FDCAN_FD_CAN;
    . h5 j0 k9 l+ X
  26.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    * ~# b) y% w9 U
  27.   txHeader.MessageMarker       = 0xCCU;8 @) k8 w& \- B- C: Y
  28.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)6 d. N7 H! d9 s
  29.   {
    0 \, p) |% `6 u" p
  30.     Error_Handler();  h/ Q- Z# r/ P; c( [
  31.   }5 _5 {+ z* _! I# Z
  32. ! g* U9 o/ b8 U3 I
  33.   /* Add third message to Tx FIFO */
    5 c: W9 N; G( g- p, Q1 }
  34.   txHeader.Identifier          = 0x1111113;
    ) f( z3 F# d( z4 f, l- ?1 j1 l2 `
  35.   txHeader.IdType              = FDCAN_EXTENDED_ID;
    6 Y3 ^4 k  e1 I4 S) w7 ]. n! F# e4 g
  36.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;* D  U: }- g6 N2 d' B
  37.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;0 D: l' D% M4 U% J( w9 h( V
  38.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;. ^! y7 g3 y3 _9 s0 }! |& Z
  39.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;
    9 _) X; L+ w6 G- `% j% P
  40.   txHeader.FDFormat            = FDCAN_FD_CAN;
    $ h& A) [7 @5 A  O4 Y6 g
  41.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    7 T& |# K, Y$ r" u6 p
  42.   txHeader.MessageMarker       = 0**U;
    1 V  v9 b$ t; x. z7 v
  43.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)
    ; F5 v+ W: D2 G5 t) P2 j
  44.   {
    ( B# ~" v& j0 d  P% L4 q
  45.     Error_Handler();3 L* `. P( j# O1 g8 t! x; D
  46.   }" g- o5 Y9 x2 P" g
  47.     ; E4 U) c$ I" J$ ?
  48.     /* Get tick */# D* @- |! i# o3 k5 G+ @) i
  49.   uint32_t tickstart = HAL_GetTick();2 k2 f0 \1 ?3 a( r' W0 R

  50. : t, B6 j, u3 q2 H% k8 u/ a
  51.   /* Wait transmission complete */
    " l* H8 D% ]; H3 u
  52.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)0 {7 x, x- e- u  ?# W* i0 R4 l
  53.   {  |% g6 R2 O0 L* K  ?; Z/ g& \7 J
  54.     /* Timeout handling */
    ! e" o) p. k) t" t. B  `
  55.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT)
      Q( C- ?: F: A4 V& U! F
  56.     {
    7 H2 ]9 i# C4 \( a
  57.       Error_Handler();4 ~3 x; c9 g1 ]9 B3 b! y
  58.     }
    ( f* j6 M& u& ^
  59.   }1 z3 a; s" @8 p+ @3 Q+ S4 [+ m
  60.    
    * G: ^1 S9 Z1 {! p
  61.     /*##-4 Receive messages ###################################################*/  l) ~2 h# [6 A+ Q" U; K

  62. & m5 v/ ]$ F9 O- ^2 W
  63.   /* Check one message is received in Rx FIFO 0 */
    ; z; ~! w! d0 {! }7 _  t) N4 m! T
  64.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)
    & a# O. h9 y5 [' p
  65.   {; O9 Z& O/ R- q/ D! Q
  66.     Error_Handler();5 t0 Y% w3 a3 |5 T6 z
  67.   }
    0 N0 ~4 |4 I5 _# `
  68. . K& l8 Y0 Z9 V. C) B3 B/ a
  69.   /* Retrieve message from Rx FIFO 0 */
    5 O) e. @- L" z( c2 U) p
  70.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)0 v* `+ x$ K* g8 |. \
  71.   {
    & A7 f6 Y: H# j5 V# T- K6 j
  72.     Error_Handler();; r+ ^" z4 ]" o
  73.   }
    # r, T5 I7 s$ J  s  I/ O$ S
  74. 6 t5 b- J3 O0 E. L* }. b4 b3 [! z
  75.   /* Compare received RX message to expected data */( D" @) k! D$ |7 C: r- H
  76.   if ((rxHeader.Identifier != 0x444) ||2 k, t% d7 r1 l. r7 j3 A
  77.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||9 U9 B  T  F) C* v( n8 ]
  78.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||" b% g: o! z. l) I* e
  79.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U))$ u9 T" {/ ], ~% w4 Q# C' ]
  80.   {& p2 Q, g+ o/ F* }2 O' r
  81.     Error_Handler();' l8 I+ M% q$ H' I$ Y& q
  82.   }
    # Q4 S% D' p0 y3 D
  83.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
    / w7 A# U2 d+ N, W, O2 T1 u
  84.   /* Check two messages are received in Rx FIFO 1 */; G6 o5 p0 v& _% b
  85.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)
    1 M0 v0 \0 ?4 r8 @& C- F
  86.   {4 O0 V. R# V) w+ {- l. G
  87.     Error_Handler();4 q- P7 W: B* ^# y
  88.   }
    * A6 h9 P) `- L' G9 K3 N. u

  89. 5 I8 y. a: H; g# j/ Z9 x- d3 D# N
  90.   /* Retrieve message from Rx FIFO 1 */
    0 _) p. K7 |4 R$ _( S
  91.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    / ~2 I4 ^" F( o. l+ ^
  92.   {' W5 @/ R% R( Z1 H; A' f/ q
  93.     Error_Handler();
    , q) I5 S5 |0 h$ y0 [% q
  94.   }2 W7 T# ^9 b# L' {
  95. ) s& t( S8 {( {9 v
  96.   /* Compare received RX message to expected data */
    ( j9 }( [6 i* U$ w! {3 g" ]
  97.   if ((rxHeader.Identifier != 0x1111112) ||
    , l2 f" t5 z0 E
  98.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||7 x+ b$ ^# W5 K* M
  99.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||3 x7 |2 \3 I' X1 C" j
  100.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))) _6 l. S/ l' x  z' k  S9 O
  101.   {
    ) K; d5 Z3 ^" r% W- X* ^
  102.     Error_Handler();
      u3 M* ~2 D! x( ^- o! |
  103.   }
    , `  l( d- P/ Q: g9 G, B) h" z) X
  104.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);, n* w; Q& p0 c; c: _

  105. 2 P( g1 {3 j; Q
  106.   /* Retrieve next message from Rx FIFO 1 */
    - U+ G' _( n; x$ B! R3 X8 d0 R: U7 B
  107.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    9 m0 H, R! w9 L! v$ c$ a, @; }/ ?' k
  108.   {& |$ V; ]6 P; q
  109.     Error_Handler();
    * ]# V/ Z. I  f' d9 [1 V" J; g
  110.   }
    9 k9 x# H. r" X3 i% c
  111. 2 a& A& t* j7 }1 Q6 L2 P+ {
  112.   /* Compare received RX message to expected data */
    ( C* {' |9 X+ [( d
  113.   if ((rxHeader.Identifier != 0x1111113) ||
    - p! c) }1 t0 E/ [9 `2 {, O
  114.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||$ M! |( u9 ]4 {9 \  `9 l
  115.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    : s4 L+ t) X4 F% k8 {8 a4 f
  116.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))
    3 j8 A6 R6 Z( |2 A. S
  117.   {
    ) g, H9 ]1 {5 z& H1 i5 c3 h
  118.     Error_Handler();
    # {; M6 l, U/ i( A) [! O1 w0 F/ |
  119.   }
    9 p5 n# U* C: u& U/ R1 D
  120.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:5 s# s6 _$ @  f8 L1 [
9.png
; T$ J4 L: m7 k! |

; u  z" {4 i0 p8 q0 j      这里多了一个C8,应该是串口出现的问题。! G% B/ n+ M: Z
- D0 T, z6 ~$ u$ V, D7 W# I0 ^
; f  T- E6 _1 y6 V  g3 J% P

: i& m8 Z& y- a( h: s+ H6 V, n; m
( w  c0 w, T' l1 O" m& f
8 C& H: d$ i0 }( k
! h+ p+ n$ l$ F/ M
4 @. Y9 s3 F8 e1 a5 e
/ Y* n7 v6 d$ h. a5 ~& r: R0 N- T( ~2 q% F2 j, `1 L9 x/ J. e" R

4 b; D5 s4 y! J! @8 Y7 q( _" Z$ j3 M  p  j# h2 H* c* y

) X3 L5 d  \/ O! O9 a7 e/ Y
" ?0 ~, k9 r# l3 N
赞 收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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