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

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

[复制链接]
STMCU小助手 发布时间:2021-12-8 22:00
前景提要
2 r0 c) ~  [+ r* RCANFD基础知识可参考前篇:
8 g- D1 O$ T% i" B( Q/ S* t" lJetson Xavier/XavierNX/TX2 CANFD 配置使用
9 b" N5 \& t% [STM32 CANFD 基础知识7 p4 o2 v4 N. H  C, l
本篇用起来, 连接关系如下:
$ v# I7 f2 C% t6 _7 @# _6 O4 q9 j/ g6 |9 w, [/ M
20210222185812381.png
' o% [! S+ h* j  C1 E( {

/ Y& E' d8 g/ `: P, f' Z; ACAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.& U( W: ?/ u5 X) z

" n0 R6 Z6 K& X  f8 j9 [3 _! MSTM32工程搭建
0 B. S8 J4 ]! Z* sSTM32CubeMX配置步骤如下:* h9 I9 h8 C4 U! F0 v1 m
$ O- e. h0 C) X: n; `
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx
( [! y3 Y: p* _9 a: o: m4 d) f* F: Z4 _8 m  @! B; \4 C
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire3 h% L) a  |- z8 N

) M& g2 ]' O, M9 TPinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator
7 t. ^2 y! T' V% O4 t1 U( l" |9 u% U8 U: ]# N8 C
Clock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):
- I' a; K+ `; m7 c- |( y
20210222185828575.png

( N" `- y2 ]/ I- F' M% |
& E: a# H! ?! e3 H# `2 {; I开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:, {% v* d7 `( _; K1 h

6 Y$ w- w2 d+ w8 a7 [1 H: O
20210222185846781.png
( \! b. |. Z, \  j# x
4 W  a" s3 v6 m5 m
20210222185905935.png

; e+ @  p: B4 J" w% }0 z
$ G* B2 U( X6 Z9 cLPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:( Y/ \! p7 ]( N) Z! @- {/ m. ?7 j; d+ H$ w
) G( _" `9 x5 Y1 u( W5 E* v  K
20210222185926920.png
& _% O0 y9 V# m, F

: I$ [( q$ l0 R! S4 t- a1 nFDCAN1配置: 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:
$ i) ^$ V% {) L$ ^" R: [& N4 o/ M# H5 N1 e
20210222185949803.png
/ t% _* `3 }3 Z8 g+ J3 X

. K% G* i# n, R6 J
20210222190005173.png
" I; }! c. @9 o

  f! a. X8 ?; L4 T0 U2 G- j9 z% fFDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:* E5 C; {7 Q5 Q5 K7 E8 ]
3 n# g3 X; \, Q( `
20210222190054536.png

2 r: \3 W  T3 o# c9 ]0 U  d! l/ b% j; H5 ]8 ~/ |- f
Project Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.9 {; F: B, g" a

! |6 Q. R) V) n' G, s, q. ~Project Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral
6 R0 S* q9 U  J! g( d2 ?/ v$ ?% E  q4 ~' ^' [4 o
点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程./ {1 p) r% |0 a; ~& R

# {  A6 k8 O3 Y" H. o+ XKeil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:3 H' L3 d" \# [0 A+ y

& h# l5 E6 x2 B+ {Flash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.1 C+ [3 `0 Z; I* L
Pack选项卡, 去掉默认的Enable勾选4 {0 \& J/ u+ L. Q9 u  f& F
到此配置结束. 下面是手动添加的代码详解
% Q. u8 r7 A5 `: m! w  D
( M. C+ I% `+ O5 ?2 F串口配置
1 L, J9 I2 R1 x" w. }( w为 LPUART1 添加printf支持:8 r1 I# A; h2 Q+ Z: s1 \
2 E% n# x1 L! X
  1. #include <stdio.h>
    " `$ F  @# ]" }% L8 ^
  2.   M& u& J2 j. [# k4 m$ s' I
  3. #ifdef __GNUC__, Y2 X5 j# l) d, a5 \# k
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)% f) H5 F- E/ @6 Q/ ]3 V/ `" q
  5. #else. B+ R2 r8 R) U+ A" h( K' |+ k
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    : R- _7 H/ I: x+ Q
  7. #endif /* __GNUC__ */
    " ]9 Z; l3 n3 t
  8. 2 ^; z* n) I& j$ \& B' ~& `
  9. PUTCHAR_PROTOTYPE
    4 O  M3 ], p. S
  10. {
    + P; E7 g8 f1 T* v7 |7 J
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);
    + |# r$ N4 a( N6 T+ p% `" H
  12.   return ch;
    # W9 B, m4 w' w; n. }1 C# P* s
  13. }
复制代码

& ?* M0 F- @- e3 K% Z100us定时器# Y$ r* p; l2 H2 L
因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.# M9 j& I0 m; E5 g& P3 u& w5 G

" R& t1 ^. |* J+ q& d. h# K2 }
  1. /* USER CODE BEGIN 2 */
    7 e/ c+ E  W" Z$ e
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.
    # |" @4 k. R0 Y+ I1 Z# A% x
  3. /* USER CODE END 2 */* V, {8 i$ l5 B) M, \7 f# L0 {

  4. % {, w% x% d* m; |
  5. uint8_t tim6_flag = 0;0 [, W( Q6 i4 _8 V; \0 K3 P
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    - }% \& |. t7 N: T1 y2 P( p% `
  7. {
    : {) r# y2 y' B+ I; m) f
  8.     if(htim->Instance == TIM6) {6 ~& O) [0 ?8 v% n  o3 s
  9.         tim6_flag = 1;
    , c/ M5 ^3 l# f/ X- K7 e
  10.     }
    8 G; y) R3 }3 d% r6 |' m; E. F# s
  11. }
复制代码
) m2 S& v, [6 a: \- V
FDCAN配置6 ~' N# C* [$ W7 W1 p7 ^
主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.5 ^( h5 }& U, T3 S# k

0 u- |! X0 x2 t
  1. FDCAN_FilterTypeDef sFilterConfig1;2 n  t! O7 K8 k5 w* q! @/ y' i
  2. % l6 m5 \  u; y% Q. i* R
  3. void fdcan1_config(void)
    % _- {$ r3 a' ?7 U3 M
  4. {
    % Y3 T9 F- t! s% u
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;
    ! A* ~! `/ {, ~- l: {7 e
  6.   sFilterConfig1.FilterIndex = 0;) F: H( U" V) E0 p
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;) @/ d, ?" H. I' X
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    2 Y! O+ J& ]  W2 [
  9.   sFilterConfig1.FilterID1 = 0x00;
    ( o$ P& O# l# |3 X3 M7 f  G
  10.   sFilterConfig1.FilterID2 = 0x7FF;
    ! h, ^0 ?9 t* V2 B. X5 ~
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)
    ; u( L: I4 L% v# p  ?6 y" K5 d9 W0 z: r9 v
  12.   {
      I% J+ ?8 Z6 v' N. ]9 ^
  13.     Error_Handler();$ K( C8 L# O3 q
  14.   }) ?( z+ ~2 o# y
  15. & u8 W7 S; u; p  v. s4 j1 d' k
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;; n. s5 x5 E0 k; L8 |+ F$ c0 o
  17.   sFilterConfig1.FilterIndex = 0;( Z0 o0 s$ `  D  W, b  P; d: x; f
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    ( f" j+ q. e' z# [, q
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    . q( D3 w! Q7 U2 c
  20.   sFilterConfig1.FilterID1 = 0x00;
    & p; T" H3 Y$ ]5 B1 K7 _  i
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;
    ) o& U$ v) z1 e. A
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)+ Z( {# z0 x$ I4 k: a0 _! U4 _. d
  23.   {
    8 U7 G! v1 r6 j' v1 b' C; X
  24.     Error_Handler();/ L6 p  j" N7 e! p7 K3 y( j4 l
  25.   }  X) p) y  e2 |# Y! C/ _  _$ ?* A0 F5 Q
  26. - R- g6 y& i% C/ W6 c- u3 g  `
  27.   /* Configure global filter on both FDCAN instances:+ @0 ^6 ~0 a& X9 T; F4 T  R
  28.   Filter all remote frames with STD and EXT ID" ~# ^& H! y) N# ~
  29.   Reject non matching frames with STD ID and EXT ID */, }7 `0 s2 s! J* i! W6 T/ n2 r
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)$ j8 j; L% b! Z' E- b% \, `
  31.   {& w: t, ?8 F8 h7 g- ~
  32.     Error_Handler();4 A3 i" g4 `4 I3 v& `8 O) M; ^
  33.   }
    , {, j, h# c/ J
  34. * Q7 C# \/ N8 _6 ^, _; J! j( f
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */2 _  {# `8 A/ R
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)' N0 y- x7 \. y/ Q) f
  37.   {2 C$ Y0 w0 ]+ S/ O/ B' r
  38.     Error_Handler();
    . T8 z" W! M6 x" t* a+ Y
  39.   }
    8 o- b. h- c8 k& K6 ~
  40. 8 v- P! y) Q" P! y. ^1 W
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
    / U! `: r) H  p7 b
  42.   {
    : x' v* s' Q- h' r+ ~* r9 N. @
  43.     Error_Handler();
    ; e3 r, g+ m7 ?& _  j- C1 D
  44.   }
    3 r' Z" a. E2 p
  45. 0 k/ @1 u3 \7 z
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode.% W; P! W* u& H+ n
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler
    : `$ H# k' W; c' x0 `4 Z  W1 A) j
  48.         TdcFilter default recommended value: 0 */
    ' N% T+ _) D0 J9 a# `5 k3 i
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
    ) ^8 {1 i% K+ h" n0 V' |; X! Y
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);
    ( M$ O4 ^  G# \" S9 Y5 Q. O, m

  51. : y1 @1 E: D# l, G' j/ @
  52.   HAL_FDCAN_Start(&hfdcan1);
    / S- Y" d3 D1 V  J, |
  53. }
复制代码

5 [! z4 h* C- V这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
0 c4 n: b' c2 D7 K: x; k
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;$ a/ w1 m7 b' j5 y% \
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;/ i3 G3 X; g+ k
  3.   sFilterConfig1.FilterID1 = 0;+ P8 V8 ]; g# T: T1 b7 f
  4.   sFilterConfig1.FilterID2 = 0;
复制代码
用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.
: R$ t$ Q9 w9 D, a1 s2 [& N* u# z# Y
有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:( _1 z: z  P0 q1 Z
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码
8 w, A9 s7 \3 {3 a6 o
FDCAN2, FDCAN3的配置和FDCAN1类似.% ]. x% v2 r7 C
" |1 w) c# l# B# Q, P$ T" r
Bus-Off处理$ L0 S0 t! m  Y& |
如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:+ ~8 }: V  v& [; R

) u& \+ P  A9 c4 I9 g# V) b1 D
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)% l9 P, u1 D/ C* l2 p# @9 P) u# F
  2. {& F, \* i$ `5 ^
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);, u/ `: y% Y, I2 t
  4.   if(hfdcan->Instance == FDCAN1) {! m) i! L3 i) Z( D0 O
  5.     MX_FDCAN1_Init();
    . m0 U1 p& j! R% G
  6.     fdcan1_config();
    4 S/ J' [/ O% U, c* {2 t9 s4 l! t* q
  7.   } else if(hfdcan->Instance == FDCAN2) {( u: T/ M. e+ Q3 s  n
  8.     MX_FDCAN2_Init();/ b9 [6 N6 h( b5 A
  9.     fdcan2_config();  n' f, o% z% w2 v" g/ Y( j( A7 K7 l
  10.   } else if(hfdcan->Instance == FDCAN3) {
    " b/ ^  g5 K! x( i4 j" v
  11.     MX_FDCAN3_Init();
    9 T) ?* D6 I  c; `% G) v
  12.     fdcan3_config();0 e, P7 t# ?( N. Q
  13.   } else {
    7 Q" Z6 U& v# B
  14.   }
    7 O$ G0 m4 i% k7 m8 @
  15. }
复制代码

2 V6 `) Q; X& }3 y) Q新消息接收处理

( ?% u8 C4 R% d8 \3 `& l直接把接收的消息通过2M波特率的串口打印出来.
7 w, N* l9 p( @* C/ m
  1. FDCAN_RxHeaderTypeDef RxHeader1;
    ! G) s/ I' q, o+ I0 `
  2. FDCAN_RxHeaderTypeDef RxHeader2;' P! {/ m2 o. j) g7 ~
  3. FDCAN_RxHeaderTypeDef RxHeader3;: _; \# t- V  I1 I- v' c) P" f; i! g

  4. 8 O, D. E9 Q. g8 U$ f
  5. //RxHeader1.DataLength => can_dlc& b0 w; D3 N3 h1 |: `: w& w
  6. //0x00000 => 0
    3 W: m! r. g# n0 H* z9 ?
  7. //0x10000 => 1
    6 u9 k2 \; _5 e7 I
  8. //0x20000 => 2
    4 L5 S5 l0 x8 P' V5 t" w0 P7 }2 s
  9. //0x30000 => 3 2 _% w3 M4 {3 I; A
  10. //0x40000 => 4
    2 c" P. H; z  D# H& u& N9 P+ f% O" ?
  11. //0x50000 => 5
    ' Y& ]6 E1 Y+ g; ?+ o7 q
  12. //0x60000 => 6
      ^% ^+ \* d' c" M
  13. //0x70000 => 7 . t8 ]* }! R+ L) m' O1 Q
  14. //0x80000 => 8 ( v7 I& a. C, n
  15. //0x90000 => 12
    9 X0 {0 i, w: H- g& G
  16. //0xA0000 => 161 O% }5 p( L7 A6 j' B1 F
  17. //0xB0000 => 20
    + I4 h# i3 ~. c7 F
  18. //0xC0000 => 24" B7 n3 [0 e3 M3 Z, `0 {
  19. //0xD0000 => 32
    3 @& W  x1 r8 D( B
  20. //0xE0000 => 48* O- M+ `0 v* l& p
  21. //0xF0000 => 64
    0 r. i5 j! B/ f  ^% T& m+ ?
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
    2 s0 m% q. _6 n
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)
    3 Q* i; e4 E- d# l
  24. {# [# {+ w! n3 C1 O+ Z
  25.   return dlc2len[RxHeader_DataLength>>16];7 `& P( w4 ~. N0 a
  26. }
    / a4 \8 X8 v6 ]9 N! {6 q  f5 q5 q# j
  27. % \: D  ?+ n" n0 X6 K3 k! i
  28. uint8_t cnt = 0;7 c+ g4 S. t8 w) ?" n2 C
  29. uint8_t brs[] = {'-', 'B'};
    % s7 y& d4 j4 t* u
  30. uint8_t esi[] = {'-', 'E'};) g& u: k+ \0 p! _" W4 f  ^5 `
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)( h1 r' Q4 y+ a
  32. {+ L) t; N5 V, F1 q  p
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {
    & r. a: i5 Q# i9 \
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);6 L% ]& X9 t8 t
  35.     //RxHeader2.Identifier++;
    6 i% r9 B6 [5 C# E
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);. V4 i! ^& h" J. I6 ^% |
  37. ! e+ L: z6 }3 `, v& F
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);7 ~$ y: |% y1 ^
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));# g' x% {* z& M' v" T

  40. & ?3 s- ^. d3 |5 P- b; K
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    8 m' D3 B% R' P# U0 X# f& N/ T
  42.     if (hfdcan->Instance == FDCAN1) {
    0 ^$ I3 Q4 W+ H) ?, I1 V
  43.                 printf("fdcan1, ");
    % g5 g/ [( X( |. y) _' w" n
  44.         } else if (hfdcan->Instance == FDCAN2) {
    8 n1 v' Z) v8 @7 ?
  45.                 printf("fdcan2, ");
    : u. {& I% G/ r6 g
  46.         } else if (hfdcan->Instance == FDCAN3) {! V% G* n/ n1 w6 w
  47.                 printf("fdcan3, ");$ h1 n' R, ]+ F+ g1 V8 b
  48.         }# F! ?. \4 ~+ s) D1 e; Y
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier, ( }8 d" y4 g- o6 l
  50.                                   can_dlc2len(RxHeader1.DataLength),
    8 T  N% A3 A: W6 U, f5 Q- D
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],  A+ J' O$ x$ G( p
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);# U9 |$ H8 _# H
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {3 [& t2 n6 c; Y; ^9 C$ A
  54.       printf(" %02X", RxData1[cnt]);4 N; h3 R$ m8 X( E. N2 `7 X
  55.     }& Y- `+ b% a# o
  56.     printf("\n\r");
    ) g2 `& u1 N7 C6 z/ N; D! z
  57. ! B6 }# w& X7 y6 \- [* P3 p3 y# h
  58. " _- ]# W5 O0 y  V3 s8 B% g1 O( c
  59.     //if (hfdcan->Instance == FDCAN1) {% G' E5 S: a9 h2 l2 w2 ~$ l$ i* z' R
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    $ Z: ~: U7 q7 X6 b% p
  61.     //  //echo
    & ]# B; J, Q1 v/ p# ^2 P/ p
  62.     //  RxHeader1.Identifier++;2 A2 z) v* O, h$ |
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);
    5 d" e& M9 e0 k' G( S" L
  64.     //} else if(hfdcan->Instance == FDCAN2) {* H+ [8 L- r$ g  U1 I; \  ~0 `
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);
    $ Z% I) F$ e2 V2 {( N
  66.     //  //echo
    7 W& c2 Z1 a6 E1 X7 w3 _$ y( H
  67.     //  RxHeader2.Identifier++;
      b4 t& I: j& i+ m" z
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);2 V( d% P3 [6 p& R
  69.     //} else if(hfdcan->Instance == FDCAN3) {
    ; Z% v9 `2 F$ l" @( z# Z
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);8 s; C& l1 H' a3 M
  71.     //  //echo3 a0 t7 B# h. ~
  72.     //  RxHeader3.Identifier++;
    7 l6 l, f6 s' Q3 U4 {0 O6 p/ Z: U
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);
    2 k2 G8 l3 G1 V: S4 [8 k  p
  74.     //} else {  j# c6 n  w+ v+ d
  75.     //  - x4 k, K- |: {$ O( }
  76.     //}
    3 t6 L* O, l: u
  77.   }2 `9 I0 s! n. C% I! H5 g/ c: l  ^
  78. }
复制代码

4 T8 f/ _* U0 Q注意注释中 RxHeader.DataLength => can_dlc 的对应关系.
5 c* |" ~+ Y* c! }
7 ]' y5 Z" r( ^) ~2 ]示例如图:6 C- |& M/ T7 _9 e4 T
) X7 I: M5 Q" a; J* O( ?" J
20210222190024669.png

2 d: {0 c. R7 d' w+ s! M, m: }) u% |1 S( d
图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.
. b6 n. T: j) x! J
/ v* |& }. ]% t  ?: a* `printf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.
. Z4 r; g( T, l2 N0 ~6 c9 Z" v" a/ t6 |/ `6 {4 ^" e
发送处理
) I( h" i6 M) A; A- b( g发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.  C4 W. K: U" K) X5 E. W

" X4 ]9 ]8 x4 l+ d- `, e
  1. #include <string.h>( g  t4 }+ \( ^; A& z8 z
  2. 0 P% u- e7 W* G0 V  Q9 c+ L
  3. FDCAN_TxHeaderTypeDef TxHeader1;
    6 ?6 [7 @. }1 Q9 n- M$ v
  4. FDCAN_TxHeaderTypeDef TxHeader2;
    % F& }/ r: |) M) W. p7 r
  5. FDCAN_TxHeaderTypeDef TxHeader3;, G6 r2 I: C! x) l+ H, r

  6. ! a2 x/ C0 H$ ~' j4 z  M
  7. typedef struct {9 U+ q- ^: j( _1 b. ?$ L9 Q
  8.   uint8_t flag;
    6 I& o& T+ k0 D7 f. X- `, g% D
  9.   FDCAN_TxHeaderTypeDef TxHeader;6 M/ H- `' L+ F' {, S3 D: i" A
  10.   uint8_t TxData[64];
    , q9 o# X& G) q
  11. } FDCAN_SendFailTypeDef;8 n, M( N9 Q% E9 H; }; [

  12. 4 O0 j4 c9 d5 ^# `' z3 |" u6 F7 K
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};8 w( z6 K( C' W' a; I
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};5 _3 Z, {" a8 w9 ]) \
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};( P: p9 `% L; K  N  B

  16. 1 M$ L: q2 N+ ]7 T) g
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])
    " N9 N4 x$ }/ H0 L1 N( O+ t$ y  Z
  18. {
    ) B8 A# S; A; B% g
  19.   TxHeader1.Identifier = can_id;/ ^' \6 T8 s. B% \: p! b
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;3 ^4 h4 _) d$ D& z$ d7 c" n$ J$ v4 G) W
  21.   if(can_id < 0x800) {  //exactly not right. k1 ?# p4 q, a2 |2 b
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;
    4 z; z8 f- h+ M) h9 S  \% j
  23.   }/ i8 x% J$ ]- S* ?* g7 p
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;: C( c3 g/ E  Z) f
  25.   TxHeader1.DataLength = DataLength;/ P* l# |5 z7 I& h- Z
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    ! T3 V& N1 ]/ Z& W+ J
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
    : ]. c2 k! A- p  _7 l# D3 F
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;
    $ J( S" F  e4 A: v& O7 o
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;7 h; u, |7 A7 B/ N4 m) b4 N' q  O
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use
    9 K! v6 H, A. h  J0 F
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {3 @+ ^, G2 `7 d7 r9 Z4 f6 L
  32.     fdcan1_send_fail.flag = 1;; h- }* y% B+ h1 D$ v5 p
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));
    4 K  i9 L( Y- H, G, Z
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));
    4 g% n2 E  W3 B; l/ N$ Z, j6 B
  35.   }   z( c; {  F! B* I0 \) k
  36. }
    ( S/ c( h0 {8 t$ o

  37. 6 z5 r7 ?# j( @
  38. int main(void)# T6 v8 ^1 X: [2 l9 X8 T2 G% y( u: W
  39. {- n" |9 M) b" d8 V$ s5 o! I$ }* T
  40.   ...# M. `0 c$ c6 l5 E
  41.   /* USER CODE BEGIN 2 *// p* q. {5 q! q( S) {+ H( X
  42.   fdcan1_config();+ p8 f) \) ^  U& l1 |
  43.   fdcan2_config();
    + F6 @' z( @7 b5 |
  44.   fdcan3_config();
    - _8 [' K4 w* F) {3 d& f

  45. ( u3 R# f) j9 x( b, h$ Y
  46.   for(uint8_t i = 0; i < 64; i++) {
    + u+ g5 V% K" R5 y9 u
  47.     TxData1<i> = i;/ V5 u9 |1 M8 ?! ~) N, L
  48.     </i>TxData2 = i;! _& q9 N3 n9 `4 _( a- y
  49.     TxData3 = i;$ k( u/ j) N7 I/ Y
  50.   }5 o5 p) C) t+ P+ g( h# ]8 t# N/ q/ M. ?+ d
  51. ) N% Y8 e  `: n) x7 [
  52.   HAL_TIM_Base_Start_IT(&htim6);
    2 q) v; w  L+ u7 ]! O
  53.   uint32_t count = 0;
    1 \2 s! n+ Z! x9 K" J6 o0 K
  54.   uint32_t cnt_100us = 0;! w0 R9 U$ s0 v# E
  55.   uint32_t cnt_500us = 0;8 a* D3 D# |2 {, u. y; n- |' f
  56.   /* USER CODE END 2 */
    4 o4 J6 h0 Y& e( A+ F
  57. $ f& b% n: A5 }  y! d1 N0 w' c" g& s
  58.   /* Infinite loop */
    7 R8 L1 n7 i& m
  59.   /* USER CODE BEGIN WHILE */' W. b  |) S. J( D
  60.   while (1)
    % e" L6 ?) G0 _8 D7 K
  61.   {
    # |( A7 o- _6 _: N
  62.     /* USER CODE END WHILE */
    ; W) [1 `) T2 f) R) a
  63. . a7 s2 C( H: w
  64.     /* USER CODE BEGIN 3 */
    - G  y& G( i- U8 o- h% a$ p4 i
  65.     if(tim6_flag && count < 1000) {5 Z+ f: r2 C  O
  66.       tim6_flag = 0;6 E7 |% q% A6 X- y
  67.       TxData1[0] = count >> 8 & 0xFF;
    ( d& a7 n4 [8 H6 _) Q' R3 W" T/ i+ o
  68.       TxData1[1] = count & 0xFF;2 Q' S- w: v  Z, w  B9 p, ?+ w8 ~

  69. , w1 ~# {% E7 S
  70.       ++cnt_100us;
    + D+ |9 K1 R2 x6 V) h
  71.       cnt_500us = cnt_100us / 5;
    4 L. R0 P; x+ u* H! G" x- ^
  72.       if(cnt_500us && (cnt_100us%5==0) ) {. P8 t- {+ H8 M" T
  73.         switch(cnt_500us) {. p" q  `  @  d" B
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1);
    - C! [3 }; w; P5 W0 I( p: M
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);* n4 q5 B/ u6 f5 U, D+ Y( X
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;8 H+ Y! I+ O! Z. c
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;4 u4 H2 ?3 }+ d( M
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;
    / C% M: Q- m2 B6 k8 ^
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;
    9 g. I* \' L1 I+ D- d' M6 G
  80.           case 7: /* next send */ break;
    . _/ w, i5 l$ B
  81.           case 8: break;: r- P2 k9 s2 x# m9 p
  82.           case 20: ++count; cnt_100us = 0; break; //10ms
    1 q+ W: ~; h  i' N7 V* V
  83.         }, O6 r2 f* q% L! a! t+ P
  84.       } else {  //fail retransmission once
    , _# o9 H) N( F, i/ [0 T
  85.         if(fdcan1_send_fail.flag) {
    8 Z- Y7 t4 ?9 ~* N
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier,
    . G! m1 }8 _' K/ X
  87.                           fdcan1_send_fail.TxHeader.DataLength,- Q+ c7 t" o- N( i7 g+ i; ~
  88.                           fdcan1_send_fail.TxData);( H& t4 U2 h7 v4 ^: N) P+ p7 W9 k
  89.           fdcan1_send_fail.flag = 0;# h! e+ M% J0 g2 ~' E
  90.         }
    ' l$ E( C7 D, A. L
  91.         if(fdcan2_send_fail.flag) {. z5 c0 q$ |; M" f% }) T1 ^2 J
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier, 7 h& M7 b8 m$ |, j6 o( y
  93.                           fdcan2_send_fail.TxHeader.DataLength,; G: u5 Q" x% s) u: W
  94.                           fdcan2_send_fail.TxData);
    ; b' t# `2 H' ]0 C# ^$ h7 o
  95.           fdcan2_send_fail.flag = 0;- Y8 Z( Y- g+ X! ]
  96.         }
    , |  k7 z* L& T" I$ _" S
  97.         if(fdcan3_send_fail.flag) {9 E3 w) N& i2 W% }7 d1 I$ b
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier,
    % O0 D& \# N: J( H5 K6 h
  99.                           fdcan3_send_fail.TxHeader.DataLength,
    . m* Q% ?* A' j7 x" o  _0 M+ s
  100.                           fdcan3_send_fail.TxData);& j+ N/ u$ k9 W' j
  101.           fdcan3_send_fail.flag = 0;' u6 E/ r( e1 R, q* A7 K
  102.         }
    " k, x4 b+ q) z  ]: w' @5 m
  103.       }
    # _8 h0 G. H/ ~- o9 R) n
  104.     }" n3 I# J8 Z" U4 E, m
  105.   }* r5 z- j# ^/ b: I5 j, O/ Y
  106.   /* USER CODE END 3 */  5 f9 Q) w. W% b7 b6 t, v
  107. }
复制代码

6 X. L9 Z" }8 K$ z! V7 v7 p9 Ffdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.
1 i+ O; Q9 r4 O
# E; a3 M- E) a( M* G# q7 x发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.
$ Y& g, ?6 U: P& W& a. V5 }/ L% z) j) @; G; O, n
这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.
6 q" {9 _! a7 F, |+ u% \( f; c8 @8 r+ v5 S3 n
因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.
  f8 D7 H( w" J+ w6 z; Y
2 `$ P1 G& j( z4 y1 ~5 q3 ?* z6 n4 K因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.' [6 g+ H( q, t4 c& p
; N, V3 K: A/ K* B7 R2 {$ }
如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.
# S/ m; D& }9 ?# m4 w: X/ I$ y3 y5 O# [& a! `7 C
一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms./ z2 T" w) ^% Z( f" u& A( o- j$ S

4 E. q- y$ ?4 b- {9 K" O, _7 |程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.5 ?6 v: r0 h. o3 ]" Z; o# a

7 P* W0 b; G4 ^& q使用Xavier配合测试一下
/ s- S& b* R. B# b, T, k$ _7 u+ B4 a7 Z把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:
! c! `) I. v4 v3 J1 r2 U8 [$ ~1 E' }/ A, G
  1. #!/bin/sh
    & J9 F$ K" T6 l" |9 O! s, \4 `# A* e

  2. * N" b5 }9 ?- E- d- }1 Q
  3. sudo modprobe can& `% T% a. n. W- W$ B
  4. sudo modprobe can_raw
    - A/ i2 G  [; `
  5. sudo modprobe mttcan
    9 r3 a/ b! R$ B
  6. ; e0 R0 ~* `2 s: M3 u5 @* n
  7. sudo ip link set down can0; L! m+ ]0 Y+ B- @  G: t; I& x
  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
    2 r8 n+ p% v% B% C9 {3 b0 v  t
  9. sudo ip link set up can0 " q! h" C$ e- S- a" \
  10. sudo ifconfig can0 txqueuelen 1000. S1 V! d( w$ z, _: t4 Y
  11. 4 F$ e2 c, N+ j3 P7 p
  12. sudo ip link set down can1
    ! b8 ~5 P8 ]* M! a$ r
  13. sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 1008 {" m. h9 u% S% [8 m! Y
  14. sudo ip link set up can1
    0 j- J8 ^# Q6 |! I: M' ?& e
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
/ M. f$ z* w, D6 ]+ x
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.4 T7 g4 H, ?2 o4 Z
* X/ g+ b& p  W, K
restart-ms 100设置总线Bus-Off时, 100ms后重启.
; ^$ X4 V) d1 {) `6 ~
% H( y0 b/ D% [6 j4 b9 Y设置完后查看设置状态 ip -details -statistics link show can1:
4 N( O* P8 O/ B$ g/ e# O4 o
( ~# R/ e6 e* f7 j
  1. $ ip -details -statistics link show can1
    * U5 H! \5 {+ S3 j$ P' e
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10006 v, B: L' \' d! b: `$ ~( r
  3.     link/can  promiscuity 0 1 Y0 Z& f% d! b
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100 ) @5 H, {) |+ K0 @, h
  5.           bitrate 498701 sample-point 0.792
    $ o; e, c' Z3 @) W) y: k  Y* ^! ^
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1' @3 ?6 \2 F6 f/ ?3 ^
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1
    ! f/ ~& a0 k. Q) f
  8.           dbitrate 2021052 dsample-point 0.736 & l. W* i$ Y( r7 `' v& S/ e: S
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1
    7 [- y8 E8 Q" @$ O2 d. a" A
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 12 [- k! l) i3 g/ i: V& Z
  11.           clock 38400000
    ! V- v) {6 X" r& ?
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off* y( n" ^6 O& q: N& r+ e' F
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 ( b+ n1 x# `) u  s6 F
  14.     RX: bytes  packets  errors  dropped overrun mcast   * V: K; h9 n, ?# c
  15.     64578440   1013451  0       0       0       0      
    + {% E6 ~* G3 i# n+ o6 G0 Y
  16.     TX: bytes  packets  errors  dropped carrier collsns
    , h; a0 U% R8 T7 h( a* E# U5 e
  17.     952448     15914    0       0       0       0   
复制代码
4 o) N% ~4 Q1 n6 T( U
位速率和采样点的些许误差测试并无影响.
# c9 x8 O% W# L* ]. I3 I1 i# r
4 _, H7 U- {( {# m' m使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:% U9 }, G0 \; m
. V& Q6 m* f  Z% ^6 j
  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
    & k" V* [1 c! u6 N5 |. S' [0 V
  2. (1613988959.106191)  can1  RX B -  124  [64]  00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    $ z/ p+ p/ f/ ]) W
  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/ ]4 c1 `3 t2 _/ v9 \4 [0 o5 }
  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 3F5 e/ l5 T; o/ C1 u
  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( f7 n$ ~  ^: O- f0 e4 {
  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 t' d7 c) G$ Y! l) n# [$ n8 I; a
  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 3F6 O. e8 j- g  G4 A5 V
  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! p0 e3 t( o2 {) Z* T) @
  9.   m& E( }) x( P* v1 v2 j
  10. ... / q% ~1 a9 r4 A* J; `9 ?
  11. 5 `6 m  \8 X8 F. X
  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 3F8 W# b; T' I7 [/ V
  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
    $ v6 K6 r7 E: ~5 D2 ~
  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' Y, b: s1 i) e  t. d  q; O
  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' M8 n! g0 }  Q7 {- @/ T. F2 B
  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
    % A$ @7 Y6 _- \7 d+ w; u
  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" }/ d" b( h- D0 a6 S
  18. (1613988969.097116)  can1  RX B E  12345678  [64]  03 E7 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
    ( S+ [/ n7 a- x
  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
    0 I& Y) J1 S3 W1 ~- X! l( g' x8 m
  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
复制代码

. i3 z' }) S" J% |. @% s这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
0 k; T& \6 M/ y0 s6 m0 E. n0 a/ H! |+ h) ?: t
Xavier发送脚本, ##后面的3表示开启BRS和ESI:
: r9 s$ j" U* F; V7 E; h4 u7 ^" l  s( ^% s7 b
  1. #!/bin/sh+ K- V  s* _$ O  {
  2. 3 N. L, p1 p! G  ~! `4 z( I6 U
  3. while true; do" \/ Z% d. ^+ K' a
  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# R% O3 p) h; c/ a+ |. V
  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
    2 t* O) c: L# u0 l$ q  i0 a
  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 A# q/ f0 [0 _: e& ?4 ]
  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# d2 M# {- w' d; D. ]
  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
    0 N% r7 d  w. u
  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  
    & v4 |" E" B8 E( g+ O/ Y+ e
  10.     sleep 0.01
    9 x1 x0 x1 o, b0 z4 R; C
  11. done
复制代码
/ r3 [3 H% f) Z1 v) i: G3 I. p% _; C. V
可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.# o: m$ o) }3 N& k

* ], c) t4 [7 k' W5 Z# V
% }8 c% n1 u' K7 ~! i6 Q" Z- d2 ]9 Z' C& }7 I9 Z$ S& P' `
收藏 评论0 发布时间:2021-12-8 22:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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