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

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

[复制链接]
STMCU小助手 发布时间:2021-11-11 22:00
本篇用起来, 连接关系如下:$ p: s3 }" a/ i) m% X
3 n; U( w. l$ I0 f; R0 i9 K0 c

20210222185812381.png


, O% e, ^' c& {% X' v( O% F; Y4 T0 Y+ S1 w0 }
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.9 ?  \4 m1 r/ Z' N! N3 `0 ?2 D

) Y& F* ]3 q) t6 _STM32工程搭建% j% _3 c, C  G/ j
STM32CubeMX配置步骤如下:, {( N8 U2 c& S

; x+ J8 }% @! y' r0 s4 RMCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx
2 f+ }. m* G+ x# _  \! o5 S5 {6 m# I9 v3 d7 V
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire8 y; C! L8 o: P) {

, K$ N: V$ T7 c2 ?: s  u( c" NPinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator
. f, ?( w' ]; H' \1 _/ N/ R+ V- a, o$ u  q+ H4 f3 P
Clock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):$ d( E2 o: E! J7 d% e" a- \

20210222185828575.png

$ A/ w. U) y4 b5 W9 B

20210222195952515.png

6 P6 u$ g8 L1 x) q2 T3 c

( d" }( S+ t& O3 y# V. s0 b3 x开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:
8 A1 p0 z, a; Q; k- A+ e# y" q3 @0 Q1 p  t

20210222185846781.png

: C" k' g0 K; H  U% {

6 h' X6 q1 I- ?! J/ ?6 p. d

20210222185905935.png

% A- ~9 [9 f7 n( m

3 Y2 U8 G- b+ o! W3 W, FLPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:. O) n8 f5 z, j1 s8 Q7 q
4 W5 n/ Q; ]+ A5 ]& O9 P  e

20210222185926920.png

; T# X) S- {  ~6 `7 d* b* M5 l8 T: R
# L/ i4 E8 Q9 T5 k7 u& L3 r
FDCAN1配置: 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:; H0 }4 G& O- s& S7 n! _: k
2 K& O/ J. g# q/ g) |

20210222185949803.png

4 o* g9 v. \" [: C( n

% o# c& {6 W: t' Q9 _6 O

20210222190005173.png


' J! c. S% O  u$ ~: ]# ^5 e; O1 Q' Q
! o7 ]! k# ^# P2 ]. VFDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:
  s' ^, D1 c4 Z
8 {! C  `0 N# a. v8 y6 E

20210222190054536.png


+ ^' E2 \' x* T. f. b+ w
+ S) P: z; E3 d& v, f) `Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.
# o1 `/ u7 t; W- L6 O( K3 N! x& L0 N# c! p+ T7 r
Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral
" ?8 J, d6 P# D- U  ~. V7 n6 A& G) F; X. P. Z+ \/ }
点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.& s/ d2 Q6 q) z$ O9 y$ W) g* i% N/ M
" D0 d/ r8 G7 D- ?
Keil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:
# g" D1 A0 \' J6 ^, P5 m
" |; P& j; i- M0 y. [$ V* ^1 a; xFlash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.
8 z3 e2 Z9 j! {* K# p6 ?Pack选项卡, 去掉默认的Enable勾选( N. r- T, I# e! T% J  w
到此配置结束. 下面是手动添加的代码详解. I5 }4 m: G! L5 e
$ R, D' H* B" w; E" x7 F1 f
串口配置
& k1 ^# s* a/ s! U1 X为 LPUART1 添加printf支持:, T! v( z7 Y0 D+ m
1 W9 H6 R0 \/ |% i: v3 R
  1. #include <stdio.h>3 r% Y. Z& z6 G; E! S0 J# E
  2. ; e( w. s# ]% N, M- G. L
  3. #ifdef __GNUC__
    ; W' S7 G( a; }9 b" h( k6 |! Q+ x+ e' s
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    $ k5 r5 R& M4 K' G3 _, k
  5. #else
      b: D5 ]# p& a; u& `) z
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    - C+ }5 ^* g$ L# N
  7. #endif /* __GNUC__ */
    , d4 m- m8 `& b

  8. " ^$ v0 w3 o6 A3 j$ \
  9. PUTCHAR_PROTOTYPE% ^7 |, T: {" @7 r
  10. {
    , R  n! R" _) \$ s% Q5 K
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);( q: b4 Y" U! d' g; t$ W
  12.   return ch;
复制代码
; Q8 t2 O$ J# j$ @! F4 @) R& j
100us定时器
5 a  ^4 s9 w/ E8 N因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.
( C4 U! G' I: _' {; \: e  D7 t1 W7 b4 C* Q5 D% I; l9 v2 q, |
  1. /* USER CODE BEGIN 2 */4 j( q- ~8 L* x5 f6 M. F- T7 e
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.3 x& x4 n- C4 a# Y" k% M% v# h
  3. /* USER CODE END 2 */3 J3 m; i; \# ~# b0 B3 o  c& K
  4.   g; D% J0 Q" H
  5. uint8_t tim6_flag = 0;
    * j7 R' d& N2 ~; A; o! c5 {
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) / v* x7 x4 t* l$ C: q8 L$ A; G* ~* r
  7. {
    $ O) ~2 B. ~8 q
  8.     if(htim->Instance == TIM6) {- g9 B6 D4 ?/ @6 c
  9.         tim6_flag = 1;6 E0 ~5 S1 Q  R; s9 X/ d1 g
  10.     }* l) t) t" }: {) t/ R
  11. }
复制代码

  a- v; h, N* r; J' U) n8 l2 K5 V( P; Y& ^FDCAN配置
) k7 C+ o+ n( S* s  V: [主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.
" |5 {7 S" e% C% c9 @& R4 `5 v6 K/ z- X
  1. FDCAN_FilterTypeDef sFilterConfig1;
    % t3 A+ \" [3 r* t+ X* s* L$ @* H" F$ |& D+ z
  2. " _: O' U2 Q0 u. Z2 n
  3. void fdcan1_config(void)* i% c5 N. ]( I% m: }) J
  4. {
    6 u9 ], U  p* g
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;
    , z7 j- {9 Y4 B& v- b! a
  6.   sFilterConfig1.FilterIndex = 0;6 L2 I: ?1 E, c: w" {6 w% G
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;% Z# v/ }. M1 }1 ]% U
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    5 a& f) F! t$ }
  9.   sFilterConfig1.FilterID1 = 0x00;
    % n0 m7 ]/ l0 A! @/ e
  10.   sFilterConfig1.FilterID2 = 0x7FF;. k  f) g6 O3 |, H
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK), g; X* V- ~+ q7 O% g' S% |
  12.   {
    ) y3 f) H5 Q; X6 J1 u: |9 Z3 E) l
  13.     Error_Handler();
    3 l0 q" _; [5 S' s9 O
  14.   }, |! W, P0 ^1 j6 W) j
  15. ) |* w2 N" y" \$ r6 r: ~  ?" @
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;7 _, W0 Q) s4 f7 C1 ?
  17.   sFilterConfig1.FilterIndex = 0;
    - j* [: i* i: E8 ]+ C
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    % h" @+ D  d: \* U1 Q
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    " M6 N* V9 w5 V3 I4 C" i. J
  20.   sFilterConfig1.FilterID1 = 0x00;
    ! j: L" @& q% S% C
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;/ C( T6 A8 W- w8 q
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    ' M9 c; d9 E: s/ N* T' W6 B
  23.   {
    * t+ A9 H5 k2 x  C6 g! `9 b0 k
  24.     Error_Handler();
    % i( Y+ Q3 L6 o; S
  25.   }
    * l+ ]. n) H/ Q& {5 |4 Z
  26. 5 \! l* T# a8 M: V6 @4 a
  27.   /* Configure global filter on both FDCAN instances:% }' ~) B4 N  C, ?) f7 x% A
  28.   Filter all remote frames with STD and EXT ID, c/ W$ N& e% |& L8 I
  29.   Reject non matching frames with STD ID and EXT ID */
    ' ^+ h) _7 X0 r: u; M- d
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)4 b: q2 Q0 |4 L. X' Q
  31.   {
    3 M- q5 a; w+ a" b: h% h
  32.     Error_Handler();
    # L5 o% Y3 B) _9 O; @4 Q; e* y/ G
  33.   }
      K# b. P: _3 E- E9 p# _

  34. ' J$ Q' H6 R8 x/ e; C- f$ [
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */& G+ Q7 e" k+ ]  }
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)! {5 i' n2 d  k" ^3 A" c% U. ~/ E
  37.   {9 e# ]: ?9 q; G
  38.     Error_Handler();
    3 G" A2 O% k$ }& \: `/ k$ }
  39.   }
    ! C- d. p" }& u8 z/ g! W
  40. 7 C# E* q  x1 f6 y/ E( u
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK). g! T# b6 N/ M9 m4 e5 N
  42.   {
    ' W( R+ \9 N" N: r' E1 ?8 S# y6 V
  43.     Error_Handler();
    8 U9 j! i5 m) i0 }( h+ i
  44.   }. l+ c& }2 ^, t3 o$ P3 y, j
  45. - ^8 p; V5 X7 F& k) A
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode.- n' T( k, t# y: T4 Y9 K7 n  _
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler( E# _% i" d6 A6 u- ]9 c! }- [
  48.         TdcFilter default recommended value: 0 */
    3 r( Z4 ~8 Z7 [4 g: I
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);" C# D; j" j% \3 G* f  p
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
    ' @" G# n8 v7 L4 y0 O
  51. 8 Z+ P8 m& e# n% _0 m' c
  52.   HAL_FDCAN_Start(&hfdcan1);
    * X8 @( z1 `5 U, O
  53. }
复制代码

- b/ }2 u2 j3 a$ @  y# ^这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
1 l: J+ j! G5 ~' r( d& k
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;1 j8 e1 z" X  E% W9 V
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;; |, c6 O1 ^( K
  3.   sFilterConfig1.FilterID1 = 0;
    ( A. `' G3 {' v
  4.   sFilterConfig1.FilterID2 = 0;
复制代码

& g8 G" J& p" O% m' W7 X用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.
8 J- w& J7 q  V" e6 e* E% h
' _$ Y+ B, ]) `1 @4 i- ?有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:. v2 J& p$ P9 m8 t

% }8 i! y$ l% L# u, s/ g
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码
3 T7 R, ~8 G1 R3 {5 ^  I
FDCAN2, FDCAN3的配置和FDCAN1类似.
: W: P9 ^$ E/ O4 m* b8 o! _: w- V- Y; E, }+ w1 R
Bus-Off处理0 c+ O- K! G! \% Z
如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:0 R2 T7 E1 G* P# u7 g. p; k

4 y% T# a$ d7 Q
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)# k# S0 ?- I! }0 i( }
  2. {
      H8 ~( `& C" c$ H
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);
    - @" o- Y: W/ G7 a( o
  4.   if(hfdcan->Instance == FDCAN1) {8 O- O) l/ @9 w8 h0 z9 Y8 i4 f
  5.     MX_FDCAN1_Init();
    3 T4 H- _" i' v' c5 `' p; D
  6.     fdcan1_config();3 e# e3 s  N& V8 g
  7.   } else if(hfdcan->Instance == FDCAN2) {
    + y$ |6 ~( ], }$ ?  N9 W
  8.     MX_FDCAN2_Init();8 O; B- U) }& F, G0 x. P  m: J0 p
  9.     fdcan2_config();
    2 `+ b/ x) w) x" b$ ~
  10.   } else if(hfdcan->Instance == FDCAN3) {- F1 |' X7 T, @2 M" u% v. @
  11.     MX_FDCAN3_Init();
      Q- D8 n. y% h
  12.     fdcan3_config();
    9 w- I9 w0 c( C7 z
  13.   } else {
    6 l! _% z; y6 p! D
  14.   }
    4 e( V* J9 `# |9 o5 M% m
  15. }
复制代码
( [3 |; J! b. p/ F
新消息接收处理
3 `7 v* `/ |: z; }8 ~& M直接把接收的消息通过2M波特率的串口打印出来.
, P$ d' D- L( Q; N' a6 g- E$ h. F; N
  1. FDCAN_RxHeaderTypeDef RxHeader1;# P7 D2 }& F  [
  2. FDCAN_RxHeaderTypeDef RxHeader2;  R, Y1 U* \! n: j; C
  3. FDCAN_RxHeaderTypeDef RxHeader3;
      S3 ?: a  u- j7 ]6 A, {# `' K
  4. " c/ n2 C# \+ W  \2 N
  5. //RxHeader1.DataLength => can_dlc5 I0 i, n* p: v$ I
  6. //0x00000 => 0 & m, u9 g6 L9 u7 v5 ^" u
  7. //0x10000 => 1 7 Y4 J' K3 n4 [: p2 x/ a
  8. //0x20000 => 2
    2 R: q! @- H) B$ t
  9. //0x30000 => 3 . W& e/ k' o5 m4 `" K9 z2 P5 _
  10. //0x40000 => 4 , `9 i6 N1 |8 T
  11. //0x50000 => 5 9 Q3 Z! B2 `* E9 M! N% u3 U
  12. //0x60000 => 6   m0 g1 P3 Q3 O9 }
  13. //0x70000 => 7
    . r5 Y" w4 K3 O/ p* B
  14. //0x80000 => 8
    0 L. m5 a  e# @9 n. C1 {: N
  15. //0x90000 => 12
    7 t' k0 V. n: O7 B% }$ @4 @
  16. //0xA0000 => 16
    5 O. m- k0 S$ R* ]2 n; o* E
  17. //0xB0000 => 201 }' e9 v* l! }. `5 W
  18. //0xC0000 => 24
    9 Q3 g" |1 Y9 P4 i0 }; b  ], n
  19. //0xD0000 => 32. w: I5 Z8 g2 _* n$ k+ n% L, Y
  20. //0xE0000 => 48- g( p2 c- z8 u: A
  21. //0xF0000 => 64
    ; n4 W$ ~* d% j6 _0 ?- m
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
    + P3 O" m$ F$ w, J" B5 v6 J
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)" L4 Q9 |! U" u2 K
  24. {
    . t* P' c0 q. m! l* R
  25.   return dlc2len[RxHeader_DataLength>>16];: c* m  u* ?8 A. R
  26. }
    ( W. V, _" v5 o0 G6 w) k

  27.   ~; {0 O6 E: m- V7 ]$ H! C
  28. uint8_t cnt = 0;
    . o7 o0 |4 x% k7 C0 z) O: {3 N  k
  29. uint8_t brs[] = {'-', 'B'};
    2 L% ~7 f5 N/ O' g: F5 `
  30. uint8_t esi[] = {'-', 'E'};% X; Q7 z! Z+ @1 {
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)  i5 {' l* D' Z$ m) {6 j3 V% d- p6 ]
  32. {* R1 L! C& C0 B
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {
    ) j1 q6 g6 F3 v! t& q1 I# x4 p1 l
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);# R2 t% p0 h$ ^- E! U: x5 `3 n& b
  35.     //RxHeader2.Identifier++;8 W2 j/ T: m/ m
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);
    0 @6 q' \5 V  w. l" w1 j- G
  37. - K# Y8 O3 z/ i- L# e
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    8 o/ e# A1 D' Y, ~1 v3 U; E
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));
    7 ^: E8 R: I2 Q! y! C
  40. 7 v9 r: u8 M, O6 [0 K1 A
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);" q$ }2 f% t% q1 |9 @7 Y
  42.     if (hfdcan->Instance == FDCAN1) {, o- b& ]' o# s0 w7 j
  43.                 printf("fdcan1, ");: l% q+ I, t1 k3 T$ x
  44.         } else if (hfdcan->Instance == FDCAN2) {
    4 k$ P9 d! B9 }& }, F$ |
  45.                 printf("fdcan2, ");* j! e1 W' P% I4 q
  46.         } else if (hfdcan->Instance == FDCAN3) {
    5 A+ L9 B  ~- B" O! |# u; ^
  47.                 printf("fdcan3, ");+ u% A5 X2 G1 r. d+ f9 e9 A* h
  48.         }9 X6 [+ K! K4 C4 Y8 |
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier,   M9 ~/ p1 n6 Y0 L2 ~$ I% r6 o
  50.                                   can_dlc2len(RxHeader1.DataLength), 8 z9 d) W) o, v) M0 D$ \
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],
    9 V0 I. {; d7 k* J' V2 R: y
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);; z* Z9 Y6 v4 |$ t: k3 I: Z
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {
    / Q1 f7 e9 l/ W1 v! N0 G# j
  54.       printf(" %02X", RxData1[cnt]);0 }$ t! q: p3 Q% w# i, @2 P7 ]
  55.     }8 A- ?) W9 y+ P# ]) p3 e
  56.     printf("\n\r");# g/ y4 o3 _& u4 [# u
  57. / V8 i( n" f" g; z1 G# J6 k
  58. 2 R! n; U# K1 \
  59.     //if (hfdcan->Instance == FDCAN1) {7 q: b4 @! }2 e+ i: z2 y
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    / P, T! b: R6 a) O1 G/ v) Y0 X
  61.     //  //echo$ k) Y- Y, a, J' t
  62.     //  RxHeader1.Identifier++;/ H5 O8 x& R# [! y4 X
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);1 J, _4 m1 l: t6 d  S3 ]! n
  64.     //} else if(hfdcan->Instance == FDCAN2) {) T5 G' e1 {4 S, j3 y
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);# Z2 b; u, L7 A
  66.     //  //echo
    % E5 k. o2 s/ W. s) `
  67.     //  RxHeader2.Identifier++;& X, o9 M+ D. n7 y% `
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);
    ' L, @% n4 f$ a& D, v
  69.     //} else if(hfdcan->Instance == FDCAN3) {. |4 W- d) C2 \4 |
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);
    9 E! Q1 S$ r$ j' u
  71.     //  //echo
    / d4 q! `6 d, D1 Q3 B4 |
  72.     //  RxHeader3.Identifier++;7 N) G( H$ {( G
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);
    0 k# }- h# `3 [. a9 Q8 R; ~
  74.     //} else {
    : |& ?9 }  y, Y" u) t% [% Y0 w
  75.     //  
    # [; i  j" t0 _3 K
  76.     //}
    & f6 L. q6 q! E, A/ V: k- ~, W8 _# ?- Z  L, ^
  77.   }
    # u; s! a# t+ a6 @. t3 T) B+ V
  78. }
复制代码

5 G# p* U' _6 B+ h  J( z& O+ m注意注释中 RxHeader.DataLength => can_dlc 的对应关系./ F% r4 ?6 p& A# O7 s

7 P2 h* w3 u0 d# Y2 u示例如图:
* G! |) r! m% Z# N) O5 c) {( _7 p4 m% \
20210222190024669.png
/ a. D3 Z# E6 O1 W

3 s2 N4 t+ B6 X" y7 Z9 k图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.8 s5 r# u$ Q0 x1 N& t" ^

, ?0 u# m/ ~1 y. g; W1 f3 Kprintf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.
2 Y8 j/ \9 ~3 r+ w+ a  p" \: t
  m5 {' }3 X* i; D3 Q  F发送处理
3 h( @, O4 O, \& F! X发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.6 G/ Y; U9 R5 t" C
+ ]0 x( c7 L  Z2 O$ ~8 e
  1. #include <string.h>" y3 R% |2 K% b& Y5 \
  2. 3 e4 ?& R* f& \) F
  3. FDCAN_TxHeaderTypeDef TxHeader1;: p8 n$ s( _2 p1 O4 _- W/ X: @
  4. FDCAN_TxHeaderTypeDef TxHeader2;
    ) ?* Z* v6 S1 {+ |
  5. FDCAN_TxHeaderTypeDef TxHeader3;
    6 X/ d+ U# e* o/ p7 h# ]' B0 o

  6. 7 {' P0 {+ W2 T6 F8 @' ~' v
  7. typedef struct {' ?% c' U. F. y/ p9 `5 X
  8.   uint8_t flag;
    0 c# g0 |( G9 k& `' P# m
  9.   FDCAN_TxHeaderTypeDef TxHeader;( ^: n- D) ?! h8 }- W7 L
  10.   uint8_t TxData[64];
    : a& S: x2 [& k- d3 W
  11. } FDCAN_SendFailTypeDef;/ K) m, N& `0 p
  12. & L1 ~' ?# R% [  g9 B' k3 c
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};& ~' I! t9 Y2 c3 H9 ~+ u9 B, r9 b
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};# E8 I9 P3 r) U% }( W6 R
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};5 u. D3 A0 {& o- J5 \
  16. - w1 {( c  p4 K" l
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])
    : o8 Z3 c; R9 E* [; x
  18. {) H# P7 L( y  s2 i; T) I7 Z% w
  19.   TxHeader1.Identifier = can_id;
    5 q5 p9 a9 g* T/ e$ _$ O
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;2 R" R4 g' ~& w3 q/ T
  21.   if(can_id < 0x800) {  //exactly not right
    " r" N* G  x3 R, {7 z6 _; P, f
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;- |& {, {2 r7 Y7 J# |9 Z7 N
  23.   }
    0 a( c. x- `- N: r3 _
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;% v; t8 N: D( m6 M
  25.   TxHeader1.DataLength = DataLength;
    % G0 ~3 J0 @" r9 g
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;8 W/ j' \8 H/ N+ V) k0 b
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
    3 \6 ^( {8 A+ ~2 }  l0 f
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;
    , D7 Q1 h0 T* q; R$ N) U4 R; f
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;  R# ^3 N6 u# U( n
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use
    " o, S+ i: i- P' w& D1 o, ]/ h5 t
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {
    1 P; A4 A: q" w' ]
  32.     fdcan1_send_fail.flag = 1;/ s: s8 J. d& t8 u" W& x+ @
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));8 K" a, d( _& O0 V$ I3 U7 \
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));( F$ j8 t- d2 I1 |4 {7 L  N2 s
  35.   }
    $ ^" c6 o  k* j9 i
  36. }- I9 |- y- M0 r
  37. 9 t* r  Q0 r6 L
  38. int main(void)2 L2 S* e2 l( h7 a2 C
  39. {( {: P  R! y, F' l1 ?
  40.   ...
    0 d* n8 l% C1 Q! \5 s; a
  41.   /* USER CODE BEGIN 2 */
    ' o' i: M' J0 X; `7 {1 d" v8 z
  42.   fdcan1_config();% `7 V) ]/ d; y/ c+ B+ v0 G% y) s
  43.   fdcan2_config();
    : x, y% q7 `- n" ]% l, F6 A
  44.   fdcan3_config();
    0 v# k& P1 M8 S
  45. ( U3 H' x6 l4 n( Y8 V
  46.   for(uint8_t i = 0; i < 64; i++) {
    0 a  M: `6 y, L+ i' c" ?
  47.     TxData1<i> = i;</i>
    / J$ s$ y: k  V8 f# o: Q  G+ F4 H, |
  48. <i>    TxData2 = i;</i>
    ! C6 y; Y5 w  I6 Z# D3 Y0 d4 k
  49. <i>    TxData3</i><i> = i;
    , b' [( U# I3 R
  50.   }
    4 n7 d- \7 u. ]2 i5 E

  51.   N4 U& g6 S" g: {1 `
  52.   HAL_TIM_Base_Start_IT(&htim6);# a) t* c8 q4 h) k
  53.   </i>uint32_t count = 0;1 G5 |! w) c' C9 n
  54.   uint32_t cnt_100us = 0;
    - t# A3 }/ G2 D3 u  {9 L! P, V: a; ?
  55.   uint32_t cnt_500us = 0;2 _, v' j3 h& G3 r  B
  56.   /* USER CODE END 2 */# C$ c) V1 n0 i3 g

  57. ' o1 {8 g' ^4 M! Z
  58.   /* Infinite loop */
    $ S+ c+ Q- c/ k& f
  59.   /* USER CODE BEGIN WHILE */
    6 H  a+ I2 j! V$ X  j
  60.   while (1)
    1 }. K* ^- v0 D' w
  61.   {/ Z( B  i4 p4 F/ h3 ^
  62.     /* USER CODE END WHILE */0 k0 H7 t+ A) A& [+ N

  63. 3 Q) ~: w# K$ O0 z) i7 b/ k/ Z8 Z" {  u
  64.     /* USER CODE BEGIN 3 */( f$ H7 S, \6 }) ]+ l: l5 D& x
  65.     if(tim6_flag && count < 1000) {
    ( t0 q# V" S* }5 y) ~
  66.       tim6_flag = 0;. }! H+ D* D' }* r* P
  67.       TxData1[0] = count >> 8 & 0xFF;7 [* V0 a' o$ J4 @
  68.       TxData1[1] = count & 0xFF;# T$ k/ N* |; h2 |

  69. 7 @* n$ p' D/ N  A
  70.       ++cnt_100us;- F( v) o' \7 v4 K* F# `
  71.       cnt_500us = cnt_100us / 5;/ }2 ]* r2 L0 t  E. y0 `$ l
  72.       if(cnt_500us && (cnt_100us%5==0) ) {
    * I+ B( H+ _. ~6 K
  73.         switch(cnt_500us) {' T; i7 L5 t9 N% K$ _; ]- M2 Y
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1); * b+ ^! s. u& g" i  R6 ?8 `9 q$ N
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);
    " B- J1 K7 Y8 R" }
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;! R/ h; o* J/ K3 ^( O
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;
    ) o4 K, G- `/ X* G/ W& Z- }
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;
    9 O2 q* V4 a3 W1 z- y1 [- E+ o
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;
    - Z5 F& Q- E) \5 H
  80.           case 7: /* next send */ break;
    . G% j, C' ~  F7 s% D( S
  81.           case 8: break;
    , S1 N* H; |$ B3 [+ a3 L( i' L
  82.           case 20: ++count; cnt_100us = 0; break; //10ms$ \! a' S3 S! e3 F, m6 j
  83.         }
    . E  i% o0 o- j0 U( y& t
  84.       } else {  //fail retransmission once( |3 s1 @; ]: E/ }7 p. s4 ?
  85.         if(fdcan1_send_fail.flag) {' N) ~2 Z$ h' l4 g
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier, 4 v; T6 J( X/ i+ {$ R: h
  87.                           fdcan1_send_fail.TxHeader.DataLength,
    - ]' b) K6 c) V7 H
  88.                           fdcan1_send_fail.TxData);9 j( p: B8 K" P! S- }. \. W
  89.           fdcan1_send_fail.flag = 0;! e% V" w8 }1 B6 N/ M0 d5 C
  90.         }
    ' _9 Y* J% M1 g! d5 z8 J
  91.         if(fdcan2_send_fail.flag) {
    7 @- o- B! Y! W9 N# U& o! n2 u' i
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier, 4 P5 j* w& U* m; U% e' H! |: r
  93.                           fdcan2_send_fail.TxHeader.DataLength,
      W$ R/ m$ ~7 j( e
  94.                           fdcan2_send_fail.TxData);
    8 J5 J  B# u: U4 x% M' |' i3 Y7 y
  95.           fdcan2_send_fail.flag = 0;1 K( ?' _& k: q- O# s) n3 Y' r8 t# W1 x
  96.         }1 g  h" U) z) o( u# y$ ^3 Y# S
  97.         if(fdcan3_send_fail.flag) {
    , j3 ?  l- `2 B9 n
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
    ; }6 E& I! B  A! x
  99.                           fdcan3_send_fail.TxHeader.DataLength,
    1 q- a) @' A% \5 n7 S' \7 E) w! a
  100.                           fdcan3_send_fail.TxData);( P+ R/ ]* R4 y2 E
  101.           fdcan3_send_fail.flag = 0;) C1 w1 U7 Q/ M
  102.         }$ E2 _$ u0 S4 _: t9 [
  103.       }
    4 H. D8 l, l4 j7 S
  104.     }. D( p- o, b' Y. v# m& a5 i
  105.   }5 W. k2 x* r$ j9 A( j+ w9 N
  106.   /* USER CODE END 3 */  
    2 P- A" n! J: {6 G, Y( M3 P- y7 I
  107. }
复制代码

: \4 ?* ~6 l6 A+ Q; \/ {fdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.
! }9 U' J1 |5 A% Q4 U, X# E4 H% X! R# C8 ]$ c' c& V, H
发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.
- t; W* X3 O2 k1 Q! Y% a, v0 r3 v
8 `1 ?& e: \% }  @% R) S这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.$ n; b7 s3 G/ @' X, ?: `( ]

+ F5 g8 q! Y4 b! m因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧., ?) p% P; v2 G. b, n. F
4 E& {8 {. v# Y0 B
因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.
9 n5 ~: \9 Q: f" c0 B/ c4 Z: L
0 z, t/ D5 z- `: \( A如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.
9 @: \, `* z& y6 k6 T; W8 t8 p5 ~& l) p% O
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.
  z& }: y6 u$ u
1 \+ e1 k7 V% m* L# g- I5 V程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.) x# y2 p/ b: a0 X* ?; A

; k) Q  T* j8 c0 U使用Xavier配合测试一下
4 A" f) p3 J5 S7 ~% ^把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:
5 v9 j0 U% i  b6 q4 y9 ~4 P+ O, P2 j4 t9 [5 X* q
  1. #!/bin/sh
    1 N, x2 j5 p+ j7 z! }

  2. 6 ~2 n% _$ {9 t* J
  3. sudo modprobe can
    ) j+ U3 `% c" d# e
  4. sudo modprobe can_raw# `0 |0 [* O! k+ k$ v$ {  P
  5. sudo modprobe mttcan
    : V4 S5 d) w4 g: P% t: s2 ^
  6. * M4 l+ Z1 x" l. J, z1 V/ _6 {7 ^
  7. sudo ip link set down can0/ w( b$ Z* E" t* Y, @7 R  t
  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
    7 V9 r: H6 A) J# Y% L! l
  9. sudo ip link set up can0
    1 A7 @6 H' ~+ `8 J
  10. sudo ifconfig can0 txqueuelen 1000
    - Z7 q% G( ^: g0 n1 k( _* }. i3 C

  11. 0 n( K" U0 m7 W' E2 Y
  12. sudo ip link set down can1; Z7 k- _# G2 g1 H: z3 N0 p9 O7 C
  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
    ! s3 L: v9 _/ k2 K/ c( I' x/ [3 n
  14. sudo ip link set up can1
    ( q' h1 }" j' W# }& J4 s) B
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.
" j5 {8 u+ Q' g9 B8 v. S4 h
$ h1 N* K1 G- D4 G) g5 m6 ~( jrestart-ms 100设置总线Bus-Off时, 100ms后重启.5 ?- p. t0 X- \7 X" z& {% p
) y4 U9 \; D2 |4 v) H0 y; K: m; s, E
设置完后查看设置状态 ip -details -statistics link show can1:, d4 S5 ]! @4 W+ L

9 ?0 I. z# l1 I: E2 M! g
  1. $ ip -details -statistics link show can14 P1 i1 U9 y2 T  U" B
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
    , }' }) }" R! v' S* O
  3.     link/can  promiscuity 0
    ! w8 L- |7 }* q! h7 O
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100 9 \' V' d' k' a7 }
  5.           bitrate 498701 sample-point 0.792 . Z2 X7 N, Z; H. ?% D1 u2 ]
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1
    - X  E( L2 v$ e
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1
    8 E' g8 E" A' @" E% O! J; @
  8.           dbitrate 2021052 dsample-point 0.736
    ! p5 g" `6 K# _/ c- A/ J; ?# S6 z
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1: A& w/ G/ }7 k. S" o
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1
    7 X8 o/ k9 M& o& `0 j+ u
  11.           clock 384000001 J5 D; D# {+ d1 p! A
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off
    5 n, R$ X9 w) q8 P: [
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 1 K) x8 _1 r  k
  14.     RX: bytes  packets  errors  dropped overrun mcast   
    1 x2 ^! k7 d+ D$ K- P( ?% k
  15.     64578440   1013451  0       0       0       0       / c' Q/ T0 w  g8 v
  16.     TX: bytes  packets  errors  dropped carrier collsns # ?; d! `( ]* M2 v0 ]0 |: d% ~; s
  17.     952448     15914    0       0       0       0   
复制代码
位速率和采样点的些许误差测试并无影响.- d2 H7 g- f! v# F/ X, \

( \& t9 {1 H, E# G' b3 p7 d+ m" I1 J使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:" Q! o: r& k$ W: X! M0 i$ d% |
4 E, w- E+ r2 E& d2 J8 k
  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 3F7 M+ b5 q  z' d5 E
  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
    & J0 x( E+ b% [% F4 q6 ]( N; F
  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
    + e/ X) a% O/ U6 |( d
  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. O; |7 N5 a* V5 Z; m! `
  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
      ?$ y5 C$ W. L" ?# {) c
  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 3F
    , j! E3 b+ L3 C' i5 o! j
  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# U0 P9 z& h( l
  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 3F1 F! u; F6 ^" k& |' T
  9. 7 V" B4 c, ^% l( f1 p0 p
  10. ...
      Q; x) j9 u6 c4 {

  11. $ O6 e" M3 T" E8 R# F
  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" N  h, a4 i4 r* p  \$ o
  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
    ( |! N+ u% D! j* f) f& m7 K
  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
    2 }: _  I/ j0 |
  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 3F0 ?$ `, D& \5 L
  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 3F0 a$ ?4 \$ i) `  m0 p: A
  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* T8 ^. Z  M: \8 y6 @" U
  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 3F0 {$ q- B6 A2 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 3F1 I8 g6 ~4 `3 i4 ]6 E! Y$ h- W
  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
复制代码

, m. P# ]% w& P) \) e这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
0 A; _$ E+ |# s4 w$ ^
+ a5 l/ R7 y: fXavier发送脚本, ##后面的3表示开启BRS和ESI:  p& ~& c! _# u7 O# V0 Q& f
% Y8 k* O0 H' x+ R  G" {
  1. #!/bin/sh4 p( D, o3 {8 `* c0 l$ D
  2. 1 i3 \8 Q/ @+ q$ R) ?
  3. while true; do5 @! ~* L/ ?' E- h+ G* B
  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.16
    # U) a6 H7 U9 N
  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
    " E7 W) V: }2 ^# ?  L3 |$ k
  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  
    4 H8 b" ~( J( w. ~
  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
    . _+ u1 G8 l( S- X; \: ?( [
  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
    ! M# \* R# J! d6 P' O+ f
  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 T8 l. H6 O* C& x" s" `% z
  10.     sleep 0.01
    " a! c) q! o; T9 a3 P2 P# I7 W
  11. done
复制代码

3 k& f% U$ ^7 S8 t& X2 F可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.
/ j4 K2 J- \# H1 b: g1 \# J4 O2 Y, m( m6 x1 ?
核心思想是:
5 x* h. [( S; R
6 c* o9 d. K" i& LMode 设置为Classic Master或者Classic Slave, 而不是FD" p* N6 d/ Z/ Y
仲裁段和数据段的通信速率都设置为500Kbit/s& M  L/ S& c( b% e, [
* I1 j' u" y7 `& b4 a7 K5 y
- c- F- o1 r& _5 h

; O! |% s' s$ B# r( z& Z' I
收藏 评论0 发布时间:2021-11-11 22:00

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版