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

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

[复制链接]
STMCU小助手 发布时间:2021-11-11 22:00
本篇用起来, 连接关系如下:
- E  X0 z- q$ I/ p) r0 {, z) L
% R8 S# l3 j. k" g' O8 N4 L

20210222185812381.png

. k$ ^1 n0 V1 a& |6 r
! a. _8 P9 R( m: @1 \$ F
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.
! e; y4 V: K6 J7 H
( {& {5 [6 D3 o$ uSTM32工程搭建! G8 ^/ Y4 [3 p5 c
STM32CubeMX配置步骤如下:6 f1 s: N5 h+ |* `  k% `# l
0 Z- R5 @8 b" t1 y" c! _& p- h
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx" _- G# X9 {) q
6 H" t. S* o; }  f' I
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire
, Y+ C6 w9 ^7 W: V' i/ t* P! A  [
9 B0 K( v3 w6 U6 C/ Z; APinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator
6 l  G( b: c7 k) ]
5 o, n& g2 I+ B% ?$ i1 D2 F! qClock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):
+ _0 y; b/ R( ]' M

20210222185828575.png


9 s5 @9 P" D) v8 A( {) D. `6 o' N

20210222195952515.png


0 A* r( y. ?- A8 z5 y$ y8 a1 U" X- I- `! H- o; }1 d
开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:1 C, y  e/ [6 C2 B7 |7 n

4 i' K% g  O# b0 ^. m

20210222185846781.png


' e; D5 a% d$ |' W2 O7 z" }/ _. b/ j4 K' J5 w5 o* s5 b" V

20210222185905935.png

' f' P8 G0 \5 n7 O
/ h% ~3 p! e& J# D4 w% |) D
LPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:2 ^5 N' l8 F7 p& U

( E' s6 j0 C. Z. s& P! O

20210222185926920.png

2 Y# a# h% r/ `4 i5 v: l: [
! _& f0 M$ F, j; S2 I# W6 ^+ Y6 h
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:, g6 @, ]5 x, p# o8 D: r: q

0 m9 }7 `! I* ]* O

20210222185949803.png


' s$ U5 g6 t8 E2 k0 X
8 R0 N+ A5 l6 ^0 R$ e9 p

20210222190005173.png

% ^. S+ P- g. S8 h* V2 A) D
4 r3 O& z# n8 [& |) J& D9 `0 B
FDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:
) \6 e. |1 z9 y
/ r! @* q- x# C# i1 o' R

20210222190054536.png

6 C6 O6 e9 H& |. C) g. a+ N

* }; }% y; ^0 Z8 T+ Z2 z, F. jProject Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.
- \# t: k* A% n5 o0 h& g
% h" m4 E9 `# K' W& A6 PProject Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral
8 H5 O3 y- F% }- a  d8 }& r1 v0 [6 }- R7 Z5 w
点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.# _8 V7 E' o5 h: z

7 ?% J) t, s% ?/ E) E8 pKeil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:! L& f6 V  Q9 m% u& |* u7 z$ W! [
1 [, F. E0 j; V
Flash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.
) k, k* n% u# I: zPack选项卡, 去掉默认的Enable勾选* g9 ?0 ~( k  k. X" }+ b" D5 z; @
到此配置结束. 下面是手动添加的代码详解7 G! {! e/ y2 P- S2 `' ?( b7 a
$ W& Q4 f% L8 B' }; a, C/ W" ]
串口配置1 t4 o& T. f5 @6 Q# L/ o& y
为 LPUART1 添加printf支持:
; y" K7 Q( |! ^8 a8 b
/ K- m2 l3 f  A
  1. #include <stdio.h>& {% _4 q+ y2 d' n$ k  c% L
  2. 0 |6 k2 e* }3 u
  3. #ifdef __GNUC__0 X3 ]. z2 G" T" h
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    * Q/ t" d6 Z5 T( T9 R2 z; S9 _
  5. #else
    ; F) |! ?% j' ]: ^! X/ @  ^
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    5 C% x0 o- {' s
  7. #endif /* __GNUC__ */
    % m% g" s! k3 N1 Y( j
  8. % G) x: H/ |" n% z$ q
  9. PUTCHAR_PROTOTYPE! T' e  ^4 ]5 n" W* Y5 J- b+ `
  10. {
    " P; O. ^6 e0 e& }+ ?$ N
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
    % a$ S# P8 E7 z2 Y; K# `
  12.   return ch;
复制代码
+ A# V$ o" R7 W- H
100us定时器
' y  L! k: j" [" m因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.
, b( m& o  |6 c- ^# {7 g3 }& W, ^4 K, ^, L& s8 w, V6 {
  1. /* USER CODE BEGIN 2 */7 F( l9 n2 {% r: R0 B
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.
    9 R' w3 o: _5 ?* c0 t- l/ u
  3. /* USER CODE END 2 */
    , o+ ]9 j8 i: A; x& s6 G/ G

  4. ; n: Z& g& P% x9 _
  5. uint8_t tim6_flag = 0;
    6 K+ O/ a1 T+ M/ J7 g' K  n" v
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) " x/ z. E! _3 X$ C  y8 j
  7. {
    ! }$ B# m8 s! P3 U. I! w
  8.     if(htim->Instance == TIM6) {
    4 A8 x- y; }' z* z1 u6 O4 P) Q
  9.         tim6_flag = 1;
      G( a- v; d" g- v* A3 T2 W
  10.     }
    7 J: P$ `, R5 m( x$ C  d, f
  11. }
复制代码
8 e) P1 z3 O& I) p9 ?8 ]% E1 v
FDCAN配置
6 f  d' J! m/ k, i, D2 J7 x主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.
7 Q0 p/ i/ Q% V% @% [$ D& \. Q9 L3 R7 q, Y* f/ U/ ], @7 K
  1. FDCAN_FilterTypeDef sFilterConfig1;# `8 j* i. L4 n8 q1 }' `

  2. " R2 d% u8 G7 y; a
  3. void fdcan1_config(void)- A" S& o  g; w2 u
  4. {& ^2 l' ~3 W4 a* A+ p  [3 W
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;
    1 b) {( U' {( Y* e3 ^/ ^0 @
  6.   sFilterConfig1.FilterIndex = 0;) q! f  a" G! X4 E/ w1 T
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    8 N& v+ Z8 r# K/ w* L
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    # S+ i) e0 z- ]; g2 I6 A8 U* E
  9.   sFilterConfig1.FilterID1 = 0x00;, K/ r7 h. I2 i- M
  10.   sFilterConfig1.FilterID2 = 0x7FF;
    + p7 g' D) J. a6 P" o5 \/ T
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    " a4 v; ~. o& c+ {) V4 o
  12.   {  n- l) F* a; O" _9 g3 t* l
  13.     Error_Handler();% P& K5 D$ v2 B$ o: c
  14.   }
    : n  @! _; l/ W  q
  15. ; z8 d) @/ k# c- g: d
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;/ s+ f8 x8 r0 D$ ?- p6 ?
  17.   sFilterConfig1.FilterIndex = 0;
    + j8 H8 ?, ^% U9 j
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    5 J: |2 k' S. Y( N& ]5 o" S
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;8 J! h% @/ V/ j' H- V4 V0 j
  20.   sFilterConfig1.FilterID1 = 0x00;6 t, ~6 J$ D/ d* ?- y2 ]0 u. z  j5 r
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;
    & u& t4 k" x' q* s4 M" J! ~
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    % z. z6 e. V% W8 h0 z
  23.   {1 K! s# L2 {" }8 ?1 F
  24.     Error_Handler();! ~4 u3 ?$ o0 b+ N: w
  25.   }
    # y% t1 e; v2 ?# j; F6 o
  26. 3 [  h" L- w3 q0 \
  27.   /* Configure global filter on both FDCAN instances:9 h& N9 N# }+ E9 ~5 z* P
  28.   Filter all remote frames with STD and EXT ID
    ' |9 O7 r4 Q4 @. I6 Y# `7 c# R$ ?
  29.   Reject non matching frames with STD ID and EXT ID */
    5 n5 P8 j  G, A" r! y! s' g
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
    ( \7 T6 `, F% g/ z6 S
  31.   {$ k5 W' p0 U) }! j
  32.     Error_Handler();
    5 c( }% J! B% C3 w  G
  33.   }. l& k& l1 C" R
  34.   m, \9 T' d4 p# ~9 Q. B* J. A9 \
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */7 h! m! ~; M" ^( g# o
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)! H' |8 n. n; M# y+ h
  37.   {
    ; X* L' t, M: c$ ~) C3 n4 e
  38.     Error_Handler();
    " w( V  e+ L4 t2 m0 J/ z
  39.   }
    + r2 f  S0 D  T  {" u' L; j1 n. U
  40. & X& d" E) f6 g7 i& `+ p' ?% [8 A
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
    4 h3 W5 N. M" r# `8 W
  42.   {: o/ F4 g7 r: y* z( q  Y
  43.     Error_Handler();
    & T' u. j2 O! Z% l6 X9 i
  44.   }$ B# s$ \- a/ p" I0 q$ Q; i( A
  45. 1 {( I% L+ _8 G) \( P8 w. e
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode.$ ~/ c9 J2 {# V& I/ d6 l. E; t
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler0 M" N( Z9 t; T0 I! w# K) M
  48.         TdcFilter default recommended value: 0 */+ R% `3 H4 L* V0 ^, j: t
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
    " A& \' Z# ]! ~$ [% z: _4 ~. O
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
    : v; V3 k4 |/ R4 {' u
  51. ) \& B! e9 S# [
  52.   HAL_FDCAN_Start(&hfdcan1);
    ; X8 f' _1 ]/ B& U! F
  53. }
复制代码
6 M, k" x1 s* w
这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
" A/ z: z! }# z) X8 U, c  L
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;# i. A/ e9 O; a* i# p3 Q" y
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    # u; Z8 S( p3 A( [! e% A" q
  3.   sFilterConfig1.FilterID1 = 0;8 W# p/ U  B6 S" }
  4.   sFilterConfig1.FilterID2 = 0;
复制代码
3 @& }5 z4 {8 d9 s! N
用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.
9 }8 G1 i+ |, U# d8 q* h9 X1 ]# D. ]& x$ ?
有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:
# y. J: b+ Y0 n/ A* Z; B: y% P6 C8 ^8 h, r- m( V2 ?% I5 e+ b* g
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码
9 u# P- z/ Y5 \( V
FDCAN2, FDCAN3的配置和FDCAN1类似.
+ @8 h. N* s, ?* Z
: n  h- x; B! j- u; oBus-Off处理
4 p5 t( \4 o. {! e. Z/ J8 u/ E如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:
- I4 r. \- z4 H% n. E1 x- v4 T9 W8 k* [( P( A. f: T3 R2 f
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
    0 x) R3 |* f" J6 \4 c4 I+ C# ^
  2. {
    . E$ Q3 ]3 |5 U# z$ F
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);1 A6 e% |5 }! W9 t. e+ a& L% }7 t
  4.   if(hfdcan->Instance == FDCAN1) {
    : y4 f6 l0 P1 q
  5.     MX_FDCAN1_Init();9 \2 e' ~9 V3 D# J( U; S
  6.     fdcan1_config();
      ~5 m7 f& Z1 I  W1 J. K* o9 X/ l+ t! c2 t
  7.   } else if(hfdcan->Instance == FDCAN2) {2 y+ O' t0 H! ~1 y" g! j2 D% c
  8.     MX_FDCAN2_Init();
    4 n/ Y: `0 Z& B3 N
  9.     fdcan2_config();; ]! Y' g  I4 x  l- D7 m- d. _3 y
  10.   } else if(hfdcan->Instance == FDCAN3) {
    + t; w/ M  m$ Y* n
  11.     MX_FDCAN3_Init();
    & ?1 f( }- Y" i& e9 f
  12.     fdcan3_config();
    ) _0 P/ d( ^5 M
  13.   } else {
    3 N" L$ h; [& l; h' M3 r' a
  14.   }
    6 S, }( k! }# n+ U
  15. }
复制代码
5 x$ P9 d0 P" I! f* _) N4 C  G) D
新消息接收处理
% ~# B; B5 c# ~直接把接收的消息通过2M波特率的串口打印出来.$ W( [1 Y4 n# U

* T5 w- e' P  t
  1. FDCAN_RxHeaderTypeDef RxHeader1;6 E/ ^: L8 q- K2 Z
  2. FDCAN_RxHeaderTypeDef RxHeader2;
    - o, G+ f' a1 O! U& ~; v
  3. FDCAN_RxHeaderTypeDef RxHeader3;5 \& T8 w/ O$ V! i( V  s1 F
  4. 5 f1 T  |2 `) O0 h  u  m, ^% ]
  5. //RxHeader1.DataLength => can_dlc3 X& o1 |. \9 D# Z5 e$ w0 u
  6. //0x00000 => 0 % T0 U4 U. l+ K7 R5 }2 U& |
  7. //0x10000 => 1
    ) o% J( n2 O5 F1 p* h; E
  8. //0x20000 => 2 0 T  g+ O1 J6 v4 c2 [  d( g
  9. //0x30000 => 3
    & I" d1 I" [  ?1 V; V) N1 R& Q
  10. //0x40000 => 4
    ) m( a6 F- P9 q4 E
  11. //0x50000 => 5
    ; g* I. |, a8 {* ]4 B$ J
  12. //0x60000 => 6
    8 f* ?! Q& H, t4 q' Z* p* B/ }
  13. //0x70000 => 7
    ) B; x: ?9 Q4 |2 w* P. T
  14. //0x80000 => 8
    * u' `- @1 u" y/ m. @4 N; ?& Z
  15. //0x90000 => 12
    - }, K) C4 Z9 E0 y' I- ^1 A
  16. //0xA0000 => 16
    , ]3 Y4 [4 g" W) d! o# `
  17. //0xB0000 => 20' A$ m4 X/ M+ j3 J  K
  18. //0xC0000 => 24
      N- R: s+ S& Y2 E) J1 @
  19. //0xD0000 => 32& g& e6 x0 X& f) m# K# p  q
  20. //0xE0000 => 48
    - ?$ `. \' B8 e& r8 {. ?* _4 V$ q
  21. //0xF0000 => 64( H3 U+ L7 x3 q% f( q( }, G# l
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};3 \2 _2 J* g" ?! y3 i
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)
    6 p8 e; F8 K& z7 Y& A7 t- |
  24. {  E- I* F! H' ^$ S! z2 _% z
  25.   return dlc2len[RxHeader_DataLength>>16];
    ' A' m# d+ b! B* f! h
  26. }
    : ~: x4 O- l/ c# h; k3 R4 e% M
  27. ( _% L/ W5 O/ |0 R% ~: d; T0 O, T
  28. uint8_t cnt = 0;
      I& a0 O- X. L# r6 j8 i1 K
  29. uint8_t brs[] = {'-', 'B'};
    0 P* ]) B2 [: d2 T2 _8 e
  30. uint8_t esi[] = {'-', 'E'};* C' M" A/ E/ e* a" {; ~, g+ Q/ [
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)* p- n5 p$ B5 R
  32. {' c% z6 E8 @: g8 w9 Y
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {$ ^: B+ Z. n3 b
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);) P. Z& @) ]7 \( X
  35.     //RxHeader2.Identifier++;
    $ _+ I8 l, f; @1 V# Z8 N
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);3 }4 v1 y7 R! [' q' X) ~+ H, L
  37. # j4 P' p. x5 ?/ S3 z" A
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);. O; \$ f* H+ Z, @' s
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));1 m( a# r* a2 V. L0 ]
  40. 3 G* K4 r5 c' j: e: c
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);0 N( C+ [1 R/ f4 q9 z8 j; \
  42.     if (hfdcan->Instance == FDCAN1) {6 u6 F2 t6 g1 B; {6 g; e
  43.                 printf("fdcan1, ");
    6 [' l  m$ A" S! U6 G. q
  44.         } else if (hfdcan->Instance == FDCAN2) {
    7 X- P' A/ j1 @$ E. D9 |
  45.                 printf("fdcan2, ");5 l6 [. Z: ?4 n& z8 n# }
  46.         } else if (hfdcan->Instance == FDCAN3) {
    & R4 k! \) \5 }$ v; B2 T& {( j) Z, G
  47.                 printf("fdcan3, ");8 l2 h+ O; I. e0 O( J" y
  48.         }9 {/ j* ^: k, Y  \$ S. j, y
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier, % r- \0 F- X$ T$ w$ t
  50.                                   can_dlc2len(RxHeader1.DataLength), & P8 B: M! k7 R8 x, \! B; ]% K
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],) z, ]" d1 `/ g) F  w: [
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);
    - D2 V$ s4 _+ _
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {
    & q3 p7 C5 P6 G
  54.       printf(" %02X", RxData1[cnt]);
    7 F+ S0 |" H3 a: r0 J4 L
  55.     }+ ?+ [& E" y6 Z. S; _7 t, H
  56.     printf("\n\r");1 D( @+ a: o( k, U6 A
  57. ) M% d9 p% g; {) n3 Z6 ^

  58. 4 g/ w" K0 v2 A: M; r
  59.     //if (hfdcan->Instance == FDCAN1) {
    : Z$ K3 B# z% p3 P) Y6 ?3 W
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);$ R& J. n* j) b: g1 h0 V9 h' `
  61.     //  //echo
    6 q2 O1 s, i) D6 v
  62.     //  RxHeader1.Identifier++;
    : X! {- \" V  q8 l( k
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);9 O0 [2 F; ~$ B& z
  64.     //} else if(hfdcan->Instance == FDCAN2) {$ @( x, V- N  \& G
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);* x6 j, M4 a  V
  66.     //  //echo
    ' E/ x& y' z, P7 C$ W1 f6 @! T
  67.     //  RxHeader2.Identifier++;1 p3 ?. l' Z$ T6 g3 v% a
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);
    * Y5 a5 b: Q. Q
  69.     //} else if(hfdcan->Instance == FDCAN3) {: [" }* c/ b$ X/ H6 a: ~) X
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);+ z( Y+ L. j3 }, H9 }
  71.     //  //echo8 X% B: ?5 S0 l7 C2 H) S
  72.     //  RxHeader3.Identifier++;
    5 ]5 m; m# N% K2 R6 a3 k
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);( Z4 u5 p3 T5 |
  74.     //} else {
    4 O: J. C. m3 u" C/ G
  75.     //  : \. p8 w* U: _
  76.     //}( {1 U" j1 p7 o; L: A* {+ D9 g
  77.   }+ f. Y+ s  r) _+ q, s$ q
  78. }
复制代码

# ~; Z# o/ T2 G6 g, w3 b4 h注意注释中 RxHeader.DataLength => can_dlc 的对应关系.7 v, ]+ Z" b4 q( i
- Y) X" r# }3 l% @. T8 H
示例如图:7 K9 n3 O! J! c% \" y- y3 q, s

6 c; N$ q& ]3 ]. f
20210222190024669.png

- X) n1 o6 }- R+ Y' L7 _3 r+ _- ^. F7 r$ @: u
图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.
& ~8 m$ X* s: ^5 h) l2 r5 S, i5 y- y* T8 B' e
printf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.. D( o% A6 l" Q4 d- {& [( E
) ]! B. ?/ Y6 e( v
发送处理
3 \8 U! k8 u) ]' A5 X3 ?: Y发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.7 Z8 O4 N% S. d: |( W  t, i

, D. V/ t4 H4 L+ A
  1. #include <string.h>( Q% X7 `& U( o5 K! U4 Y/ D+ I
  2. - |6 B5 ^, E% S# S( d9 b1 Q& D
  3. FDCAN_TxHeaderTypeDef TxHeader1;* s% o  u& y* s. `3 R0 h7 v* e
  4. FDCAN_TxHeaderTypeDef TxHeader2;
    7 `9 B. O: p5 A" r
  5. FDCAN_TxHeaderTypeDef TxHeader3;
    . t2 s- n. b3 U
  6. 0 ?4 A* [. w" [
  7. typedef struct {
    5 B( }6 b8 _2 ]
  8.   uint8_t flag;5 B! [! _. `; X2 h+ `7 ?: D3 w
  9.   FDCAN_TxHeaderTypeDef TxHeader;' Z- J# k( L2 I. ~6 R& W
  10.   uint8_t TxData[64];% }5 [$ c3 y3 U+ b( x
  11. } FDCAN_SendFailTypeDef;
    0 S- }3 s2 i( i% Z# P1 M
  12. 4 h) J+ @3 @. E
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};
    2 X' i! R9 g9 C4 G- @; `
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};
    ; l  g$ `& b1 u/ T1 t) ?7 F3 f
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};
    . d  G6 A5 p" ~2 q1 T1 X+ C
  16. ; l# Q5 u0 [$ \( [: V
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])* \$ t% J9 ?- X' t( ^" F
  18. {. ^, Z8 V. ^1 f5 I
  19.   TxHeader1.Identifier = can_id;* Q: d) D5 C7 W. f9 |; R$ u
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;" b' B0 W! V# H  [. M, O0 W- O+ d6 k
  21.   if(can_id < 0x800) {  //exactly not right
    6 P4 M$ C1 v' N, K/ V8 i& u
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;
    ! E. M5 C$ h8 E3 h8 {
  23.   }% J$ X8 X/ v) u! q! a- J. o
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;1 ^/ o% p+ p+ A! i# l6 v* s$ |/ G
  25.   TxHeader1.DataLength = DataLength;
    1 |" d/ Y3 j  c+ M5 M8 ]/ f+ g
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;8 z7 \) d/ F$ w( P# a" B
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;5 X. Q/ }1 q' n8 m* D  y
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;
    ! _+ W( f8 X3 m. Q" d6 p; @5 |
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    ; [% n4 L2 w2 E0 [6 f$ B3 W3 S! U1 \
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use; Q5 \' S7 O( l) j5 w# |. B" f8 H
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {
    - \! M3 ]2 [. Q# B% ^( }! S/ U
  32.     fdcan1_send_fail.flag = 1;! R0 u' q4 g4 J1 ^
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));
    4 P9 a, D. p4 f
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));
    7 p6 O2 y) b9 D' y0 s
  35.   }
    & n  r6 N; ]1 u, i. L4 q' D
  36. }
    + ?! @" }1 A, C  T6 y% c

  37. / S5 H+ B2 V3 S& s
  38. int main(void)
    0 v9 w" {8 A8 \" p) E& q$ r) U
  39. {5 U' c; e6 Q2 V6 }
  40.   ...; i+ |" {- ?# ~$ {, v: e
  41.   /* USER CODE BEGIN 2 */
    ) H% H& M$ f0 k4 H3 [. u  e0 `
  42.   fdcan1_config();
    9 }& W- B# J; k: ]  n, Q
  43.   fdcan2_config();
    $ g, a9 g) F! L
  44.   fdcan3_config();2 f7 O; x: A: ^, V2 [0 j3 `
  45.   K) M0 s) a  a, e# Y( l- x# E6 U* K
  46.   for(uint8_t i = 0; i < 64; i++) {
    0 d! a+ M( D  k8 m4 i/ j8 j
  47.     TxData1<i> = i;</i>
    ! F2 R/ f8 g1 E- Z6 \7 G* J
  48. <i>    TxData2 = i;</i>
    8 T; X4 n# y/ g2 Q0 M* w
  49. <i>    TxData3</i><i> = i;
    & u  v# P, B5 H, ]. N- C, [6 Y9 f
  50.   }7 p9 v( T( K1 @# ~4 a8 Y- u

  51. # O1 o; L4 r- @, T
  52.   HAL_TIM_Base_Start_IT(&htim6);
    6 Q- ]$ @$ Z  z% ?5 A  \0 w
  53.   </i>uint32_t count = 0;
    8 w4 K; L! w9 J7 m8 N
  54.   uint32_t cnt_100us = 0;
    ! F- F" I$ c# h; c" U! |
  55.   uint32_t cnt_500us = 0;
    * O3 P. _3 F4 o" Z# W/ G
  56.   /* USER CODE END 2 */
    , d/ d9 |4 }! k( y# s/ ]

  57. 3 U4 }1 Q* p: ~) V
  58.   /* Infinite loop */. R0 ~- o- ]6 C: }( p) N
  59.   /* USER CODE BEGIN WHILE */7 V8 s5 u! {7 a3 p" |+ |# B
  60.   while (1)
    4 q6 u( O& c1 f9 H
  61.   {$ L- n# [. f% W
  62.     /* USER CODE END WHILE */
    8 @& R5 `- ?# R6 t, H! Z" ?! s. b/ D

  63. # n, Q6 i" K  m& k% ?2 v- [+ z6 ?
  64.     /* USER CODE BEGIN 3 */
    , \) e  ?( H+ I; E
  65.     if(tim6_flag && count < 1000) {6 I; X2 L- d* \
  66.       tim6_flag = 0;- z# `* U2 A1 I, Q! ~, P
  67.       TxData1[0] = count >> 8 & 0xFF;6 ^& Q! }7 `* ?
  68.       TxData1[1] = count & 0xFF;
    7 ^4 \# W# w* p; Y  B" l& t' R$ u
  69. " k! y1 W$ e+ s; G/ u4 R1 [  e
  70.       ++cnt_100us;0 w6 k2 L* k  T6 J# i# g
  71.       cnt_500us = cnt_100us / 5;5 _- q; v, C' R" f0 G* o, B% j
  72.       if(cnt_500us && (cnt_100us%5==0) ) {
    * J: U0 G; q  L3 x; @$ h
  73.         switch(cnt_500us) {
    6 ^- C9 w8 J0 n$ o
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1); . e! @0 x- D) l2 f1 h$ j
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);
      W) S" t: I3 |! i
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;& U$ M+ s& h/ J( n
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;
    3 `+ q" o8 R1 P) p1 U
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;- v! _* U5 \* B. j0 x! L! X/ B
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;
    / D. m( ~+ x4 O" |
  80.           case 7: /* next send */ break;2 B- I, P8 n( a; z2 O7 K. q
  81.           case 8: break;
    & _' v& ~/ z' ]9 G. G  k
  82.           case 20: ++count; cnt_100us = 0; break; //10ms) g& i+ c3 x3 _; q
  83.         }
    * O# E% \$ @' G' u9 b! G
  84.       } else {  //fail retransmission once
    0 \, s9 x0 V# ]+ b2 W6 `
  85.         if(fdcan1_send_fail.flag) {
    ; x0 R3 M( r! M1 t0 `) g# u  f  m9 r) E
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier, ! a+ J* J% ]+ ~: m6 @  H3 c) o
  87.                           fdcan1_send_fail.TxHeader.DataLength,
    4 g) y' g( A$ X! y* ]' \
  88.                           fdcan1_send_fail.TxData);  @* e) k9 U- [* Q
  89.           fdcan1_send_fail.flag = 0;
    , p) M8 _5 Y% ]
  90.         }! F# |8 C; y4 A, B( h
  91.         if(fdcan2_send_fail.flag) {, I+ c7 P" W  p# _- g' n; L
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier,   d- Z( V7 U/ ~6 R. X3 A
  93.                           fdcan2_send_fail.TxHeader.DataLength,
    1 a3 g2 l* i! l7 h' E7 T9 x
  94.                           fdcan2_send_fail.TxData);: N! X0 E. _6 W3 ^- N, s
  95.           fdcan2_send_fail.flag = 0;
    / U3 |+ s- T+ |& H8 F" u: u
  96.         }8 `- \- c0 n6 o
  97.         if(fdcan3_send_fail.flag) {
    2 l! z! N9 @3 c
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
    & p; C1 q  G( u8 s
  99.                           fdcan3_send_fail.TxHeader.DataLength,7 U) o( T: i8 e' y# ]( \( X
  100.                           fdcan3_send_fail.TxData);
    - o! d, U" P6 x( K, b
  101.           fdcan3_send_fail.flag = 0;; j! F) d5 H& }( g/ T/ v
  102.         }
    3 ^" Q, ]: d6 R: ~2 b+ x
  103.       }9 X# C# h7 U# J$ k# R3 ?
  104.     }
    / b& C8 I) O% l# {
  105.   }0 t3 p$ Z6 L4 s7 l3 e% k
  106.   /* USER CODE END 3 */  : H" l* ]# C# q
  107. }
复制代码
3 K( ^- T. k% ]8 ~) [
fdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.# M( x* j/ w. g1 i. R2 p; L

+ k9 Z$ x: M8 j4 I发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.
$ a( Y& u, a) Z; ]- u4 u  L' e5 U  X2 r4 a# |
这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.$ t) Z$ ~# f- S0 ?% M: \5 C

" Y  h9 g! K" y8 p" K  Z因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.
4 `& L- \$ t, Y4 p- D( J
6 T: ?4 I3 X# W- i  V' T' V因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.
2 @5 v! B. X7 ?" |: D2 Z, o, o7 u( c( l7 {! Z4 a
如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.9 h/ o% B( }) }) I- ~& v( ~
( Y. h" x$ e1 c' ^, B" m& o6 b
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.
6 g* O, T/ _7 c% N& F( Q$ [+ O5 E" q, N3 B! t7 Q1 D+ V0 e& G7 q
程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.6 B% Z; @+ F9 z$ I  |* }' T
8 e; U  c7 A7 S8 ~# m" ]. f
使用Xavier配合测试一下! w* E8 m0 Q( F  v* j5 y8 q
把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:
) O& m% O( B" ?) d. S2 P, h1 l+ C2 _4 J9 E: b7 u9 Z
  1. #!/bin/sh6 [6 e" D( k/ a+ l5 S

  2. 7 j) C' _% K6 U! x3 A3 ?& N# G
  3. sudo modprobe can
    1 H6 q( h+ M- q  |9 U
  4. sudo modprobe can_raw+ G9 g& v5 `, Y* f/ i* A
  5. sudo modprobe mttcan5 v& C' L" y  O4 a. ?# C
  6. # H9 c$ {4 j6 [' |( [
  7. sudo ip link set down can0" p  `5 r7 s1 [; N  W5 g
  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
    " w2 y5 M/ U/ |9 L% K& `- @
  9. sudo ip link set up can0 ) o8 \' _, i$ i' i
  10. sudo ifconfig can0 txqueuelen 1000
    * w3 E- S2 D" f: @# u9 k3 z& H( Z' d  T
  11. 6 |2 u- u2 D5 }3 [# f
  12. sudo ip link set down can10 e: `3 p( B1 v. }& Y$ b$ V! E
  13. sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 1001 N: J1 L* T2 q5 N
  14. sudo ip link set up can1, V( J9 b) z! |' |, e
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.
' T/ Q5 ~: K! ~5 ~2 @) Q
% x' Z7 q2 e4 `' i/ D* Grestart-ms 100设置总线Bus-Off时, 100ms后重启.$ h1 e$ O+ D* o4 ^, T! N

$ t+ _1 H' B1 ]8 J1 Q设置完后查看设置状态 ip -details -statistics link show can1:
- l& W3 p" ?( b' K# X/ m% N, E9 ~
& h$ I0 Z. A9 ^/ e: c! W  R5 G
  1. $ ip -details -statistics link show can1
    ! f5 ~# y! t) p# h
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000# x; G- @$ j. u2 A9 J
  3.     link/can  promiscuity 0 4 P* I$ T. ~: e% U, T* D
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100
    / x7 G0 N1 @2 _6 ^
  5.           bitrate 498701 sample-point 0.792 ) Q; _7 J& o! }
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1# l  {6 U5 r( h0 ?& c; m( ~
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 16 k( }4 v* H/ R# w2 S1 s
  8.           dbitrate 2021052 dsample-point 0.736 5 W# g0 ]9 ^/ q0 }, O
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1
    & d& k( w1 C, Z5 |3 C. }" T
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1
    9 o) A% u! i2 j* f4 n8 P, J
  11.           clock 38400000+ Y* [$ h( T' l. U6 F6 l1 ]$ w
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off
    2 ?' Z& T  e: |; c8 `! ]
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 4 w7 [$ b! Y3 X) G; \. W+ A0 o" x6 H
  14.     RX: bytes  packets  errors  dropped overrun mcast   , D1 ^3 q6 S( x! I4 T  l. F$ h
  15.     64578440   1013451  0       0       0       0       , o3 l6 z  E: v  G: Z
  16.     TX: bytes  packets  errors  dropped carrier collsns ' W9 y! K/ C1 L7 O  E; r
  17.     952448     15914    0       0       0       0   
复制代码
位速率和采样点的些许误差测试并无影响.) K$ t5 \6 ^, z) R

1 d& Y- `. d7 ^0 Z- W使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:
7 e7 K# S2 W! W# |, X8 e( U0 C3 F. T8 H7 F  h' @' k+ m- z
  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
    / d" f& ~/ v2 j' Y* a
  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
    5 E- O8 t, W* U/ ]" |4 O. L# a
  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$ d4 Z; l. Z- v1 M; 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) O9 Y+ P1 ~* Z/ c, T3 O
  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
    ! n9 D+ Y2 T1 _5 ]0 x
  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 3F8 W- ^1 S) ?0 U/ d( I3 w
  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 3F7 j( f0 f2 i: u, |2 a9 k6 @
  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- u* ^0 G) Y) G% y1 k3 B
  9. ) d& a  n: u& y0 O
  10. ...
    / q5 M2 N! _( h! f7 O
  11. 6 }/ @% w: }, Y: U# U- C! p
  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' u9 G2 \! F  d. k% r2 M" b! I) F, c
  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
    ; |6 @1 C8 t+ T
  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! X4 S4 X/ s# C  f4 p5 j! Z! ?& Z
  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- z0 F$ R/ g$ ^2 i- v- m5 _- M
  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  F1 g6 f! D2 X& h
  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 3F5 {/ Z( T' c$ {, C; _
  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/ u9 r; p: C2 }# t
  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 3F2 M; m  n9 k2 i( {' s& S% F
  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
复制代码
; n, b* X" ?# m; N0 `: T3 R
这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
% e) [- y% H/ M8 V1 C/ z# K* x  D3 H' O! z- s* M# A* ]1 |
Xavier发送脚本, ##后面的3表示开启BRS和ESI:
, t& A3 l$ V4 F# g
6 g( [, ]+ d( G$ Q6 \
  1. #!/bin/sh4 a. i  ^7 A6 I# T
  2. 3 y/ v) \* o4 q; a+ U7 X& H' r
  3. while true; do
    " x  x4 _. W9 c" N* _. I
  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* H# J+ i  u! p2 C
  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
    ! e1 A% W# |* z9 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  . u2 h( Z# q6 `* ]- p* C2 C/ v: v
  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. d! d  F) k5 J" S
  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# e" s" S# A4 N6 C4 T/ t; _3 [
  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  + l. M  q( {4 I7 a
  10.     sleep 0.01
    9 i1 D' V) A/ V
  11. done
复制代码

$ I. _! ~5 J- O" y: U& M可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.
1 F0 H- M3 S6 R7 C" x5 J+ G5 [# t# T- x9 v' W
核心思想是:
9 Y" J1 J; i5 {+ Y6 G
0 R& S6 n" q6 ~5 j/ c& ZMode 设置为Classic Master或者Classic Slave, 而不是FD# b' L5 K# X. S
仲裁段和数据段的通信速率都设置为500Kbit/s
1 u! L; K8 `9 R3 K* N8 o# ?: I9 v1 m6 A; s7 j
# Z6 `5 Z+ l$ v* d( [

9 P/ H( d7 O( l1 A6 s
收藏 评论0 发布时间:2021-11-11 22:00

举报

0个回答

所属标签

相似分享

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