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

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

[复制链接]
STMCU小助手 发布时间:2021-11-11 22:00
本篇用起来, 连接关系如下:
1 l" I3 x2 ^8 S/ J* `% s- C+ [
/ O/ U* s# R3 Y( f& C6 n+ E- q

20210222185812381.png


; T! F4 s/ Q  ~8 Q  i( f7 I5 Z! y) Z8 `
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.0 e: n" F8 _+ v  t, I- `
0 b- S) T  |9 v& e) W
STM32工程搭建0 v: ?9 L, B- k- h/ x' n/ |
STM32CubeMX配置步骤如下:
4 D& l. F% h  P7 ]% g) m: @/ ~& ^0 [3 a+ M: S* l( _2 O" z& _0 H
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx6 k3 b2 b9 `$ u5 q6 C, K
' y: N/ a; a. E7 c! D
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire
3 g# d7 X) F# n, b6 d) s4 A8 b; p- n5 Q+ ^
# C- S- t+ K6 H! F. \Pinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator
  O- [8 y3 Y( q$ N- ~
- l# J3 g  {1 B& ]9 `Clock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):
7 j# Q) j9 Q" [$ E4 M/ v

20210222185828575.png

. Z( U' S- I) p: k+ T

20210222195952515.png


0 F+ i% `6 U: u: y
8 i! u4 s& E6 e: g7 V  S开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:
7 x) @! A' Z/ f' J9 ^# d: ^; J. W/ F

20210222185846781.png


# K9 g8 G0 \0 \/ l" f9 [! m! r
) `. j' S( q; ]

20210222185905935.png


8 o" c; Z$ G" q8 ~
, ~& u( J! \+ X7 gLPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:
/ x* n/ w5 V" n' d4 z
; b1 f9 d9 y6 E* Z5 E

20210222185926920.png

) f' |' c0 }2 w( K* K

; p& e* `" M' X" @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:
/ `( H& B, n! i9 _9 l" f; O  W5 S

20210222185949803.png

: Z6 h7 t4 n* H; f

9 a0 F7 f( i: O+ L! D

20210222190005173.png

& R; R( Y0 E" q5 a/ w& b

' ~3 Z9 H0 W$ k5 n2 \$ ^& J' tFDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:
* V# S& ^0 ?9 U' s" {4 a9 m! l
2 L4 a0 j- c. V4 S

20210222190054536.png

. g* D& C: f: j* k$ u& N7 m

4 f8 `- f: a0 PProject Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.
: L* ?+ N6 ]$ G
  j: K+ P0 Y  l# rProject Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral
% N3 n7 L8 j, p& F1 z
- u( c+ W5 i0 w" C5 F* ^* a2 l点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程., q# {: v5 M, i; q& N) R5 S/ C
  e+ {/ o; a9 ~1 a- h
Keil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:5 F5 C3 f" E* x: c% Q
7 _: X( O  ~8 q, c
Flash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行." ^9 N2 G% Q+ f& m9 ^
Pack选项卡, 去掉默认的Enable勾选
1 N% S! _* D) }到此配置结束. 下面是手动添加的代码详解
5 W! ^- d# [% m  X* _0 d# n. a
4 w1 N3 `% t1 J1 C' f5 d3 r0 ]串口配置2 o8 b5 Z7 u0 i7 }/ {" Y4 }& X
为 LPUART1 添加printf支持:+ J% `  b0 w' h

1 |4 W1 `: r* P& Q' W
  1. #include <stdio.h># D8 V0 `+ A3 L, |! N# \5 h+ d

  2. ( n/ Z' q0 F! K
  3. #ifdef __GNUC__
    6 J6 @9 ~9 s+ Y2 ^( c) B9 |. p
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    ( m* J. |7 Q  D3 B1 z
  5. #else
    ' o1 j8 P: N4 t/ M+ |: }" n$ v
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)9 g& W) D* l6 c) M, u& {2 k0 h
  7. #endif /* __GNUC__ */
    % r, N! d' {5 {: t! Q

  8. ( [1 _+ t, g4 B* w
  9. PUTCHAR_PROTOTYPE
    9 Q0 T6 f, k% U% ^/ m' u
  10. {+ u6 B! M- K+ y' k
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
    1 O% W0 c& \( g
  12.   return ch;
复制代码
& F  d4 M9 l$ ^! e8 q8 J$ K" j
100us定时器2 ]' o. X& S' I$ E( C
因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.; y. |$ n) c6 u1 {5 U
& \: m' @! J2 M/ B( E
  1. /* USER CODE BEGIN 2 */, |4 I+ q3 ?# L7 Z+ Q5 b+ W7 F1 W
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.6 R. U+ C% W1 d( c4 E* x% x( Y
  3. /* USER CODE END 2 */
    - H3 v3 ^2 U6 |# T6 m

  4. ( ~; j0 @5 K$ b( X) y& B7 a
  5. uint8_t tim6_flag = 0;/ T5 x$ {  I  l6 {! C. m4 v) f
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) " g4 M2 |1 y+ x9 f
  7. {. [# }2 M5 o( I  S" e, T; e# c( L
  8.     if(htim->Instance == TIM6) {
    $ ~/ D( s' |1 y! w  G
  9.         tim6_flag = 1;
    * @1 z* P( o# Z6 o3 z3 d
  10.     }
    % f% F; T! O. K2 s/ W9 W
  11. }
复制代码

) v4 l( B, I( QFDCAN配置
0 C4 A/ q- h4 U主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.% s# P& x# c6 t

/ |, y2 s7 v# d) Z- ~
  1. FDCAN_FilterTypeDef sFilterConfig1;
      w+ _, k( k, I( ?  _

  2. 7 Z7 Z' c5 L7 V  p- ?/ d
  3. void fdcan1_config(void)6 U  E( i5 r2 [1 p+ o
  4. {- l. R& p! M( ~: y" B
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;
    ( B; h) ?5 P; v) B' }8 C$ @
  6.   sFilterConfig1.FilterIndex = 0;/ ~; x5 f0 o& M& z2 z" |
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;9 m% T1 n! l' J
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;3 U7 a  t# ]  D, ?7 l" _
  9.   sFilterConfig1.FilterID1 = 0x00;* p1 K; t4 t. I* E
  10.   sFilterConfig1.FilterID2 = 0x7FF;. Z- M$ P$ r3 c5 Y
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    4 @- c5 ^7 L; b2 r
  12.   {
    / A- s1 T$ A, j8 G3 ?, [+ P
  13.     Error_Handler();5 B5 Q) z3 H7 t9 b
  14.   }5 n& U) H, A3 [9 i5 ?! x" A

  15. 1 \: {0 {2 `3 [4 u. ]
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;8 V4 v2 _; J! x) D3 I; z: z% V) O1 m$ @
  17.   sFilterConfig1.FilterIndex = 0;
    2 B. l* ?) T, I: c8 V
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    * g" G3 N8 c8 W0 y. `" X7 Z4 A
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;& l1 h" A6 v0 ^8 C* Q5 I
  20.   sFilterConfig1.FilterID1 = 0x00;
    - X, |/ N$ z7 b* T- a* t
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;" [/ A/ N5 G* G8 H) z. c! J4 i$ o
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    / |' b7 M7 |( _# S3 [; A* v
  23.   {
    - ?3 t5 {. E  @3 b
  24.     Error_Handler();
      v* T0 X; E$ W& V
  25.   }1 g7 }; D7 _/ T& r3 M

  26. . I% J- {, e9 [( g' g9 m* o
  27.   /* Configure global filter on both FDCAN instances:
    8 f0 x4 `( H! M! b) J7 u- u0 t3 v
  28.   Filter all remote frames with STD and EXT ID/ x; W( y) C- ]4 x
  29.   Reject non matching frames with STD ID and EXT ID */
    , U& D2 ~& E8 T0 G) R# Z6 W
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
    9 z- O' L: M+ H; Q; O1 R
  31.   {4 A8 W/ j2 ]4 N& I; w  s% P
  32.     Error_Handler();# j  Y  R2 \1 Z
  33.   }
    ) e5 i$ T- d) T! I6 l' d

  34. * ]9 [$ V0 n4 n7 z
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */
    + T! K5 g' u0 a, n
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
    / ~( }5 `- J9 P4 s+ F* D5 E3 H
  37.   {
    5 K; T- ]$ U: m& R* J
  38.     Error_Handler();
    ; p+ t+ X; v& {' F
  39.   }
    7 u' L0 F/ N3 ~
  40. ! W9 j* g7 [4 ~$ l% i2 `3 P2 Y
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
    ; G9 ~) _. ]2 `, U
  42.   {
    , q% v; M5 I0 K  @+ J
  43.     Error_Handler();
    3 Q3 T5 {- g% Q% h" i5 D
  44.   }' B' d% M$ z' X; c

  45. 5 r% F' `, V) g) \. e
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode./ ?+ D8 _8 Q4 ^9 D
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
    # w* w  ]8 o: l3 p
  48.         TdcFilter default recommended value: 0 */
    4 p" `* {, D) j/ Q- ]  q, n* k
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
    - \. P. Q$ t% S' D
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
    + R" R% B) z- N( A

  51. ( M9 j4 a" Y6 H$ u8 i
  52.   HAL_FDCAN_Start(&hfdcan1);2 v# y! `9 d; x6 d6 O
  53. }
复制代码

% f; l, c8 \" H7 L; j$ O这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
$ L, _; p. i3 [% N% c8 d( @% E
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;, i2 u% W# o  `- Q* P
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    8 F6 g9 @! O6 A. J, @" N) i
  3.   sFilterConfig1.FilterID1 = 0;
    3 Z) p0 W% V4 U; t! f
  4.   sFilterConfig1.FilterID2 = 0;
复制代码

3 R3 _- u$ n. [  O用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.1 j- x' T; g* @% {& y
3 i) \4 m0 c1 [
有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:. Q, b9 B/ s- B9 m

' A. G# `/ X- T% S
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码
: m' P( Z8 G" ~8 O
FDCAN2, FDCAN3的配置和FDCAN1类似.. p1 B! w9 U8 v7 l6 H6 j( K2 n

9 ^9 `* o4 k" C8 ABus-Off处理
  f( N7 k0 S$ ^如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:
4 m: O* _% H9 h4 @& h: a6 T& E8 p4 \% h3 D  Q* M# Q- F
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
    0 _: G' l& h2 j3 g; }6 Y5 Y5 H
  2. {
      [0 G, Q4 a8 O' A' `
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);
    5 ]* O8 \; G+ }) _
  4.   if(hfdcan->Instance == FDCAN1) {
    + P% s7 @5 s+ n5 D: s# x2 b* [( U& n
  5.     MX_FDCAN1_Init();7 j4 ]" f1 @5 j# @  D" W
  6.     fdcan1_config();
    ; E+ i8 c) Q! m
  7.   } else if(hfdcan->Instance == FDCAN2) {2 p& K. J! p1 L) N" x
  8.     MX_FDCAN2_Init();
    ! G% d$ I( s, Y9 R
  9.     fdcan2_config();
    # w) q! x: Q  Y4 @& z8 X
  10.   } else if(hfdcan->Instance == FDCAN3) {4 j' k3 s8 z+ ~+ w0 U
  11.     MX_FDCAN3_Init();$ Y9 c" d6 B0 {: c$ z4 o) f( p
  12.     fdcan3_config();
    % u* B2 c* A3 O0 s
  13.   } else {% z, m1 v5 |* W
  14.   }
    ' ?7 m! I0 H, b( I8 o- E/ m" S
  15. }
复制代码

: d, \- c/ ~4 v, B! g! m新消息接收处理
3 U8 a+ ^  c8 U直接把接收的消息通过2M波特率的串口打印出来.1 M$ B3 J( c! v9 I

6 w: N0 ~5 W% o# S- u  [! F/ ?! v! A
  1. FDCAN_RxHeaderTypeDef RxHeader1;
    9 c  ~9 r- ?# h. _+ f0 \
  2. FDCAN_RxHeaderTypeDef RxHeader2;' B: s# a$ a9 u
  3. FDCAN_RxHeaderTypeDef RxHeader3;7 e5 y( `, j+ {. n& k3 G1 \6 ~" |1 Z0 \- S
  4. : ~3 r4 z2 t& c* e/ E( R
  5. //RxHeader1.DataLength => can_dlc% D$ U+ L3 O  y) s. m
  6. //0x00000 => 0 * |+ `# z% e: C6 z8 P
  7. //0x10000 => 1
    6 x( T& \# r/ {, M
  8. //0x20000 => 2
      U# ]$ V" f. W: K
  9. //0x30000 => 3 * G; r5 A% y1 D+ \. v3 E* @
  10. //0x40000 => 4
    4 [7 E  O+ l9 J7 ^
  11. //0x50000 => 5 * L! S, T: a' m$ r; }; t, @
  12. //0x60000 => 6 3 ~6 g1 w& j- f3 Z& H
  13. //0x70000 => 7
    % a- c# D$ t3 V' l. [
  14. //0x80000 => 8
    ( `+ L& q* V5 y  C& i
  15. //0x90000 => 12: Z: h# ]3 _& Z  r9 K! n+ ]
  16. //0xA0000 => 16
    % G9 k/ q1 t! }8 M& I! C
  17. //0xB0000 => 20
    7 U# ~/ i0 O2 B  d
  18. //0xC0000 => 242 _$ @& f$ {0 S  v- P
  19. //0xD0000 => 32: a+ B  p( }% m. D- K
  20. //0xE0000 => 48! M; k7 Q: U# \2 j  @
  21. //0xF0000 => 64
    6 l- H, y: F; I" N; H- c' q( D% A9 R; K
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
    1 h- ]0 G  s( M% u9 Y7 q+ K/ P
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)
    " f; g/ a" e7 Q9 k( _/ Y
  24. {9 X  S& W" n# C
  25.   return dlc2len[RxHeader_DataLength>>16];+ J5 [# q7 k8 }; H8 k% L% R
  26. }( n5 n0 A+ G( Z$ t8 U9 X  T  s$ ]
  27.   `) I. U7 C7 s3 Z3 Q6 ~! s0 ^
  28. uint8_t cnt = 0;; g* F; a$ V+ F) v, S
  29. uint8_t brs[] = {'-', 'B'};2 G9 r% T7 c$ ]) r
  30. uint8_t esi[] = {'-', 'E'};
    : _7 D( |/ H7 l
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)0 c; t6 p' p. E. ^9 _5 z4 h
  32. {, T9 r$ W+ w8 o5 l- D( \. d
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {' y' i8 s- Y& T, n" g' [" l
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
    % N' H$ W5 Z8 T
  35.     //RxHeader2.Identifier++;
    7 r2 F5 x7 _; p
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);% P8 Q7 Z; e. [# W- K* _: K) ?: _" k+ N

  37. : ?/ a5 A" X9 t6 T' R2 [
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    $ \* A' S( e2 B/ O* m
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));
      m, e6 ]+ Z# Y# i1 N0 I
  40. 4 i: W$ n2 K  F0 Z% q- J( V
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);2 B9 _) d. L0 U9 A! Z! V9 t7 A
  42.     if (hfdcan->Instance == FDCAN1) {/ g2 n6 e" H) Y8 y- Z
  43.                 printf("fdcan1, ");
    ' v: V5 G$ ^8 i( Y
  44.         } else if (hfdcan->Instance == FDCAN2) { & P; s% P. [3 m
  45.                 printf("fdcan2, ");3 K# S/ q. ^$ L: B2 r* @
  46.         } else if (hfdcan->Instance == FDCAN3) {
    3 j. V) z  Q5 W0 b+ |
  47.                 printf("fdcan3, ");4 H7 u9 F; d( d* ^) Y( e3 g
  48.         }0 V) g0 N3 T8 ~! {5 U
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier, 6 _$ _  u+ I( p, d% d+ S
  50.                                   can_dlc2len(RxHeader1.DataLength), ! r2 a8 D7 E2 P& w: ~3 d/ j
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],
    / z- c  k4 }# q, r2 H- D! `: F  p
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);, w& T  _  a( D! p4 {$ H1 {0 d
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {4 p( S. H* e: `
  54.       printf(" %02X", RxData1[cnt]);8 u+ S' }& r2 C) M: A' }5 {1 o2 a
  55.     }+ i& e- e  h( l; ?5 v2 E
  56.     printf("\n\r");
      J3 t- M3 X" a3 F

  57. 6 b, a6 _1 J. Z' f4 z
  58. 3 W- N" u: I# d2 W$ u
  59.     //if (hfdcan->Instance == FDCAN1) {
    " G% n3 {8 q1 B
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    ( A- s* P1 \' J$ r
  61.     //  //echo
    ' \( E% H5 m" k' j7 O  `9 }% f
  62.     //  RxHeader1.Identifier++;7 w  x2 g: ^- e
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);' l; s* r+ e/ k/ u6 }
  64.     //} else if(hfdcan->Instance == FDCAN2) {7 F" z, z" i5 i" X6 V/ s
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);3 B- Z( J: e/ l1 i( ]
  66.     //  //echo
    7 \) g# p! m7 y8 B# e$ a: l
  67.     //  RxHeader2.Identifier++;
    * w; u6 K8 `& x: j5 K  X
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);
    7 U) x& j: ?4 \- J, ^: L7 z: M
  69.     //} else if(hfdcan->Instance == FDCAN3) {
    + i5 ^& t! z5 @$ m5 X7 @
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);
    & {/ f  R. Z% I& T  ^  X) i
  71.     //  //echo/ E( ]) s) c" }2 @: k
  72.     //  RxHeader3.Identifier++;' [+ V  P9 u+ O2 D$ P. L/ l4 ~
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);: C* `: `8 D- c( o/ y, ^
  74.     //} else {
    * l8 p# N) }( [: k% a! T
  75.     //  1 G3 N, C! L7 P  H! u
  76.     //}
    ) U' r; S  E" l' c# B2 w
  77.   }
    ( Y  D1 Y& S' I" M
  78. }
复制代码
# c& y1 N% M" p3 B0 a
注意注释中 RxHeader.DataLength => can_dlc 的对应关系.( ?5 c  _: k1 F2 N- {
& Z& i+ B8 w/ Q8 ?
示例如图:
! X8 a9 U0 E+ L5 |8 I" n# e4 h! J& n- K( V* C* g% v
20210222190024669.png
, |# Z) p- A$ a3 C* f' ]3 V- H

* O0 v# J& G# ?0 c- y9 h图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.8 p. C  l% M6 g  T, f* W
7 m  H5 R9 U7 _& b2 x
printf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.; N3 x0 ?& B* T8 e
+ N$ ]. h7 h6 a$ r2 l
发送处理# D; I- a" S# K7 ^8 {) O
发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.1 o/ G& E/ \$ S- l" g
6 L' I' i1 F; x/ R* ^$ H4 j
  1. #include <string.h>1 e  S1 i$ O. l1 y2 i/ @
  2. ) v+ n& [' P" {5 `6 H
  3. FDCAN_TxHeaderTypeDef TxHeader1;9 ]3 Y- P4 I- u
  4. FDCAN_TxHeaderTypeDef TxHeader2;( ]: N; w$ W4 a6 N9 R: q
  5. FDCAN_TxHeaderTypeDef TxHeader3;- I- ]$ T# B! I* q* @
  6. ! D; _# G0 O; j3 B! a
  7. typedef struct {
    : Q1 e" d* o5 h9 {: ^9 ~, @
  8.   uint8_t flag;
    * n' ^- o0 l1 Q' m/ ?1 D, L% E
  9.   FDCAN_TxHeaderTypeDef TxHeader;, _% z9 d. b/ r; Y, Z4 j! T$ s
  10.   uint8_t TxData[64];, m6 R2 r/ I3 i3 a5 Q3 h, ~9 D
  11. } FDCAN_SendFailTypeDef;
    5 A1 V# }! z* Q% h$ N

  12. 3 M9 P# S7 I' g9 i
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};1 G5 K+ c/ g; p- t
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};
    7 M" D& V6 p0 _7 R8 v
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};
    6 x! C+ {7 S. ]! v; V' C
  16. 0 N5 A2 s: P# R6 U$ L* D* N
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[]). {1 a3 Y1 X, ]# M
  18. {' ?7 t4 v8 ^5 |4 x* A6 f& B5 w0 ?0 K
  19.   TxHeader1.Identifier = can_id;
    8 L+ }  n6 [% ~2 U0 f
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;
    9 o+ z; u5 Z5 O1 i+ @& D
  21.   if(can_id < 0x800) {  //exactly not right! v. |/ J# n; s) V3 ~4 V& i6 k
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;
    ' {9 |! x& P- v( e) Z0 ~
  23.   }$ M6 R  n0 T" l; c0 O" B- i
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;
    * K' q7 G( ^' n+ K- D
  25.   TxHeader1.DataLength = DataLength;( n; P" V4 s3 n5 R0 F
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;5 u5 d" G9 K/ R, Y/ P6 y
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
    + T0 \/ a  r. z
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;: f" g5 O% U/ J* i3 L5 P
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    $ l7 K5 _$ e9 D( v% ]
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use0 A) _% V1 x. `' f
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {% e; q7 o9 i- F
  32.     fdcan1_send_fail.flag = 1;
    - h$ m5 z$ g0 ~3 C7 }  J
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));* M8 Q$ Y3 e( v) R( k
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));
    8 T! |5 h! d2 o
  35.   } ! Y1 }8 \' C# W/ |6 h9 K9 J
  36. }
    3 ?1 S( e& c+ S$ T5 i
  37. # w/ q9 a% |$ ^8 a
  38. int main(void), v- V9 B( z4 {+ ?, g( k
  39. {
    * h2 ~/ ?& w1 B; e8 M! ]
  40.   ...0 ], |* O+ K; Z7 G- J1 [3 b8 [
  41.   /* USER CODE BEGIN 2 */0 m- {* I  j0 |7 v2 v; Q
  42.   fdcan1_config();
    ) A7 D; f- L- B: ^
  43.   fdcan2_config();
    1 N" ?5 e* p& l: K  p( @
  44.   fdcan3_config();
    ; D5 U+ P6 [# L* v# o" q
  45. 0 Q# E" W3 x7 n9 X. q' D) ~
  46.   for(uint8_t i = 0; i < 64; i++) {
      z& B: ~& O4 _
  47.     TxData1<i> = i;</i>: }5 r6 n8 `$ ]3 ^! H5 b; r
  48. <i>    TxData2 = i;</i>" t- o( j+ K/ I! f6 [5 S
  49. <i>    TxData3</i><i> = i;# J$ t6 ?  ]6 T) _3 p" S. o6 p; {
  50.   }9 P. K0 p+ p0 U4 G

  51. ' W& }& ]3 z2 m! F" V. }
  52.   HAL_TIM_Base_Start_IT(&htim6);
    5 g4 W& B5 f+ }
  53.   </i>uint32_t count = 0;
      ?7 C  B  {- c- O% R
  54.   uint32_t cnt_100us = 0;
    " C. n" L3 _( F
  55.   uint32_t cnt_500us = 0;
    - u- t  X; D) \$ R: |
  56.   /* USER CODE END 2 */, M1 F) l) k' w" l* t
  57. $ L5 G" U4 A; j8 b& u
  58.   /* Infinite loop */
    - x; S1 j) E, z, D/ ?/ r
  59.   /* USER CODE BEGIN WHILE */
    . T8 O! P, T% g! A+ l6 j, b
  60.   while (1)
    6 Z, `8 {" r( _3 ~* a8 q) N) J
  61.   {* s" {4 r) S# }. Z' L. k( _8 ?. Z
  62.     /* USER CODE END WHILE */
    ( v% x/ u2 v4 |) ]
  63. ( }5 h  _3 H7 M8 Z$ K5 n: J6 o
  64.     /* USER CODE BEGIN 3 */6 n% N  |8 x6 p- i7 C1 z# w4 w
  65.     if(tim6_flag && count < 1000) {4 @: U. n' Y+ x1 Z% d
  66.       tim6_flag = 0;4 v3 D# G$ r: }: V
  67.       TxData1[0] = count >> 8 & 0xFF;
    9 w: _% f4 o2 y# ]9 k8 z
  68.       TxData1[1] = count & 0xFF;
    ! H; Z( Y" h5 e) D- N6 u
  69. # {+ k, \" E% j7 f+ b
  70.       ++cnt_100us;
    * Q* w* b' J3 P
  71.       cnt_500us = cnt_100us / 5;
    - ^9 T! H- _$ ^# c
  72.       if(cnt_500us && (cnt_100us%5==0) ) {
    - I3 _6 v! M/ y" K, S$ A
  73.         switch(cnt_500us) {. O0 Z/ D* j$ F) c- l& a
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1); + D8 N. @0 C4 x0 H1 w
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);
    2 S2 r* O- J7 f' ^4 \
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;; w7 x' [2 Z$ u1 x
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;' c8 n' K& Z/ l5 ]) u
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;" a, r  a% m, \9 q9 B. d
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;! x$ V+ V3 ~# y7 j! G# E
  80.           case 7: /* next send */ break;
    5 C4 D; b$ G& v
  81.           case 8: break;
    " Y! d6 A) w0 [1 y. {* Y! M1 _
  82.           case 20: ++count; cnt_100us = 0; break; //10ms
    : ]& i" i* R" U9 W. _) z: y
  83.         }
    ! ]% C, \- e# D) k' `: X
  84.       } else {  //fail retransmission once- m& x& [+ p* W7 s
  85.         if(fdcan1_send_fail.flag) {! D" b8 e: v& R
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier,
    " a  h9 M3 ~0 X
  87.                           fdcan1_send_fail.TxHeader.DataLength,
    4 z; v8 N7 {) M0 v' d' v
  88.                           fdcan1_send_fail.TxData);4 p- i+ D+ ^) e  q/ i
  89.           fdcan1_send_fail.flag = 0;
    6 K# S8 ?- B: y! `( g* j
  90.         }4 q' w/ p2 z) g2 D
  91.         if(fdcan2_send_fail.flag) {& y3 r3 C1 x3 J* a  p3 X: a
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier,
    2 `6 c, W& f& }2 T+ Y
  93.                           fdcan2_send_fail.TxHeader.DataLength,8 q& B) s$ q9 j- h6 x5 I+ R
  94.                           fdcan2_send_fail.TxData);
    + r& M, n7 E+ a" T& Z
  95.           fdcan2_send_fail.flag = 0;
    * h- q( @. |- G& u
  96.         }* c$ a# Q/ H& ]
  97.         if(fdcan3_send_fail.flag) {  K5 z1 J( y; O- s$ p' F2 g, k
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
    / Y* J$ k! J! W  ?3 n! b5 L( h' z
  99.                           fdcan3_send_fail.TxHeader.DataLength,
    $ N  I3 S. o  @4 m0 C  F4 W
  100.                           fdcan3_send_fail.TxData);
    + p. P0 |9 A8 |, s. j
  101.           fdcan3_send_fail.flag = 0;& v# ?7 {: O* P( d5 ?
  102.         }
    6 \( g) Y. Y$ H9 T* p
  103.       }7 V" z! z6 U$ g6 S9 H3 w& p
  104.     }
    ( |8 i" \- t) n  v8 V0 |
  105.   }& O6 q6 Y9 B8 U, I
  106.   /* USER CODE END 3 */  
    6 D/ V1 j4 k9 B7 K, e
  107. }
复制代码

7 W/ T& `& M6 J) P- |9 v# ifdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.
" C3 D) ?& R6 A3 }. S2 o( L2 G+ L3 w4 b* M* W9 e, n1 ^6 }3 d' Q4 c
发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.+ R6 b) v; t, N7 ^* Q# D% E- U3 u
, h7 O% H  O$ q8 d; q/ z
这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.: z3 x5 l& s2 \1 p9 J, y
% ~- J- `  S4 @
因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.
2 O) I6 W- D: `) s- X- S5 x( @1 q* G/ s' X4 W* _7 Z* F
因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.
/ J5 L" K5 u. ^
* p* n% v& i1 ?- ^. H& T. C8 A0 r如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧." Y& m2 u8 o; H( x2 i6 u4 C. b7 P+ }
3 u0 v( Y  M% A6 C. [# K# z# n% @
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.% h$ N' t) v8 I

; F& [. x6 v2 l( u- l& Y9 E- x程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.* ~; W( j* b1 e* M3 w
* s9 J! {% U7 G! L: E- `% p3 K6 }
使用Xavier配合测试一下
3 N" R" n! D9 Z, A; J* P1 V把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:- X; T$ \+ K* ]% _
, z" N  t5 B! t4 K0 K! Z: I
  1. #!/bin/sh( H4 l0 m4 v% J' {  J

  2. $ z( L) D: G* ^6 B8 v9 [
  3. sudo modprobe can
    . ]! k9 }7 K; Q
  4. sudo modprobe can_raw6 d! ^0 V- ^3 I5 q! F! i
  5. sudo modprobe mttcan) o% a0 x' L0 X; A. E
  6. " P- G3 Y/ Z3 e# |
  7. sudo ip link set down can0' U! j6 _; P# y% O- T( p8 g9 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$ d) P( d& Q: \7 S- @
  9. sudo ip link set up can0
    . G2 J' F9 t1 V" J. q# E0 p
  10. sudo ifconfig can0 txqueuelen 10003 R( N6 d6 [; n+ J4 H5 B& \* t

  11. # b8 v- G, X. }; _; z& v
  12. sudo ip link set down can1
    . U1 Z) l- {! j! s$ C  k2 X" u7 m
  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
    . F, O1 f$ r) h& U7 H
  14. sudo ip link set up can1: [, u# C: J9 t6 |4 i9 Y$ i
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.8 I4 z8 b; |5 E4 @. B; ~3 u
, r) y$ {3 R+ E9 @2 R' o. K6 u
restart-ms 100设置总线Bus-Off时, 100ms后重启.
* }9 i  f  t3 _! Q5 w, F
! ^4 |) b2 m/ H7 O& }, e+ c设置完后查看设置状态 ip -details -statistics link show can1:
& t$ ~& V: e% ?) ?  n& q! W+ X7 `" W6 j$ ]
  1. $ ip -details -statistics link show can13 O4 T% k3 z0 t3 G! `$ R. O$ `6 `
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000' B# @9 x; ?/ Y& ~
  3.     link/can  promiscuity 0 5 u+ }) c' _9 e/ t; c9 ~) q/ k( ]/ _
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100
    / l# v2 j* c2 B/ ]9 ~3 D/ }
  5.           bitrate 498701 sample-point 0.792
    5 D& r# m$ K0 \
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1
    ) B: [# b2 }0 _7 u" _
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1
    : K5 V' m) _0 y0 T2 W
  8.           dbitrate 2021052 dsample-point 0.736
    1 f) @8 G* f3 L2 w" a% f" U
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1. ~7 V/ y1 b2 j( }
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 1
    8 i1 s- _: |( _$ E
  11.           clock 38400000( Q9 A+ c2 D' u; K
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off' J1 l- L5 w; u9 i/ n+ _1 g' F
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 , k' B# G  O* G7 ~0 }
  14.     RX: bytes  packets  errors  dropped overrun mcast   
    5 O5 k  A; Q$ E4 u0 K2 Q8 Z1 y' \
  15.     64578440   1013451  0       0       0       0      
    $ Z+ D$ b# M7 G9 Q) \. Y
  16.     TX: bytes  packets  errors  dropped carrier collsns
    " P6 ]8 L( b/ h& o
  17.     952448     15914    0       0       0       0   
复制代码
位速率和采样点的些许误差测试并无影响.
5 R6 I" }9 T" C/ w# ], A5 w! j
0 d1 O& ]6 u, n- G- a2 |$ e( _使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:% v$ W* G- F$ ^

* p4 ~. M- j1 P1 c5 E
  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) o$ G1 h2 o9 B. K' c
  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
    7 @0 G( r! ^2 x4 a9 i0 k% A$ U+ R
  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+ f" g& q- q- B4 z. u6 o. Z- s
  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, T' m2 J- X& M4 {, m+ w& v
  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
    . F; {( m7 t+ 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 3F
    3 Z5 s; ?5 X  [) z1 Z1 M5 z
  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
    7 C' j+ v) E. t9 ^" V: L+ ?+ g# H
  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
    3 F+ G) {0 M; }0 I- h, C
  9. % ~, h. _7 O* n9 U1 X
  10. ...
    8 z1 M% {( p; ?$ ^0 z- x; [+ K9 ]
  11. : R# B, v* L; f+ C# ]' Q# I
  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
    : A4 @3 L. L& l. D% _2 o7 b
  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( E( W( \$ p6 }4 e9 }, p% O" V; O2 H
  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
    * g  ?( N' M, O( X' P4 I
  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
    / K) ^7 T4 i& f' 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
    6 Y, @7 A) j6 C$ j# q
  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
    4 Y0 Z, f! Z- G9 [0 z) ?
  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& y5 E6 X; P3 G; s; J# s5 U
  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. e: D9 K8 C% }! P  `" {0 T
  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
复制代码

. d/ A  T' E$ Y  |+ m& [/ f6 t" F- C这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
5 t" d; B0 I& |  V' @$ `  K% V  ]% L3 n$ e5 i# r
Xavier发送脚本, ##后面的3表示开启BRS和ESI:
: J% `5 _6 Q' M" C1 n( ], ?8 S9 t8 @9 X6 K, ^
  1. #!/bin/sh. a# a2 C0 d1 w( x" J
  2. 6 J; U! p6 _1 y6 w
  3. while true; do0 L- Q% \  @% d3 d0 a* v
  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.165 I, ?' C* Q/ ~( 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% g  _! D' A/ T9 |
  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  
    $ l' q# t; K' R/ o( N- x' p, ]
  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' q" a, ?/ F+ b* d+ E5 r
  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
    ; V0 J. J7 ?5 z5 m3 m' M, d
  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  
    2 D3 M5 @/ q/ m; X7 j
  10.     sleep 0.01
    , V: d0 }5 }+ |7 e
  11. done
复制代码
) \9 J' r) o  L9 G% s7 N" m9 H
可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.- o# h/ I; w6 P) K" q
3 o5 }2 I  ~  u; w
核心思想是:& f9 v: o" \4 W) f7 u

$ N* N  \5 }% i: B. {Mode 设置为Classic Master或者Classic Slave, 而不是FD& U  \# x: @/ u0 z- [- H
仲裁段和数据段的通信速率都设置为500Kbit/s
5 G6 a, y6 f9 Z9 x8 x# h; a! u) ~5 c& {, Q: G. s; }6 d
2 M( E) h+ b- P( k- e
4 C) a4 z& z' j* {7 w. S8 U
赞 收藏 评论0 发布时间:2021-11-11 22:00

举报

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