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

【经验分享】STM32G474 CANFD 用例详解

[复制链接]
STMCU小助手 发布时间:2021-11-11 22:00
本篇用起来, 连接关系如下:
. Z& V, e+ p& k! g' E. l* X
" I3 A2 Q4 `: B% [5 ~2 u! j; H

20210222185812381.png

4 f7 g) Z9 y! `# R6 u$ N
4 C* ^: i- v, c0 e9 G) ^3 B9 F
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.
) ^$ {$ f  v$ t/ z! N! @( |
% J# g$ t+ z7 o9 U6 C- GSTM32工程搭建: `& M$ ^+ r' u* X' S. n
STM32CubeMX配置步骤如下:  L4 `, ?4 j- K/ m* c& x" y

- e' Z/ R& c! s+ {( Y7 fMCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx
* o* x+ K& }+ X! j. u0 ~7 ?7 ]; O7 Z" R$ p( o. i
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire
5 e; l" B: P5 p- T& f; z( X: f  q" D+ o) R$ ]9 E- Y, E
Pinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator5 s- p2 R+ C2 {

8 X2 G3 }- A* pClock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):0 U. j* c$ V  R. v  Z. [

20210222185828575.png


% b. W  v$ V  f

20210222195952515.png

$ M0 H4 P6 {" j. D; K" s# x, |2 E" a
/ D' N3 w: V. M5 G3 m6 u3 i1 a
开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:
& l1 ^* @0 F) d% n$ p" c4 O" w% S- N3 o, F4 o) c) O6 f$ e

20210222185846781.png


! F0 ]: M- G- r9 l) H+ U% I) A* H2 w- E% }" W2 ?

20210222185905935.png


- A4 ?. r' N1 q6 \- M( R# v% M3 ^/ P
LPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:) g' D  v  |. \: A$ M2 W- c  T

: s! ^0 _/ ?: e" j( ^# J- s

20210222185926920.png


" r0 E( s% @; v( h' b& W. F
2 [( R/ G/ {0 b" W8 m# XFDCAN1配置: Pinout & Configuration -> Connectivity -> FDCAN1, Mode选择FD, Frame Format设置FD mode with BirRate Switshing启用位速率变换, Auto Retransmission设置为Enable开启自动重传, Trasmit Pause设置为Enable开启传输暂停, 速率和采样点设置参考上一篇 STM32 CANFD 基础知识的位时间和采样点小节, Nominal仲裁段设置500Kbit/s(160M/NPre/(1+NTSeg1+NTSeg2) = 160M/4/(1+63+16) = 500Kbit/s), 采样点0.8((1+NTSeg1)/(1+NTSeg1+NTSeg2)=64/80=0.8); Data数据段设置为2Mbit/s((160M/DPre/(1+DTSeg1+DTSeg2) = 160M/4/(1+63+16) = 500Kbit/s)), 采样点0.75((1+DTSeg1)/(1+DTSeg1+DTSeg2)=15/20=0.75), Std Filter Nbr标准帧过滤器数量直接设为最大28, Ext Filters Nbr扩展帧滤波器数量直接设为最大8(虽然后面并没有全用上), 勾选FDCAN1 interrupt 0中断, 引脚也从默认调整到板子上用的引脚PD0/PD1:. N+ ?' E6 x! V) c

5 l! R( l3 y% V* h

20210222185949803.png

' o& I$ ?& ?1 n) E9 B2 w" D4 }

7 m$ Y! I2 l' E

20210222190005173.png


% Z3 [3 ^" i: s3 P% ^6 n& W" v
FDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:
/ r0 d3 l+ r4 ^7 I8 ]4 ?+ S6 ]* J% m- K- b  W; T) I

20210222190054536.png

% v) N1 B6 b; e- W* t3 \

# B5 K; B  r4 ?Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.2 ~) `& Y+ S2 q0 e
$ p$ s5 B. I/ H
Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral  _: z9 E6 S' E, F1 z0 |

# T0 |3 V/ k# G) `- R- ~3 }% M  [7 p点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.
4 c1 F, t) M' x8 |/ a9 Y7 G/ N
5 t, m6 w3 t3 `) Q, k0 x! w* LKeil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:
8 [; r5 @0 `3 [" A5 M% R
9 V: b$ `  h0 j0 xFlash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.
3 l6 B3 t5 D9 m" @Pack选项卡, 去掉默认的Enable勾选
* N  E7 J: S" A, t  W到此配置结束. 下面是手动添加的代码详解! q( I: F5 o" S% @5 H

, I/ B7 |; D0 |) B" t) |1 A串口配置$ {; ]: f  w1 k2 p9 D; K, R
为 LPUART1 添加printf支持:' ^- a' Z9 v% `

' V4 ]! F$ ~* f
  1. #include <stdio.h>8 r2 J- E( e# y

  2. % n4 h6 F, @- g( S: e# o
  3. #ifdef __GNUC__- g, ]* |- \& @! n
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)# y0 |, }$ u* r  P& K% h8 s
  5. #else5 _" \; O+ [; ?* I- G
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    , P1 q- ^' o0 A+ l# h* ?5 g4 }
  7. #endif /* __GNUC__ */3 C" }; q6 D6 P

  8. 6 o4 I$ N- J5 x. Q" {5 E8 E
  9. PUTCHAR_PROTOTYPE
      h2 X. [/ }$ P" X0 n
  10. {
    1 ^0 }, g; m! v3 q
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
    3 C' m+ C/ V+ A2 B  L; ~
  12.   return ch;
复制代码

8 e0 I8 V3 l9 m2 S/ X100us定时器+ T4 [1 R- m' J, C/ M  ^" \
因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.
+ W8 M- v) j& K+ O! a5 l% U
7 D+ U7 }0 y9 `( c! d  V$ F# i
  1. /* USER CODE BEGIN 2 */9 `6 Q) j( @* c6 n; ~: v/ u$ G: ^# k
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.4 `0 I+ G( o" f% O$ l
  3. /* USER CODE END 2 */
    0 W; l1 y9 ~* o+ j' a( x2 }- p
  4. 7 Q2 [5 k$ H% s+ u+ W  r
  5. uint8_t tim6_flag = 0;
    3 Z  F1 g9 p5 v# c6 I
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 6 W# U! m3 T2 v4 y' N2 a
  7. {
      Z0 Y5 f7 F% q$ H
  8.     if(htim->Instance == TIM6) {# f# e* w5 Z0 f- l, B
  9.         tim6_flag = 1;) h* Q0 n& A$ V- B8 F7 Q
  10.     }0 U" p2 T% M, H$ n$ W: V2 ~* K) x/ Q
  11. }
复制代码
( d8 r+ w4 s9 y
FDCAN配置
( ~$ m  L  A5 Y* M2 D& b9 L主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.
7 z" c: o* b+ F( {0 m0 O9 |  Q! Y/ }4 a) f. x# S
  1. FDCAN_FilterTypeDef sFilterConfig1;
    / x0 h7 i7 v' u: _( O0 m
  2. ' s& d' k, M, R  C+ u, Q
  3. void fdcan1_config(void)
      ]6 n- s7 x1 _0 h% S: p% D: ?
  4. {: _) d) K  S( T* V' f! _: P
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;( K7 e2 q$ A: P$ u0 I# v
  6.   sFilterConfig1.FilterIndex = 0;
    7 y6 p0 s; e* X8 v$ F  e3 ^4 h
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    ( J6 R8 N: Q/ z. e: B/ V
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    - ~& E" p9 P9 F" n) a6 Y9 n$ w
  9.   sFilterConfig1.FilterID1 = 0x00;+ T* G) O% Z: E- b& A9 ~) U
  10.   sFilterConfig1.FilterID2 = 0x7FF;
    / M7 j6 D4 Q9 q5 Q  P/ H
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    4 k2 q. o( B0 ~, y4 o+ r
  12.   {
    8 L. p6 L. _5 q6 L
  13.     Error_Handler();
    ' F$ Z- H: ]. Z& ]% Y" R$ I
  14.   }
    ; O! Q3 |% o7 f+ E: p) l8 d
  15. / b7 A1 K/ G6 ?
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;1 g( \2 \% q' Z2 I
  17.   sFilterConfig1.FilterIndex = 0;
    * m7 m1 E* c9 m  p
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    , K1 H4 F2 L: k" M
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    " b% ~4 v8 N# G$ s# T
  20.   sFilterConfig1.FilterID1 = 0x00;
    $ U" L2 }# }4 V7 ^
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;
    0 I3 t: C3 W4 H) T6 A, h$ n
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    # G7 U( h5 t4 v9 l% ~+ x; h; T* X
  23.   {
    6 @, j2 V2 ?6 M/ R
  24.     Error_Handler();
    2 e5 P9 H& O5 l9 R$ ^! o# E
  25.   }+ @  W" k( f' ?. |# m- r- i
  26. - V: q4 M( J0 ?) H- @7 c" H
  27.   /* Configure global filter on both FDCAN instances:0 J# Z9 n% ~$ N! \* i. L, T, V4 P
  28.   Filter all remote frames with STD and EXT ID
    . h2 o6 Y. _/ l$ r- r% i, {6 a
  29.   Reject non matching frames with STD ID and EXT ID */
    % \: T$ c, d6 H# N/ [1 d
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)- w1 v) K" i! p
  31.   {
    " b) _- a2 v; H% i
  32.     Error_Handler();' f3 l/ e) s! V
  33.   }
    ; V0 m1 j' }2 \2 m/ B/ k5 q

  34. 1 d: j. r9 \) }& V/ m8 j! G8 U
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */
    0 `: m' g& e% R$ x# T# J
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)( d1 Z' m% F$ @2 U4 R7 N
  37.   {
    6 L" r1 L1 h0 _4 Z- b0 E) g: ]1 M
  38.     Error_Handler();
    $ r. V% K3 y& G
  39.   }' q- n' L: y- r  {
  40. / d8 i  L+ I6 `7 D9 V; P6 x; O
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)2 y4 e8 z7 `- u/ M3 B6 P5 L
  42.   {* R, y% [& M, o# I/ ?2 n& ]
  43.     Error_Handler();
    + e" N2 Y8 M1 @" D
  44.   }
    # e  q8 g) A7 Z- |' |# v" V

  45. ' R1 o8 E+ P. u6 P9 S
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode.
    6 z: {3 F" E3 F
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler' V7 d5 t# }) |& E+ A: |0 e- N
  48.         TdcFilter default recommended value: 0 */
    ; }- Q: E$ {( C" O5 W; v6 j
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);" s# ]. c2 p" @( U6 k2 T: L& C
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);' K7 a& R& ^% z8 H: ?# s- O5 d( b

  51. 4 [; ^4 O: }6 |! i8 G
  52.   HAL_FDCAN_Start(&hfdcan1);& e$ I) k# L1 s% A$ v
  53. }
复制代码
/ ]4 Q+ s! I& d& r
这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:4 _  i6 m1 i$ n) Y
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;
    4 m1 c! P2 [  ]7 I# e$ E  E
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;' |, \" ^+ m% r% o8 c; D
  3.   sFilterConfig1.FilterID1 = 0;1 K/ i) v3 ?/ R( M/ f) v
  4.   sFilterConfig1.FilterID2 = 0;
复制代码
4 w9 T# E3 K# c  L& N& D
用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.
4 z/ L/ z9 C9 E' a0 [! z
( V* {' x) y: j$ N5 p) M# V0 e有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:, P" r4 l; d& m, }0 v

0 ?5 k2 g9 a' @" {1 w
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码

3 j; J+ d5 W; b! S( Y+ F: ~" vFDCAN2, FDCAN3的配置和FDCAN1类似.$ x  m! d0 u9 s7 l3 @- h7 J
% a1 d; \4 Q, K4 D2 l/ T+ l
Bus-Off处理9 G' T5 |( n+ [% @( ^5 u+ x  @
如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:
+ h) j$ W  U6 T0 W( p2 g4 F5 ?4 k7 U
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
    - ]0 E; x3 [8 E) W; |& F; r  E1 D
  2. {
    " T5 R5 f1 I" Q' K
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);
    2 e* y! l/ {# O( |& ~: |, a- Z7 z
  4.   if(hfdcan->Instance == FDCAN1) {, n, H5 V6 i" K3 r2 G4 L
  5.     MX_FDCAN1_Init();
    " f* e% N- X: v: j4 t
  6.     fdcan1_config();& Q. H& _# j  D$ K; T
  7.   } else if(hfdcan->Instance == FDCAN2) {
    : \/ t* l: I, Q9 S: V; {
  8.     MX_FDCAN2_Init();
    / l* ^* S. S( D. i* P6 t0 |
  9.     fdcan2_config();% T! E) @# A* K; B2 q
  10.   } else if(hfdcan->Instance == FDCAN3) {8 k: e3 D6 G7 k# g
  11.     MX_FDCAN3_Init();
    : U$ q& W" u, B( m
  12.     fdcan3_config();
    & o6 H1 z' q) o( R* c
  13.   } else {
    ' |. P. `# R6 R! @% s) z: B9 X
  14.   }
    ; X1 t# E6 v. \1 c4 v' l9 V9 T. R
  15. }
复制代码

1 W8 x$ R4 T7 d7 M7 Z新消息接收处理
; O6 z- ^) w5 o4 o直接把接收的消息通过2M波特率的串口打印出来.$ B$ x0 b/ p: H  N
: A5 [1 P5 ]5 h, N0 ~2 o+ n& d
  1. FDCAN_RxHeaderTypeDef RxHeader1;
    & X0 }0 X" y% I" w
  2. FDCAN_RxHeaderTypeDef RxHeader2;
    ) }. v3 O. ^7 F# \$ N+ ?( x
  3. FDCAN_RxHeaderTypeDef RxHeader3;
    / R9 ?6 Y& g, m

  4. 9 _# z+ E+ m! f1 `! ?
  5. //RxHeader1.DataLength => can_dlc$ U) O3 L9 q0 G& m8 f
  6. //0x00000 => 0 ; c4 r. s9 ?% G* q) D, b
  7. //0x10000 => 1 / Y: ]& W3 E5 p3 ~; E
  8. //0x20000 => 2 9 Z( g" U" \2 U9 T
  9. //0x30000 => 3 9 M, j* m0 I* {, }: @
  10. //0x40000 => 4 + j* p1 R" Y- u( |! f; K7 h
  11. //0x50000 => 5
      H- ^, \$ l: g- @0 v
  12. //0x60000 => 6
    / K: `, J2 i5 z3 A5 d
  13. //0x70000 => 7
    $ d- [4 f# J" r
  14. //0x80000 => 8
    + X  q# }! Y! P( Y7 M( k$ I
  15. //0x90000 => 12
    9 N4 F$ E& F2 c" e* N
  16. //0xA0000 => 166 w' N* r& J9 u) w2 `
  17. //0xB0000 => 20  S; E( p+ x9 g& ^+ r& k
  18. //0xC0000 => 24! q, s. e3 Q% w2 x; W) Y$ ?
  19. //0xD0000 => 32# t! S! J* D6 h7 H
  20. //0xE0000 => 480 J& A; k, I( d% Q. V4 D
  21. //0xF0000 => 64! X) Y/ {, w; j% i
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
      Z) w/ c5 S  L
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)9 ~1 K: A5 Q. A3 {+ g. C- s
  24. {' n0 N) C  u# g
  25.   return dlc2len[RxHeader_DataLength>>16];
    9 v) a6 I9 Z* F) i# |) Q% h5 H* z
  26. }
    ( X$ P, x2 o. r) _% s# L! G: ~/ s
  27. - x) a" g& F4 }1 f
  28. uint8_t cnt = 0;& e2 p9 M- C" x2 v* c
  29. uint8_t brs[] = {'-', 'B'};1 K9 \- p8 [0 [2 B- E! Q4 E
  30. uint8_t esi[] = {'-', 'E'};, A7 [. w5 J$ A% j
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    ) I+ F4 q, V$ r2 i
  32. {9 |; |. i; G5 V) ]  n
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {
    1 O" ^/ Z0 F4 J
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
    ; o- Z. M' u5 T4 T
  35.     //RxHeader2.Identifier++;
    , h8 O! n. d; r( g# Z
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);8 v& q" A7 o/ y  J: j0 ]
  37. ( _+ u) C/ a) F' i6 [
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    6 T5 G0 l  k. A
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));; l& G4 _% V& @1 `( a- G4 |1 j, L

  40. : x! K! S+ H" m8 p& [
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    " t& I1 n/ M# H0 E( y$ k
  42.     if (hfdcan->Instance == FDCAN1) {& j+ [. E; F; ]+ _2 B% c* c8 X
  43.                 printf("fdcan1, ");
    0 ^, D$ g# H$ O1 q8 s9 h5 ]
  44.         } else if (hfdcan->Instance == FDCAN2) {
    6 i4 |$ j' r+ F; ^6 G
  45.                 printf("fdcan2, ");# o* o5 c7 u7 z3 y' c, O1 a- D5 D4 E
  46.         } else if (hfdcan->Instance == FDCAN3) {
    * p% Z1 A+ L% M0 n) w4 m
  47.                 printf("fdcan3, ");0 q4 [% v  ~( |5 m, w3 u
  48.         }
    + m; p# m( }! \2 g+ }
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier,
    : _* H: ~% H. ~3 k% {
  50.                                   can_dlc2len(RxHeader1.DataLength), 9 J. ]* |5 G: I$ R! a! P. W
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],
    8 S4 W/ ?& _- |
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);4 V2 \3 ~: U/ D7 c8 N
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {- S5 r9 h) m# B! Q: G
  54.       printf(" %02X", RxData1[cnt]);8 A% L+ n2 K: p( k/ d
  55.     }+ R: G1 j$ G- v
  56.     printf("\n\r");
    2 Q  E7 ]% i7 h# d6 h' ~% b: q+ w
  57. 1 F2 S- ^  {; c- g. B
  58. & b4 L% P. F. v9 i
  59.     //if (hfdcan->Instance == FDCAN1) {* ~; U# m7 t, L/ ^/ E
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);- ?4 ?% X8 C" f6 B
  61.     //  //echo, G! `, V6 v0 \" A3 A
  62.     //  RxHeader1.Identifier++;
    : `, b$ j' l9 ~- h8 X
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);
    ' ?; a0 f: E& D! A
  64.     //} else if(hfdcan->Instance == FDCAN2) {
    ! i& ~( N3 h" {4 g) ]/ l
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
    4 X' t$ L1 {. v8 Q3 o% v% t  G+ t2 U
  66.     //  //echo( M; k* k5 L- W, S( O$ h
  67.     //  RxHeader2.Identifier++;8 `% ?; A, ~) |: U% u  U1 }/ q- V
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);8 o) U& a' [$ N# @; o2 F
  69.     //} else if(hfdcan->Instance == FDCAN3) {
    , u3 s; x+ h/ \$ P, g
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);
    " \; @% H. j9 I/ N. |+ ?
  71.     //  //echo% e3 v% P( d- c/ H, m# a+ O5 K0 e6 j
  72.     //  RxHeader3.Identifier++;; ^% V+ o4 Z2 t+ d
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);
    : b) w4 x- a3 @1 n) r  G5 Z  S
  74.     //} else {7 }2 e" c( {; \
  75.     //    _2 G3 k0 @, W" ~2 f$ B
  76.     //}& ]' ?2 e. K6 k# e9 }: R
  77.   }
    0 e7 O* t& q9 t
  78. }
复制代码
) m6 D; [% U& x' D6 e
注意注释中 RxHeader.DataLength => can_dlc 的对应关系.
- ~) J5 n" _! u/ N  V7 A. ?6 s" ]* x3 I5 _1 B' F
示例如图:
7 }5 G5 z/ O& E% t, X. G% F" I4 e1 i0 Q6 d* }5 u$ l6 G$ u
20210222190024669.png
* }) ~" f' z+ e

' J4 C+ x( d) \图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.
9 h" T1 d; M5 \% X
. z7 @2 T4 V' ^! z9 J4 yprintf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.
# M" N. N: A7 l. Q8 P$ `  G' K! ?1 U  t$ t4 p. p
发送处理
# W; R  s; U* U% x5 R发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.
' K+ h' U+ E( j/ f8 z
. x8 B# F' B2 [5 E- h
  1. #include <string.h>% Y8 x( o6 \" P  V
  2. # n5 V6 \  O; o$ X1 |1 `9 z
  3. FDCAN_TxHeaderTypeDef TxHeader1;
    : z: I' ]  Y4 q4 |! _
  4. FDCAN_TxHeaderTypeDef TxHeader2;! w7 f" x' Y( Z  \- B
  5. FDCAN_TxHeaderTypeDef TxHeader3;
    5 t/ V  C2 B! z0 c" }6 I# p( u7 N8 P

  6. 3 O/ A: w( F: I5 g; B2 M
  7. typedef struct {
    3 H% C8 t) U7 ]+ t) h6 `9 q4 _
  8.   uint8_t flag;! e' q* ]& b; n5 j
  9.   FDCAN_TxHeaderTypeDef TxHeader;
      ~' w! S# L  s% r5 [! @
  10.   uint8_t TxData[64];
    * {: v' J; ?2 K6 h) K  y: }1 e
  11. } FDCAN_SendFailTypeDef;1 G/ d1 c! ?! l7 A7 W0 Q6 q
  12. 0 n. N/ j. M3 p1 M, U' o% _" O
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};- o, w+ i: E4 Z. p; a
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};6 H6 i2 R2 E9 v( A4 [
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};
    9 M: ]9 E8 z) l* n5 {% ]9 s" Q

  16. * u, I1 ^# m2 V0 \/ b/ }# E8 |1 d
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])
    4 |2 y9 E* V/ g' B1 f9 q) e
  18. {: @0 P9 v3 p& N6 K, I/ \% P3 N
  19.   TxHeader1.Identifier = can_id;0 u3 V( n# Q, P2 N. J' u6 R# Y
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;
    . r" N4 f# k" y0 p) ?* L
  21.   if(can_id < 0x800) {  //exactly not right5 U' W0 n: {9 W$ ^1 [
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;7 S0 X/ v! i: T
  23.   }! f6 n) A$ J% e/ L$ F3 m
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;
    " B' I3 ?$ p- ]
  25.   TxHeader1.DataLength = DataLength;
    / R) R- x" D1 p+ g) R1 E, J, E- ^
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
      l1 x  y; D' A, O  q! X
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
    + u" c0 J8 N0 R. C& o8 G: R
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;
    5 S  j& m9 n6 u2 w% B7 u
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    , ^; U! p* f' V! I4 Z% j
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use
    $ J/ v: Z8 i0 N  X4 B% q# t% K
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {
    , r) M( @/ r$ \2 [8 s: l9 O( Z
  32.     fdcan1_send_fail.flag = 1;
    4 n8 V# L$ Y: l1 k' @8 W
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));& M$ f8 N& q+ ], L) h% E
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));+ g) P2 R; |# _: q5 v7 H' k  J8 T1 T
  35.   } ' Z. d1 q$ j# `0 [5 w
  36. }# F& K' Y& E/ K$ a) G& f

  37. 4 R. `/ k; T+ t, |: k: ?6 |5 I
  38. int main(void)
    2 \; Z3 `; Y# a* K" H
  39. {
    : |0 J  N4 T8 L. j: e$ _
  40.   ..., U$ K' c# s: K
  41.   /* USER CODE BEGIN 2 */+ _5 O. G8 m% p. S# m
  42.   fdcan1_config();' H5 |3 M: {9 [2 b1 {9 a& H. [
  43.   fdcan2_config();
    5 @. t$ j+ _1 X3 i
  44.   fdcan3_config();
    / {' D/ ?% ~' M+ C1 Z4 O
  45. ( x! o) a7 D5 a  O2 \
  46.   for(uint8_t i = 0; i < 64; i++) {
    ( l8 P1 S4 e. Q* c: v
  47.     TxData1<i> = i;</i>& P8 z/ d  K8 A+ i) ^
  48. <i>    TxData2 = i;</i>
    1 J, G7 D; a9 [0 E4 v. D
  49. <i>    TxData3</i><i> = i;9 o) v( Q: G4 Q
  50.   }
    : R; k) |& l( {; y! i

  51. 2 c# g3 o+ V" h( d, @* F; X
  52.   HAL_TIM_Base_Start_IT(&htim6);' w, E2 g$ X' M$ Q/ y/ S* A6 D) O  r
  53.   </i>uint32_t count = 0;+ F1 B: M2 t  r  G6 u. v
  54.   uint32_t cnt_100us = 0;9 X  e8 g" {- _) C
  55.   uint32_t cnt_500us = 0;
    8 C! g, l8 u& Y
  56.   /* USER CODE END 2 */- H; J& c* `$ ~) f2 P
  57.   N6 N9 b# T; Z
  58.   /* Infinite loop */
    # E7 R3 a/ }( E' P) N' U" V9 T
  59.   /* USER CODE BEGIN WHILE */
    ) U; O- y0 N; C; D" [0 j" g
  60.   while (1)0 ~0 ~; S' n$ T; u, x
  61.   {
    7 c; I) X) Z/ \; [( Q
  62.     /* USER CODE END WHILE */7 Z$ X9 `4 o, x, u

  63. 0 h- u% T1 @1 L8 u9 Q
  64.     /* USER CODE BEGIN 3 */
    : G" _3 J! u5 {2 _6 F
  65.     if(tim6_flag && count < 1000) {
    & w' L6 f, ?( y2 R, F1 {' Z
  66.       tim6_flag = 0;
    $ H; l2 j( R0 e
  67.       TxData1[0] = count >> 8 & 0xFF;
    9 ~* H1 G7 \0 x: B
  68.       TxData1[1] = count & 0xFF;
    # o% u+ L! }7 t9 |
  69. 7 q9 i" `8 o/ s& d+ r
  70.       ++cnt_100us;! t, O# V1 |( {+ e2 C
  71.       cnt_500us = cnt_100us / 5;4 e; I. F; c, `
  72.       if(cnt_500us && (cnt_100us%5==0) ) {7 G8 W7 d8 ]. h$ O
  73.         switch(cnt_500us) {+ g7 J: F( @# v4 u9 Q
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1); 7 p! [/ ~5 z' I, G0 y. y" _
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);/ H' {- E3 r: P3 P1 G* R
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;2 g* i: ~0 N9 f" `2 [
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;
    ' q6 p7 U" c6 A2 w. Q' E5 }; K. P  T
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;; Q# `& ?6 m; k: H  `6 e& N
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;- w! \1 ~7 B4 F4 C) S$ _% }- [
  80.           case 7: /* next send */ break;, A; d/ X$ ?& }: j) A
  81.           case 8: break;
    1 `9 S+ t" q# Q# T& [
  82.           case 20: ++count; cnt_100us = 0; break; //10ms, S- |* I0 d( I
  83.         }! c1 ]; G* x$ w+ H, |+ @) F
  84.       } else {  //fail retransmission once) f: U' O# W: T; H
  85.         if(fdcan1_send_fail.flag) {
    ; o% C; X7 @% L& @2 Q
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier, & k* c+ s2 T) K, C
  87.                           fdcan1_send_fail.TxHeader.DataLength,9 }5 ]' M# [7 X
  88.                           fdcan1_send_fail.TxData);3 Y! k, K) p! X/ u" D& A
  89.           fdcan1_send_fail.flag = 0;9 m+ B7 F3 |6 R: h+ i9 e9 \+ _
  90.         }& _( O! B" Q: }; o
  91.         if(fdcan2_send_fail.flag) {. Z" _0 s2 |9 W3 x
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier, 8 ^, h/ P4 x& \( F1 f+ i, g7 L
  93.                           fdcan2_send_fail.TxHeader.DataLength,
    8 S8 L! I9 T( `$ V- F
  94.                           fdcan2_send_fail.TxData);* B: r. ~. W% H# F
  95.           fdcan2_send_fail.flag = 0;9 G$ r) L$ X4 l- u
  96.         }
    * _5 l, r( ~2 E' ?
  97.         if(fdcan3_send_fail.flag) {4 |, [7 ]% O6 W2 A
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
    ) F- a# I; C) \1 Q: G, u/ M
  99.                           fdcan3_send_fail.TxHeader.DataLength,
    0 A5 L8 d6 i7 u6 {0 L' J9 C; G
  100.                           fdcan3_send_fail.TxData);
      }7 E6 \2 u9 y0 |/ ]0 |
  101.           fdcan3_send_fail.flag = 0;
    6 ?$ f, y. j4 K; L: ^3 {
  102.         }' I: X( O& t2 H" O1 ^2 A
  103.       }
    " @# I' k3 @' A, c! ^: w
  104.     }  c5 I. Q. G  H( Z; }' G& {
  105.   }
    ' Q! K2 c8 j9 Q! V- F
  106.   /* USER CODE END 3 */  1 }" J& h; V4 n' M# O2 ]# H, O
  107. }
复制代码
; s5 P6 B3 O# ]% I
fdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.
6 K& l9 o4 k( _4 M" R3 h
. `9 y9 N: k( b发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.4 I* x6 M. `# G. _/ w) f/ F

9 T1 k) z2 O6 G3 w; c这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.
4 @# p- e; q9 H1 k9 X* S3 g5 T9 W. `0 w8 T3 f
因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.& `( [- E8 E! G$ L3 s* m, n

/ o* c2 J- ]$ C1 H8 V7 J因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.7 [( t" y& p% l, Z. y
6 G. Z4 N; M: Y8 e* x
如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.
# }/ ?: c: v+ s% [8 p% T3 d9 q: B) ?4 B7 l9 M1 [: m0 J
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.
9 V/ s+ o' w8 f7 R
! M; Y7 I; M7 X$ ^程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.7 h* T& m9 E0 H% s* G

2 m; n) {2 _' U8 |( N+ ?! P3 N使用Xavier配合测试一下- s" |: R; {" v' H% w( f" }# v
把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:
3 _, F% ~) }- ~4 H& y5 S4 _# Q, g: N' h- ?( {! A
  1. #!/bin/sh" F, m3 _% e9 Y8 G9 \5 K3 Z% V

  2. % H  m4 `6 ?7 `( M& c9 H
  3. sudo modprobe can: n: [; F, g( D/ F+ {! U# N
  4. sudo modprobe can_raw
    , N/ A# L' ~% q3 x
  5. sudo modprobe mttcan
    . P. j8 x, A" f- ]
  6. ( M/ G5 G* f+ s+ w& n3 q  d! {
  7. sudo ip link set down can07 S  j; c& S* j# j: D
  8. sudo ip link set can0 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
      S5 ^, K) c' c8 D9 Z# d7 V
  9. sudo ip link set up can0 2 G0 d, d$ p# H. ]# A" U
  10. sudo ifconfig can0 txqueuelen 1000# |; m* }2 u% t2 m. n" Z" o+ @

  11. # J8 [3 g$ L0 E3 B1 X
  12. sudo ip link set down can1  p: L0 Z, K- {: s. x" s8 I: V
  13. sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100
    / s% Q* ~% @$ y9 P
  14. sudo ip link set up can1
    7 j5 o& a+ m+ R5 u) t0 e
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.: H! ]! a% a8 V( t0 n$ |
4 y) Z: {2 z# j# u2 E" O. X
restart-ms 100设置总线Bus-Off时, 100ms后重启.
. {; p( W! V" {, O- k8 t3 ~0 Q( f% u0 u8 ~$ [3 A
设置完后查看设置状态 ip -details -statistics link show can1:
+ q. Z$ z! s# I# ]9 Z/ e
' l/ i1 E( e) w
  1. $ ip -details -statistics link show can1
    / ]' A* Z" @. c7 X5 @
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
    : z- V, p4 ~4 F: r! ?' Q
  3.     link/can  promiscuity 0 " c5 d0 w: R7 }
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100
    . M6 a  B" C5 B' I9 n/ Q
  5.           bitrate 498701 sample-point 0.792 ' F6 ?; r8 c" v' B
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1% P) q8 W5 ]- x2 A% W% |
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1
    % Y6 N/ P0 \0 a* f( B; }
  8.           dbitrate 2021052 dsample-point 0.736 3 a- o7 `8 E$ w- E, m* }
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1* ]7 k+ N0 `5 Y4 k. q+ i
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1/ g# O, j: n& l$ \7 B
  11.           clock 38400000
      L3 Y( Q. V4 @8 J$ a2 [7 e; u5 v7 _
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off
    . X3 E; ~# w5 K
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    + U$ j9 f% {. ?+ q! _5 k6 _
  14.     RX: bytes  packets  errors  dropped overrun mcast   
    5 K  Q8 h* d+ S. w' u3 q. _' F
  15.     64578440   1013451  0       0       0       0      
    ( S+ r: h9 o& s" i6 B' G. O
  16.     TX: bytes  packets  errors  dropped carrier collsns
    $ x$ G- ^. ~5 S6 z8 R
  17.     952448     15914    0       0       0       0   
复制代码
位速率和采样点的些许误差测试并无影响.: U% M  P7 [/ R" t

* q! t- w) K2 C0 X: V6 {5 I使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:. Z7 ]$ C: ~  A0 E$ W9 y% N

  j( E: ]+ n/ c  m7 n
  1. (1613988959.105805)  can1  RX B -  123  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F# U: X0 w) e# _- ^0 K! v$ ~! `
  2. (1613988959.106191)  can1  RX B -  124  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F* h& N, ^2 O' V8 E
  3. (1613988959.106609)  can1  RX B -  125  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F$ C( [. f8 j# u4 z4 X
  4. (1613988959.107337)  can1  RX B -  12345678  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    & p0 h- Q! D5 ]2 Y: X! D
  5. (1613988959.107865)  can1  RX B -  12345679  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F% ~# u. z7 U1 ^. Z6 C$ o& Z4 y" K
  6. (1613988959.108332)  can1  RX B -  1234567A  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F1 S& a1 R. i  q& P% C
  7. (1613988959.115791)  can1  RX B -       123  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    " E1 y9 v7 d1 b% V8 @
  8. (1613988959.116215)  can1  RX B -       124  [64]  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F+ Z$ _. q6 C+ ]1 w7 c1 s4 L

  9. # @; Z# K; ?5 [8 s5 L( l' l
  10. ... & o1 j! ]0 S8 @' K* |

  11. # Y) T" ?. k0 k3 j% l. ~7 N; a5 T
  12. (1613988969.087131)  can1  RX B E  12345678  [64]  03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F: f9 i! P1 E; k5 Z( c* J$ M
  13. (1613988969.087612)  can1  RX B E  12345679  [64]  03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    5 W3 D* r, o6 ?# X* v
  14. (1613988969.088160)  can1  RX B E  1234567A  [64]  03 E6 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    ' `- a1 c& h7 t1 w$ t; z: Q
  15. (1613988969.095802)  can1  RX B E       123  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F) Z$ S  z; a$ x
  16. (1613988969.095935)  can1  RX B E       124  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    ) ]5 N& Q) i; B! }# [* @: F
  17. (1613988969.096294)  can1  RX B E       125  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F! h! Z9 p" t& B4 q( g- H/ a0 J
  18. (1613988969.097116)  can1  RX B E  12345678  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F  S  d2 I: R# i$ J5 J
  19. (1613988969.097604)  can1  RX B E  12345679  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F& U9 O! y) |& v9 c$ }( ?+ p
  20. (1613988969.098102)  can1  RX B E  1234567A  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
复制代码
. d0 ~0 ~3 r' j' r
这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.# p( g4 L% v6 t, x; _4 h

8 B; h: [4 I4 L$ _. d0 F) CXavier发送脚本, ##后面的3表示开启BRS和ESI:
, d$ g6 S2 ]: Z9 G  G. p2 t! q+ k- n; G5 a8 A+ l/ D- d7 H
  1. #!/bin/sh" S3 O  G7 y( S7 R8 {
  2. 3 d3 F2 H8 N4 {1 C
  3. while true; do( ]; y7 Z7 J4 Z  u
  4.     cansend can1 18FF0001##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.167 N; L) H7 \( P. O) ?, K* x3 P
  5.     cansend can1 18FF0002##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16# `$ \- l1 p; o- l* M. d9 T6 }
  6.     cansend can1 18FF0003##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16  
    ' V) p# W/ S0 _' T0 b; g) ?
  7.     cansend can1 18FF0004##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
    & @0 T7 B& {% H3 y
  8.     cansend can1 18FF0005##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16
    4 ~4 z1 j/ H3 M# H" ?
  9.     cansend can1 18FF0006##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16  7 |5 H" f5 \* k# M/ q
  10.     sleep 0.014 l, P6 M& m, U7 u% G4 q5 P
  11. done
复制代码

$ m) {* P  `2 E1 d+ S- \可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.
2 L- A5 d* A, ]6 y5 w3 X  ?2 i+ \2 ]( X( u% y
核心思想是:5 q* x! ^  ]9 H& ]

) g; Z# k' y) C2 v8 y: mMode 设置为Classic Master或者Classic Slave, 而不是FD1 p' M/ t  Y2 a4 R1 G9 ^- v
仲裁段和数据段的通信速率都设置为500Kbit/s; A# }- J9 f6 Z' z( @3 M
' w' G/ ^2 R$ Y& x( }" m

: A2 }3 ]" b  q0 V1 N5 V1 t/ B
; N0 c8 K" }" |, C5 A
收藏 评论0 发布时间:2021-11-11 22:00

举报

0个回答

所属标签

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