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

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

[复制链接]
qintian0303 发布时间:2025-5-4 00:05
      控制器局域网总线(CAN,Controller Area Network)作为一种专为实时应用设计的串行通讯协议总线,在工业及自动化领域占据着举足轻重的地位。它凭借简单的双绞线即可实现信号的高效传输,凭借出色的性能与广泛的适用性,已然成为世界上应用最为普遍的现场总线之一。实际上在我的应用场景并没有实际使用过这种借口,接下来我们也是主要学习一下STM32这方面的的具体使用方法。
- c# |: f; L: X8 `8 N3 c      本次测试的C092是支持FDCAN的,CAN FD(CAN with Flexible Data rate),即“可变速率的 CAN”,可视为传统 CAN 协议的升级版。值得注意的是,此次升级主要聚焦于协议层面,物理层并未发生改变。CAN 与 CAN FD 在多个关键方面存在显著差异:
. a' F6 ]# P) y- y0 q      传输速率不同:传统 CAN 的传输速率相对固定,而 CAN FD 引入了可变速率机制,能够根据实际需求灵活调整传输速率。在数据量较大或对实时性要求较高的场景下,CAN FD 可以提高传输速率,从而更快地完成数据传输任务;
1 T0 {+ z& R6 x7 h! v- u3 ^- [0 W      数据域长度不同:传统 CAN 的数据域长度有限,限制了每次传输的数据量。而 CAN FD 扩展了数据域的长度,使得在一次通信中可以传输更多的数据,减少了通信次数,提高了通信效率;* @$ s$ K+ w: I3 D
      帧格式不同:为了适应可变速率和数据域长度的变化,CAN FD 对帧格式进行了相应的优化和改进。新的帧格式能够更好地支持可变速率传输和大数据量传输,同时保持了与传统 CAN 协议的兼容性;# s3 r$ D% X0 O: B4 P
      ID 长度不同:CAN FD 不仅在数据域长度上进行了扩展,还对标识符(ID)的长度进行了调整。更长的 ID 长度提供了更多的寻址空间,使得系统能够支持更多的节点,进一步增强了系统的扩展性和灵活性。! p" }1 k: B5 \
      我们看一下班次开发板的原理图:' t3 r, b0 k- f' c  T4 G6 h
1.png 0 J4 P7 B& l) h  D
( X/ a$ X+ f# H$ I
      实物接口如下:: p) [' y* N1 E* L5 ?
2.png ( G9 W& M$ W$ F/ J  P

, v6 `% ?/ z: g; x7 Z& O3 @8 T      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。* i" X+ }) d" b9 H; r0 C) C) U) q
      那么如何实现FDCAN的配置呢?& N0 U: K  u$ A6 p
      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:
- @' b* B- z4 Q/ l! D& l& J
3.png

7 g% C6 H0 f* s5 e4 B- _      启动FDCAN:
8 w* {8 b4 p* S6 v  }" z7 _1 I. y! M' w) |: A
4.png , Z: p" H4 z! l8 h
5 A7 V/ L4 Z) D3 b/ Q: e3 O
      这里没有过多的模式和配置,直接启用就好;0 [' d5 ^* w* n# Y' v9 E% b" z- t
      注意修改默认引脚:
; y& J& Y3 p3 H$ B0 ]- U
5.png
( S! w! Z% X" C& t" R+ g* K
6 B8 Q' a* T2 J7 O# z0 s
      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:
# L" P1 Q: R4 f9 `  \# U& k+ P            
基本参数
: P! A$ w1 A- h' I
Clock Divider! n0 K1 s3 w2 B" t% J! c; G
时钟分频2 N3 d- M8 a' ^% D
Frame Format
; n# i/ {: |9 F7 M
CANFD模式
) C0 q) I5 g- f& E, d9 R8 X* w
Mode( E8 h$ }# d6 G+ A  L- ?) U
正常工作模式! Z7 ^) P# g! j" ?$ O
Auto Retransmission
- p: y$ x# D3 i! k; E* V( Z
自动重传/ l. ~  j1 e# b/ G+ C
Transmit Pause
7 I: ^( w, ]6 x3 Z5 @
传输暂停
0 i# e' N- ]8 ]$ ^( h" Y
Protocol Exception0 N2 n9 i, a2 P) E& D/ [
协议异常处理* L0 B. S8 Z; m  m/ a4 ?. s% p
Nominal Sync Jump Width
& ]4 V: K# g: X5 X; v
裁决段同步跳转段宽度2 T8 l: f4 q% @; w8 B. C- H9 w3 W  B
Data Prescaler! `% p* A( n- j
数据段分频系数( M$ e  \$ X, v2 ^; s
Data Sync Jump Width9 l. C! W  p9 s- w7 ]$ O
数据段同步跳转段宽度
! T  H4 |$ |' K9 [, Q5 v
Data Time Seg1
" W$ H* t4 x% G
数据段时间段1
6 D+ J$ V+ W9 h7 f) P
Data Time Seg2
) |/ P& g/ i3 X8 P4 x
数据段时间段25 n6 i5 {$ [2 Y+ R! q: e4 B# Z4 Y% s
Std Filters Nbr
5 r& w! r, c0 a9 d" d+ d' T
标准滤波器数量
# `: G: {8 H3 n9 z: d. n  U
Ext Filters Nbr$ F& D7 d$ e# ^5 f5 g
拓展滤波器数量
/ N1 T  T+ u5 @0 \3 H( s& |1 x
Tx Fifo Queue Mode6 O# p- |3 I+ J' `
发送模式2 B8 y# u3 u" O2 X
              我们按照例程中的配置参数进行一下配置:+ |* y0 c* A7 r6 a8 L1 C
6.png
; K2 y0 ^! j1 {6 x7 u+ e* o0 U7 R

; W  z* i! f6 D8 ]( Y      接下来进行比特率的配置,如下图:+ M7 G9 w5 E/ e
7.png   o2 A. o$ t9 j& }/ Q1 Z
- W6 g$ P) K9 X) W
      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。1 _5 e$ V2 [- q: k
      依然是回环测试,我们将CAN接头短接:% W8 Y& I; z6 N7 x* O
8.png , D! Q' v6 E/ v* `  K! o# m; q! {

& }2 O0 ]; Q8 G, @6 _" |, i0 n7 }      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:0 v, M  a* \/ I3 ?  v5 o. M
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */
    $ M$ }% f# t, P+ r4 J  w7 q
  2.   FDCAN_FilterTypeDef        sFilterConfig;) ^6 [( C* |! [9 r7 }
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;
    . o$ V( \1 I# Q" p" |* |6 V
  4.   sFilterConfig.FilterIndex  = 0U;0 j0 D) o3 E" k' ]3 P
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;$ n1 M! @, E7 q$ p
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    8 w! z( m; H* n1 y. p& e  x
  7.   sFilterConfig.FilterID1    = 0x444;
    6 Z4 j5 ]. u5 B' w" K# X
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */
    / q9 y7 J) }& s7 \+ [
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
    * r# @1 V) T9 _# E0 E6 Y, z
  10.   {7 u. f" C# O3 c, ^
  11.     Error_Handler();' I6 S* s; Q7 P
  12.   }
    ( P& c& U3 g5 h6 F& c
  13. 8 D7 ^. ~! v0 u: J; m
  14.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */" G- g5 j' ^% ?" [: F# W5 }
  15.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;/ K" Q1 J, n) `8 _
  16.   sFilterConfig.FilterIndex  = 0U;) k2 x+ T' T0 E! H) ~& d3 W
  17.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;5 `* F" v% h5 l6 x1 i) R' B: j
  18.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;% [' F" [* w6 F6 s, R4 H& [
  19.   sFilterConfig.FilterID1    = 0x1111111;8 ]2 |  L7 [! G/ x
  20.   sFilterConfig.FilterID2    = 0x2222222;, ^  t* i" Z3 J# h; D2 j
  21.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
      q7 H9 U; }5 g4 _" i
  22.   {
    $ U' k, j$ q& ?6 j& }
  23.     Error_Handler();( d2 E3 W. D) o/ m9 q: C
  24.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:. t, f( {- w& m+ H
  1. FDCAN_TxHeaderTypeDef        txHeader;3 Z1 B+ L8 ]/ @  J- K& v4 D# w1 ~
  2. ) _( z& H$ b# i; K  Y+ F: \$ v6 S4 O
  3.   /* Add message to Tx FIFO */
    7 e2 i& w: v; k6 X
  4.   txHeader.Identifier          = 0x444;) q) M  @1 M3 j. h
  5.   txHeader.IdType              = FDCAN_STANDARD_ID;
    " l7 t) e6 h7 e
  6.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    5 N$ M; x' k- W8 T. r
  7.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;9 {: \9 F% Y9 F& T1 g. ~
  8.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    9 U8 A, p/ j$ o6 g( X0 Y" R
  9.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;, R5 N( W. f7 W
  10.   txHeader.FDFormat            = FDCAN_FD_CAN;
    2 B# _: p: Z3 C) J5 A
  11.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;; H$ |9 i6 p8 i, p
  12.   txHeader.MessageMarker       = 0x52U;( U3 K, |  S# \$ \1 i
  13.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)
    ) i+ T9 H3 l$ w/ L* \
  14.   {# h8 Y/ C- A4 n. f3 X
  15.     Error_Handler();
    5 h' y9 s9 b8 C: r+ N7 s
  16.   }  g/ }2 o" z- {/ G

  17. ! A5 L+ u. G! _2 w5 s: g; b" W
  18.   /* Add second message to Tx FIFO */
    $ ]4 X7 i' t6 E1 O
  19.   txHeader.Identifier          = 0x1111112;
    : @8 }! C# M" a& o. O" w5 K7 H3 M
  20.   txHeader.IdType              = FDCAN_EXTENDED_ID;, D& N4 A& |5 L' E
  21.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;" e& v" O* n, h1 {9 _
  22.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    , B8 C. n3 t- X" Z) n+ {- |, Z
  23.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
    : L2 P' f% P% e0 I
  24.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
    7 W+ M& F! H5 r1 y- D& m5 A7 x
  25.   txHeader.FDFormat            = FDCAN_FD_CAN;
    - }: I8 t( s( {" ~5 c& M+ ?
  26.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;% _0 `: M( d2 t) {* s
  27.   txHeader.MessageMarker       = 0xCCU;  Q, L* z4 ]$ z: o9 S* k1 H, N
  28.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)
    3 Y: n3 s0 c/ o$ X& H1 o! \& W
  29.   {
    + }' }! g/ v$ A: r: C
  30.     Error_Handler();
    5 d; O! T) y% I; e6 P( h, a& n
  31.   }) f6 w2 g: ?9 Z" Q4 h) r8 w8 y
  32. ( E2 s$ b, r. X3 U& E1 |% u0 b
  33.   /* Add third message to Tx FIFO */
    , M; A5 K! P/ u1 B. G
  34.   txHeader.Identifier          = 0x1111113;
    7 e5 m: e* s5 A( c/ m$ G
  35.   txHeader.IdType              = FDCAN_EXTENDED_ID;
    + u% E/ Q1 y( N! c, a
  36.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;4 t  [0 v' W. |" H) J
  37.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;+ g; T: `: V3 s7 Q9 h0 o
  38.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
    . \. [! I- \1 Y/ \, ~5 T
  39.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;
    9 f( m$ S8 W0 b/ q- j
  40.   txHeader.FDFormat            = FDCAN_FD_CAN;
    & E9 p9 w( [% @3 s
  41.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    . X  s  x. l6 V6 k
  42.   txHeader.MessageMarker       = 0**U;( v( \( G1 L& [
  43.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)+ @/ `( r' h6 @0 i+ O& X
  44.   {
    % j2 G$ K' C$ x: l
  45.     Error_Handler();! |! [1 ~5 i. ~
  46.   }
    % U/ a4 N( F  W! Q) p
  47.    
    / N; U, ?. T& M6 l8 z' A
  48.     /* Get tick */$ E7 ^' _% F2 i- _! g" B' I
  49.   uint32_t tickstart = HAL_GetTick();
    * {  ^, A: ~3 T9 K) T
  50. . L8 [) K' N* Y% q2 i# c% D5 Y5 Z! G
  51.   /* Wait transmission complete */* s, V- i, E( b
  52.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)
    ' g: g/ @2 @( t* C" z# R8 F
  53.   {
    ; V+ D% b. i8 H; S+ [! g  e- n
  54.     /* Timeout handling */
    , j1 U8 Z2 V3 ?5 z2 \* X; R
  55.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT)/ ?+ ~9 r  q: T
  56.     {0 o7 `0 E4 q/ c3 K8 ?: r3 a6 Y
  57.       Error_Handler();7 w6 f9 a# d: P/ `5 d7 c8 ~* p
  58.     }
    + P* }6 A5 i! [# Z+ r
  59.   }
    6 Y: [- L; O5 U4 z# V# a
  60.     % m7 ^9 \9 U7 o3 x1 L& P; @
  61.     /*##-4 Receive messages ###################################################*/
    % L) S- A" K& K5 O! j6 T; X8 L
  62. : a" e3 {2 q* k6 b1 y# y7 ~: Y
  63.   /* Check one message is received in Rx FIFO 0 */& H! ^. R& D! O+ c3 }
  64.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)( @; W( _$ H4 b; Q8 k: c- p- j/ D" w
  65.   {0 f5 R* e/ P4 A7 R( ^
  66.     Error_Handler();
    4 g. K- _: Z6 z5 Z9 Z+ |( f9 z! V. L# }
  67.   }5 h( G: o1 P- ]% T6 ?! Z$ N4 w

  68. - ^- u1 V6 V$ U# H
  69.   /* Retrieve message from Rx FIFO 0 */$ u2 }5 M3 Y4 p3 G3 s; k
  70.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)
    - a$ _# D  w5 f" @$ c8 y
  71.   {8 M* L  L# g. G' i
  72.     Error_Handler();
    9 g3 R, P  E/ `) \8 Z! h
  73.   }
    % V0 R4 w4 M' w. e* I( \- E6 F9 U
  74. $ J; g, Q/ ?+ c5 n
  75.   /* Compare received RX message to expected data */" Y( `* A0 `7 P* Z
  76.   if ((rxHeader.Identifier != 0x444) ||
    ; c7 {1 W* U6 S8 J) p. ~
  77.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||8 O$ \8 A' b* T1 m
  78.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    8 U4 L! R) ?9 i
  79.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U)). J8 ]. n7 [# R( l+ }0 P. A8 {
  80.   {' V: w2 o3 q' g  ?
  81.     Error_Handler();8 o! c* {4 d$ F* ^# Y+ R
  82.   }, k8 ~! w% A, C/ z
  83.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);& S7 t9 [2 q; \  F# f
  84.   /* Check two messages are received in Rx FIFO 1 */
    * p9 s. O; G0 R0 O1 G
  85.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)
    7 n) I5 X- Q4 N0 ]# Y1 _9 c: o5 e( Q
  86.   {1 M6 s4 a, z+ E5 ?& l7 b0 P
  87.     Error_Handler();) ~8 G( B" Q& `
  88.   }
    % N9 A9 P5 B! X7 }, V9 O9 |
  89. 9 [/ t' V2 _* j2 U* M: V
  90.   /* Retrieve message from Rx FIFO 1 */
    # ^3 A) Q- ^7 b1 ?- n- m7 K% q
  91.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    6 [( u& G4 I1 \& _
  92.   {
    . e3 T4 w5 H& `& ~
  93.     Error_Handler();
    ( W  y+ g  ?% W6 t* ^+ L
  94.   }
    : a, P/ a! L3 X" V  B+ u1 W- A

  95. 4 m+ `) o! y% ~
  96.   /* Compare received RX message to expected data */7 y) z7 _9 ^( h  _
  97.   if ((rxHeader.Identifier != 0x1111112) ||
    8 }: K. I! n* H# z- z
  98.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||; \# p$ \+ O5 t, M8 ~0 _
  99.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    " r: K& P& b4 `0 R; b, t: d
  100.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))7 \1 n* ]% |' K! m" H
  101.   {: D( X) f2 C2 l# R1 ^
  102.     Error_Handler();
    - }: q/ C+ f- S; S4 J, U
  103.   }
    9 B2 R0 N# S$ U
  104.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);! \- Z# E" S8 ]( @4 `! |$ M

  105. - c; s3 ~1 r" V2 w
  106.   /* Retrieve next message from Rx FIFO 1 */
      a/ `: m+ X% e! ?7 J3 A
  107.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)& H( w9 S# q1 y* E) s
  108.   {
    " d+ K* Q- `* j. K4 T9 B
  109.     Error_Handler();# B( q  G% {& g" y. ]6 {7 m
  110.   }
    / @' m) P% n4 _
  111. 2 i3 `: l6 ~8 t
  112.   /* Compare received RX message to expected data */
    8 m2 F% r1 C9 v/ n
  113.   if ((rxHeader.Identifier != 0x1111113) ||' z, {  @# ?: z$ m1 c
  114.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||+ Y# M0 A$ q6 C4 E4 J2 ^
  115.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
      L7 H9 x8 }- y0 @1 }
  116.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))
    2 q2 `7 H9 {# B8 p$ G9 J  \
  117.   {; ^1 T' x" k+ v4 S& @9 t
  118.     Error_Handler();
    & p* i, y1 x3 D) g3 z2 f9 y
  119.   }
    5 h( {& J: G" D3 I4 U+ Z
  120.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:, v7 R, I5 M( `, O
9.png
1 P, Q( l- H' T- |
$ c# J' t5 e. i$ v
      这里多了一个C8,应该是串口出现的问题。
$ x8 T% W. G* G/ j$ x
# R0 F1 z4 Y; T7 q6 I; Q6 O1 B; s; K& G
* u6 ?% E+ Q- L# n3 ~- m

7 k/ M2 v3 D$ x3 e6 I/ a' y$ h  c. E5 ~  [% k

1 ^. Q1 R9 L+ n+ C3 N4 S( M- Q0 `6 t
" [9 d# h  ?( H/ ^; G

( T$ z: T. p  T! V
. N, l8 \7 {% b4 N: |, H+ p! T; m4 _5 s

7 C$ R* ~' x/ T" Y' u9 A) }: F: V6 f$ v3 x) ~
收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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