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

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

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

% Q+ s/ D3 E# |      实物接口如下:
6 T% v7 J4 O5 Y
2.png / j' [4 K! l9 _% ?( w- l

7 N" G; d8 G4 |8 I2 ~7 s8 s" H      可以看到就在常用的USB接口旁边,也就是说基本上对于C0系列来说,USB和FDCAN只能二选一了。
& W" U5 s8 g8 Q, i; C, A      那么如何实现FDCAN的配置呢?
: T9 ?2 b  M: S* R5 J- B: h8 u8 e# ]      先看一下时钟配置,因为C092支持最大的是48MHz,到FDCAN最大也是48MHz:' z" R$ z1 `/ K! _7 P$ a5 c; F, D
3.png
1 G' l/ _5 E0 q$ T0 u% Z
      启动FDCAN:3 @$ S& T, e. z# N- w
* x8 S( W: ~' I2 C% j' b6 P
4.png " N" K1 N/ Q% b/ I3 A$ ?: Y% {- Z
/ |3 t. L% ], P1 Z, _; ]% M' s6 s
      这里没有过多的模式和配置,直接启用就好;
# S6 I4 t+ i* O. T      注意修改默认引脚:
* b0 T) E1 p; d0 @3 h& p
5.png
. v% c) }2 @: ]) O# j$ I# V; m& L- Y9 g

( G& ]( N1 J  r- c      下面就是具体参数的设置,我们本次主要进行一下回环测试,所以要进行如下配置:1 }' o& \$ A" U9 _, Z
            
基本参数; t" k* x. P- N+ k: E6 U& l, P+ L& i
Clock Divider: ]5 p8 o: {4 A! M, X8 i2 H* v
时钟分频4 K" l! s4 o! A) ^$ |
Frame Format" u' t4 l5 N( N3 H, u' I) z4 u
CANFD模式
; ^/ n+ l6 d8 E; i8 U
Mode
, C8 l, G- ^) v" |0 c. ]
正常工作模式! [' H7 ^' g; t! q
Auto Retransmission
1 }1 T& R4 P/ P& [$ [
自动重传
, `9 F* m8 @( j9 b; r& q" v8 z5 h
Transmit Pause
7 r  b. X6 u- R
传输暂停
- B6 Y& k! N  y: k
Protocol Exception
4 n/ O3 a. K! }# @1 ?1 K; _- h
协议异常处理
$ L& V' f% e/ y8 Y* M$ q5 B
Nominal Sync Jump Width
) ]6 j4 B! I& W5 w
裁决段同步跳转段宽度; b4 `8 x% ]8 {! J, L# q
Data Prescaler
2 x! a: t# F. a/ X
数据段分频系数! Q! Q2 p! [3 h
Data Sync Jump Width
/ z% N* x) k; Z
数据段同步跳转段宽度' N3 n  D8 m1 ]& h5 _' y
Data Time Seg1
/ s  m: A1 V" a$ P2 B6 g
数据段时间段12 ]) L/ q7 g) f6 M  Y2 y; d
Data Time Seg29 k! Y" W( R6 Z) B3 P$ {& n/ [
数据段时间段2; s2 }2 D2 v; o2 H) m+ I' q
Std Filters Nbr9 z" R: e% p- e
标准滤波器数量
2 ?' p/ J' E/ I/ {( [. Y. p
Ext Filters Nbr
& O4 Z7 u( q% t  N6 e6 p
拓展滤波器数量
; C; L8 O; D& D
Tx Fifo Queue Mode8 z% G2 ^% X2 {
发送模式) d& T# A6 P7 o0 ~; d5 I- e8 ~2 e
              我们按照例程中的配置参数进行一下配置:3 `" M. m  Y2 T7 {9 j2 T9 z2 R
6.png
4 H+ G5 N' z1 T  T- X/ z' y1 v

+ j3 G' z8 C+ `      接下来进行比特率的配置,如下图:
) B. y  `% h) r2 Q. t
7.png ; t  _. f% ~0 C# O. ^
% B+ ~% \% E: S4 F
      上图的选项最小数值是1,比特率=CAN时钟/时钟分频/预分频/(Seg1+Seg2+1),所以就算是最小配置参数,得到的最大比特率是16M,不过我们还是不要设置那么大,就和SPI的配置一样,太大不一定通信稳定。4 T' _* n/ e) h8 ^2 u& z
      依然是回环测试,我们将CAN接头短接:
; t- y2 i; u: n% u  ~
8.png
2 J# A, X4 j2 i. h4 z
4 q. Y% H: a7 _$ A+ g+ x
      这里我们主要配置过滤ID,前面各开启了一个标准滤波器和一个扩展滤波器:6 K% s# Y; {7 f# F' e: @1 T8 [( }# U+ y
  1. /* Configure standard ID reception filter to Rx FIFO 0. Only accept ID = FilterID1 */7 g7 X; S* l$ @) z9 F2 {9 ~
  2.   FDCAN_FilterTypeDef        sFilterConfig;9 k1 O0 |9 {2 F  r& y
  3.   sFilterConfig.IdType       = FDCAN_STANDARD_ID;6 W' z' d" V+ W) K& s& Z
  4.   sFilterConfig.FilterIndex  = 0U;
    , d) J1 i! T; i. x4 u1 A! C
  5.   sFilterConfig.FilterType   = FDCAN_FILTER_DUAL;
    / |2 O! E3 ~  z0 Z
  6.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;$ q4 B) n  N/ Z' H' a' s$ B% m
  7.   sFilterConfig.FilterID1    = 0x444;% {! }% `" ~  q* w. o# W
  8.   sFilterConfig.FilterID2    = 0x444; /* For acceptance, MessageID and FilterID1 must match exactly */
    0 p' ]/ Y* D! x: I
  9.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)3 c; g$ e9 p3 R) |, W
  10.   {" I! ?% C2 R0 _$ }
  11.     Error_Handler();
    + w7 N) O: x0 k% y- _6 |
  12.   }
    & {1 o5 [7 R$ M9 x4 \/ ~
  13. * Q( N, S: N3 z+ o; \  t  r
  14.   /* Configure extended ID reception filter to Rx FIFO 1. Only accept ID between FilterID1 and FilterID2. */
    / j4 g" n0 s5 g% q- s2 a
  15.   sFilterConfig.IdType       = FDCAN_EXTENDED_ID;
    " \. J+ [% ?7 Z! ~2 s
  16.   sFilterConfig.FilterIndex  = 0U;& L1 E% f: }- m5 a5 f6 j
  17.   sFilterConfig.FilterType   = FDCAN_FILTER_RANGE_NO_EIDM;
    . |; f  v8 f( r
  18.   sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO1;
    ! z% {$ Q3 y- A
  19.   sFilterConfig.FilterID1    = 0x1111111;, p3 q) y  x6 a. a9 W
  20.   sFilterConfig.FilterID2    = 0x2222222;
    9 n; l3 E  ^$ Y4 ]* Z* a+ j
  21.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
    $ J# s! {/ E  U
  22.   {+ V+ k/ o% _- j  C
  23.     Error_Handler();
    ! Q7 w, |! L1 t
  24.   }
复制代码
然后是进行数据的发送和接受,这里都是通过FIFO的模式进行缓存的,并在接收节点进行接收数据打印:) r9 d" r" p8 p- d5 l, c' A: c7 i
  1. FDCAN_TxHeaderTypeDef        txHeader;6 X: x6 y5 B# H: r5 B

  2. ' _7 v( y/ h5 k1 y7 t% \0 y/ p/ R
  3.   /* Add message to Tx FIFO */
    9 ~* h  \* S  {. g" |4 m9 P
  4.   txHeader.Identifier          = 0x444;
    : Q: l) i+ A9 Y; _; E4 d4 B
  5.   txHeader.IdType              = FDCAN_STANDARD_ID;
    0 b( k; r" \" z: s
  6.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;# o; t8 G# v6 A/ e6 A
  7.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    2 q  G  F; z8 T6 C: S; |
  8.   txHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    ; X$ s2 m% \$ [! s7 y
  9.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;
    1 u+ c: q5 F0 O0 a( ?) ~
  10.   txHeader.FDFormat            = FDCAN_FD_CAN;
      i5 O  n& O' y( X, z# q: b
  11.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;. X& M8 i% ?. e6 z; D# M
  12.   txHeader.MessageMarker       = 0x52U;
    ! t, K) v6 \2 M2 S& Z' B
  13.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData0) != HAL_OK)
    0 O! [5 _2 C+ ~
  14.   {
    & H3 c" `- b5 r
  15.     Error_Handler();
    0 G  d/ n: L. N# f  `
  16.   }* A9 J! [8 G$ E! \9 I, L6 Q

  17. , _' h  n4 A0 a' l" o' }- K6 n. O
  18.   /* Add second message to Tx FIFO */% i1 h2 `9 i/ q6 @5 K4 k: _6 I
  19.   txHeader.Identifier          = 0x1111112;
    ( j4 ]; ]# c0 T
  20.   txHeader.IdType              = FDCAN_EXTENDED_ID;1 [2 }6 E4 c1 Q3 C) s
  21.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;% n0 d" ?( E! E% o  z  Z: w8 y
  22.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;
    ; {/ F% R) O& j5 I
  23.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;6 A! G* g3 T" l' Q6 f8 E
  24.   txHeader.BitRateSwitch       = FDCAN_BRS_ON;: Q9 D: x6 {5 R
  25.   txHeader.FDFormat            = FDCAN_FD_CAN;& s& a1 \$ z; F6 r( Y
  26.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    / M( D. }; Y9 `$ h2 w* _
  27.   txHeader.MessageMarker       = 0xCCU;
    ) S( L  S8 F7 y% F5 W! J) t# F
  28.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData1) != HAL_OK)5 H3 {: s% ^  z
  29.   {& a1 k5 P% l1 k: P) l+ \  p
  30.     Error_Handler();+ z) m! }- g6 u' c; N1 Z
  31.   }( A. y2 M# |3 O2 B
  32. . [- J# W7 t5 P) n3 U" N) h6 a
  33.   /* Add third message to Tx FIFO */
    ( X! @+ w. D& @6 j' @2 M4 _7 S& d2 C
  34.   txHeader.Identifier          = 0x1111113;* k, P' a: X! f( ?; L
  35.   txHeader.IdType              = FDCAN_EXTENDED_ID;& |- x9 |/ v* M$ M
  36.   txHeader.TxFrameType         = FDCAN_DATA_FRAME;
    ; A# g! {' T) Y7 G: k6 t
  37.   txHeader.DataLength          = FDCAN_DLC_BYTES_12;  I- X! m) C/ E. W
  38.   txHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;3 j2 x! p8 G! p* A& ]2 x
  39.   txHeader.BitRateSwitch       = FDCAN_BRS_OFF;1 f4 d9 S7 q9 D& o4 U
  40.   txHeader.FDFormat            = FDCAN_FD_CAN;
    * A8 G' G* {3 e9 ]; v. R7 _8 R
  41.   txHeader.TxEventFifoControl  = FDCAN_STORE_TX_EVENTS;
    4 H: f2 x4 C6 g
  42.   txHeader.MessageMarker       = 0**U;$ m, G. b. m7 _2 e- B
  43.   if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, txData2) != HAL_OK)+ S  F9 h# U) w8 v- m
  44.   {: i, X6 y4 e% H: T( \
  45.     Error_Handler();
    2 F. S1 p5 F( h/ t' T
  46.   }( K' {! ^: y0 _9 N
  47.    
    " }' ]: l" u) `# m" ]! ?* I0 e
  48.     /* Get tick */
    $ y8 ~) Z4 X5 W: V$ X  z+ `% K; L
  49.   uint32_t tickstart = HAL_GetTick();3 r. i& y& ]  j5 |6 I

  50. 5 a1 E# U2 w; ~0 D
  51.   /* Wait transmission complete */
    : F  ]8 i, e- h2 g( z/ q4 S2 O4 I8 m9 o
  52.   while (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) != NB_RX_FIFO)1 s3 A/ u8 e% @8 F0 ?4 n% A; a! @4 Z
  53.   {) U' G3 @( i3 X3 f% S2 }$ x& C
  54.     /* Timeout handling *// O" Q) k) _* A
  55.     if ((HAL_GetTick() - tickstart) > TX_TIMEOUT)
    & k4 l$ }7 @0 c" o
  56.     {
    ! B' F0 ?0 F( e1 v9 t
  57.       Error_Handler();
    : \5 V: O1 D( r- v+ G+ ^
  58.     }
    * Z. @+ J( \1 ]' Z  a0 |* ^6 c
  59.   }
    % |  D; ]+ m7 \% {7 J. V9 [- u
  60.    
    ) A" F/ h% i6 C! Y
  61.     /*##-4 Receive messages ###################################################*/3 Y3 y2 B3 `( w; U, |4 `1 K

  62. 7 I5 o4 Q3 Q2 n7 I; w+ f# e/ o
  63.   /* Check one message is received in Rx FIFO 0 */
    1 b! x4 ?+ y7 q
  64.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO0) != 1U)
    & ]+ I& k, M$ D- \+ ?; v
  65.   {
    ' k* _0 }( m; M+ Z4 A, \9 m  f" t
  66.     Error_Handler();
    ; g/ c2 |, F- \* R2 B. Z4 k
  67.   }
    1 ?4 u4 @: p& S: I

  68. # v, i6 l2 Y6 T9 `7 C' ~, b9 y% h
  69.   /* Retrieve message from Rx FIFO 0 */* C0 ^; ~2 w0 ^1 U
  70.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &rxHeader, rxData) != HAL_OK)0 w# h  n) I4 K# r
  71.   {
    , d  T$ D$ w% s6 y7 U
  72.     Error_Handler();8 I& z/ A, c0 V
  73.   }3 ~% B; |; L3 C# K$ G% J; y" b
  74. 8 B& a% L0 Q( `6 B2 p
  75.   /* Compare received RX message to expected data */* f0 P  s. [( H6 U; ^  z
  76.   if ((rxHeader.Identifier != 0x444) ||
      W2 H8 j6 O% {/ b
  77.       (rxHeader.IdType     != FDCAN_STANDARD_ID) ||( f! e7 f& j) W% L2 ~* e
  78.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    + u4 C8 W3 T- ]+ h
  79.       (BufferCmp8b(txData0, rxData, COUNTOF(rxData)) != 0U))
    - L9 V. v' H' g* v1 k0 ]6 g% S
  80.   {
    0 I' s; z' K. @* x) I) ^- x
  81.     Error_Handler();+ y5 g4 c8 u1 y
  82.   }
    ! O9 O. F2 e1 G& w4 |# O, d5 f
  83.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);: `' P9 y! V# Q) o' n3 }0 g) K+ b9 _
  84.   /* Check two messages are received in Rx FIFO 1 */
    8 t' ~- Q2 e# ]" z5 O) a
  85.   if (HAL_FDCAN_GetRxFifoFillLevel(&hfdcan1, FDCAN_RX_FIFO1) != 2U)# Z0 ?# w' R6 a3 _2 }9 s
  86.   {6 R9 ?1 I& e0 a' h8 B, m  M' g3 F4 d
  87.     Error_Handler();
    , d: K* N7 B1 Z  x5 `1 O
  88.   }; v4 o' l: |" U* S$ q

  89. $ S" j2 L) b4 I2 }  W
  90.   /* Retrieve message from Rx FIFO 1 */7 T6 D3 U* b3 @0 H3 O$ g; X
  91.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)
    " E, k4 J* \, Z# d
  92.   {
    7 P/ Z: Q9 g# f- \7 t% y3 i3 J: K
  93.     Error_Handler();
    " v- U1 w3 c  A! q% f) O# a  L
  94.   }
    : c& \$ e9 @6 t3 ~
  95. ; b; g' U) _! s: n3 k2 h! J
  96.   /* Compare received RX message to expected data */
    ' ]) s! E2 H; B% `# j
  97.   if ((rxHeader.Identifier != 0x1111112) ||* c' e" I  u7 b% V9 t
  98.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||# M5 b9 f3 m5 Y* ~
  99.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||
    & a8 ~& u4 J# D- g; [
  100.       (BufferCmp8b(txData1, rxData, COUNTOF(rxData)) != 0U))
      Z4 T  n3 U. T7 e+ q; \, N3 v* J
  101.   {/ p* \) W# W, h$ `* q3 s# c3 E# d
  102.     Error_Handler();
    " m9 K& m& x( B% f; Q
  103.   }4 D7 N$ f! ]$ f) h+ i5 v
  104.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);" H7 X6 y& A. A8 k& @# y7 S2 v
  105. % m- z' _& g. \, R- l
  106.   /* Retrieve next message from Rx FIFO 1 */, i2 w, j% c/ L4 L* C6 z
  107.   if (HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO1, &rxHeader, rxData) != HAL_OK)! D1 v) X3 W  l0 T
  108.   {/ ~2 a' i. h% M' |" w- U
  109.     Error_Handler();
    7 v. r0 P3 p8 I) e
  110.   }
    6 |5 n4 L  b$ p, }' \9 F; z5 U8 {! |! z

  111. 5 d, i4 u! w7 S6 @. K
  112.   /* Compare received RX message to expected data */) F' d: e; P2 p2 \
  113.   if ((rxHeader.Identifier != 0x1111113) ||7 q7 A" j# Q+ d5 J& Q" P
  114.       (rxHeader.IdType     != FDCAN_EXTENDED_ID) ||; y5 V, u# d* V9 `
  115.       (rxHeader.DataLength != FDCAN_DLC_BYTES_12) ||: Y- v2 S$ ~. l& Z9 y
  116.       (BufferCmp8b(txData2, rxData, COUNTOF(rxData)) != 0U))
    ' }+ y6 f: R) Z- L9 T7 ]
  117.   {
    # J( a5 m- Q4 }; ~2 l8 U' ~; e
  118.     Error_Handler();
    - {* q* {( e7 p+ l( ^0 k/ E
  119.   }& ]" |; T- S$ x6 f# j5 d6 Q: r* W4 H. t* c
  120.     HAL_UART_Transmit(&huart2, (uint8_t *)&rxData, 12, 0xFFFF);
复制代码
     最后在通过在FIFO中查询的数据进行打印,与发送的数据一致:; v1 J% |) G0 o
9.png
* I0 y2 W+ y4 q" u$ ~5 N  k- S# {
% M4 o8 g7 V" T- w6 a  P
      这里多了一个C8,应该是串口出现的问题。% }- ?8 ?) _# D; Y3 E, r- R3 b

. n) c" p4 n; ^( x3 J! i
. i4 J( B+ @( n' M# x0 V1 H2 h
- L# {6 C6 l: u8 x: t0 M# |3 v. }5 q4 S) Y# {6 |0 O4 W* ^. K0 I

$ @; ]& k5 w+ d7 g( W3 I7 j. _: u6 C* d1 R
: Z- @! x, ]4 @( w1 R
  @) e$ t* {* M

9 H" ?8 C6 S7 c' b, I( w& b+ u% J5 O

! \  |& b: u- W& n! A+ d
7 G3 _1 L6 J6 @" V" V0 [' K: q! B
赞 收藏 评论0 发布时间:2025-5-4 00:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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