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

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

[复制链接]
STMCU小助手 发布时间:2021-11-11 22:00
本篇用起来, 连接关系如下:) k  I3 V# z# C0 t
5 ?- S; {( X/ R; d* m+ u

20210222185812381.png


5 n' i* s3 l$ l9 p* q/ c( W  |6 m( P) r$ o+ t7 P
CAN收发器均选用支持2M及以上CANFD的收发器, LPUART到PC用STLINK连接.
" @* G0 a5 U' m! Z' s5 I; T
2 C9 [# l" l$ E6 ASTM32工程搭建  t9 v! w5 O6 O1 c6 D7 H
STM32CubeMX配置步骤如下:) v+ y( _" J$ o0 O5 D- f
9 A$ l+ M% R/ l! ]
MCU选择: 打开 STM32CubeMX, 点击 ACCESS TO MCU SELECTOR, 选择 STM32G474VETx6 W) V  S2 _5 Z' `( {
$ @) C7 a$ X: F; p) o
调试端口配置为SWD: Pinout & Configuration -> System Core -> SYS -> Debug 选择 Serial Wire) j, b# ?; Z3 t" r. @

  ~7 ?# P% v3 F' `& i+ pPinout & Configuration -> System Core -> RCC -> HSE 选择 Crystal/Ceramic Resonator: M* }* b8 M2 p3 b$ R% D
5 \4 n$ n% X8 Q5 x8 [: E
Clock Configuration(我板子上用的外部12M晶振, 主频配置成160MHz, FDCAN的时钟来自PCLK1=160MHz):
& r( x/ l. f6 `( b4 L# K  R

20210222185828575.png


; I" g# O7 O6 J9 g6 \' l& h

20210222195952515.png


2 Y8 d: W* ]2 _- s; O6 i! l8 H' ^# C; b& _4 n+ Y$ F/ u0 }' E
开启100us定时器中断: Pinout & Configuration -> Timers -> TIM6 -> 勾选Activated, Prescaler设置为160-1, Counter Period设置为100-1 -> 勾选TIM6中断:
( B' B# h7 n/ y; X- A0 Q( a1 K
: c3 _' G# M& y1 ~9 f" e. z

20210222185846781.png


4 z6 l' @# T% \
2 O& K" u& u2 G

20210222185905935.png


; J( h: B0 H$ Y6 X8 F
( H8 l4 w) E; B3 d) BLPUART1配置: Pinout & Configuration -> Connectivity -> LPUART1 -> Mode选择异步Asynchronous, 关闭 Overrun 和 DMA on RX Error, 波特率配置为2M-8-N-1:. E  \; C2 O4 N5 H, P8 _

9 [5 d. D, b% @9 t8 v

20210222185926920.png

; i2 b/ c. W3 r! ^
; r  V3 G0 O0 ]; t
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:& Y3 |2 C9 F# i. Y# X, {/ V8 {- c
( A! I( X6 s; X( h. v4 x5 x  z

20210222185949803.png

" Y) p, o; \6 D# n! Z  y4 X

7 ~' b4 k' W* {

20210222190005173.png


% r3 V9 f$ d' @* H; m) R- ^+ B, j: e' o% n3 [5 L, ~1 i9 `9 R7 c
FDCAN2, FDCAN3的设置同FDCAN1, 注意引脚要从默认改为板子上用的, 最终引脚位置为:2 w5 u; S( A) H+ ?, t

5 M) |* e  R4 [- T9 t1 O

20210222190054536.png

! F& B# j. ]7 r& _, G( k) P4 V

  @4 k9 ^" c' b, P+ ^/ v' F- ]" pProject Manager -> Project -> Browse 选择工程位置(Project Location), 填入工程名(Project Name), Toolchain/IDE 选择 MDK-ARM, 把Minimum Heap Size改为0x1000, Minimum Stack Size改为0x1000. 或者更大一点.1 [/ I3 o! c( Y) i1 P% C

$ w% [7 R8 m0 }# p& g- w. y3 MProject Manager -> Code Generator -> 勾选Copy only the necessary library files, 还有Generate peripheral initialization as a pair of .c/.h files per periphral7 q$ ~5 y  Y7 g, Q5 @4 ]

* S2 i; l. R; c7 y9 e% U1 d: _点击右上角 GENERATE CODE 按钮生成代码, 点击Open Project按钮打开工程.
7 k$ `4 z/ _' M) |/ b# f+ D/ j6 `2 n2 S4 Q
Keil配置, Keil 点击魔术棒或者Project -> Options for Target ..., 默认配置Debug为ST-link Debugger, 点击Setting:# |6 _7 B- b/ x7 j) K6 ]' [

& T5 h4 p$ e- _+ P: sFlash Download选项卡 -> 勾选Reset and Run, 这样下载后可以自动复位运行.  Y7 U+ A" f' g
Pack选项卡, 去掉默认的Enable勾选
. s) ^, a) L& f  }到此配置结束. 下面是手动添加的代码详解, y# {1 a( W' f+ O' @" O8 v# r
; c  U" N. W$ X
串口配置
& V  j: L2 W6 m# R  u9 L8 H# Z9 i为 LPUART1 添加printf支持:( K+ m- \6 {; n9 z. \
) p3 e1 |3 d6 }8 F: r! T) w( ~: W! w
  1. #include <stdio.h>2 d8 k' j! A1 l
  2. 4 n; ~' y: x4 b: n. |
  3. #ifdef __GNUC__
    8 n- r: e$ {* R5 D/ x( j
  4. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)' U: ~: d. W5 Z5 X0 h7 l% V
  5. #else
    ; C- m1 w% N3 P- l
  6. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)7 a, m2 K! M7 f1 R% e0 P8 ]
  7. #endif /* __GNUC__ */
    3 ], W8 P: ^6 ]1 `7 m* W
  8. ) f3 a3 ^, ]' \: d0 w& \
  9. PUTCHAR_PROTOTYPE: J0 q8 C$ p  x6 j( O9 Q2 B3 d8 J
  10. {( U; M6 }# p! n
  11.   HAL_UART_Transmit(&hlpuart1, (uint8_t *)&ch, 1, 0xFFFF);7 z% G0 R& K1 D5 k; \0 ^/ K; j
  12.   return ch;
复制代码

2 W1 v4 j. Y1 }. W100us定时器, z$ e1 s7 i' M4 C6 O4 T: Q4 I. k% u: \( J
因为用最大64字节测试的, 实测只发送的情况下, 1s传输最多2490+约2500帧, 再多就丢帧了, 也就是400us/帧, 保守一点, 这里设置500us传一帧, 如果没传出去, 100us后有一次重传的机会, 这就是100us定时器的由来.
: r8 N; ^- G" a( x  A2 U9 `
! Z* ~, Z# {& ^7 K4 R
  1. /* USER CODE BEGIN 2 */) @7 |# \8 z4 V+ I& [
  2. HAL_TIM_Base_Start_IT(&htim6);  //Starts the TIM Base generation in interrupt mode.
    ) w1 G$ c$ ]) h1 b" Z3 @
  3. /* USER CODE END 2 */
    8 h% F; s/ B- m, d# m. F& V+ V
  4. % C" l8 x) N# p; j9 l6 [$ N# h
  5. uint8_t tim6_flag = 0;
    / W% a! }" C, D
  6. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) ) w0 c7 l; W! c3 F9 g4 P
  7. {
    2 T6 R# j. C3 W( q# K9 Z
  8.     if(htim->Instance == TIM6) {' X$ e% \+ q% S; D! l) t
  9.         tim6_flag = 1;
    " N' k* G) r3 w( S
  10.     }. v/ Q' a4 y2 A% k2 T) i
  11. }
复制代码

% w  J* A0 p' ?FDCAN配置& H# p0 {) i! ^3 f' L  `. o
主要是标准帧滤波器, 扩展帧滤波器设置, 开启新消息接收中断, 开启Bus-Off中断, 设置发送传输延时补偿等.
9 W) V4 |. b: O+ O1 U+ m
/ V! Q7 r4 o4 f$ R1 \( }
  1. FDCAN_FilterTypeDef sFilterConfig1;* k1 g7 N" W2 S9 F7 h4 W
  2. 0 N, y' j2 v" I; C0 Q2 T3 g% ~
  3. void fdcan1_config(void)
    3 T9 k) }- r  E! i% o
  4. {
    . ~* `7 Y( \$ F% z
  5.   sFilterConfig1.IdType = FDCAN_STANDARD_ID;
    3 x9 o( p2 I0 r* d" p5 v6 E- j
  6.   sFilterConfig1.FilterIndex = 0;5 f, u+ D2 r6 w, f( Y
  7.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;
    ! p' J0 s4 i! n4 I; f
  8.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;$ }. W) ^& c+ Q9 W9 Q  J
  9.   sFilterConfig1.FilterID1 = 0x00;1 _3 x6 E0 i* s4 u& `4 `& f
  10.   sFilterConfig1.FilterID2 = 0x7FF;
    * \3 K' |% ^' C: _! Y$ P" R
  11.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)& C) ?) b  _6 g
  12.   {2 U* x% h- a' l/ l0 K$ D" T
  13.     Error_Handler();
    8 ~7 }0 {# g. H! B+ N# i7 z* C
  14.   }
    ! ~  e6 g, I  b! v

  15. 2 O/ o3 D2 I9 x6 N: j, A! \3 s: u- B
  16.   sFilterConfig1.IdType = FDCAN_EXTENDED_ID;
    * V, Z. O8 U- x% v5 {! d3 f3 y7 h
  17.   sFilterConfig1.FilterIndex = 0;& M2 m1 T3 e8 r3 A+ F$ r& o7 d
  18.   sFilterConfig1.FilterType = FDCAN_FILTER_RANGE;& u" A6 q* v6 n2 V. e2 H0 S. D
  19.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;( N% }# k0 B* f, w
  20.   sFilterConfig1.FilterID1 = 0x00;
      P3 W8 @: a/ b0 p. T2 r
  21.   sFilterConfig1.FilterID2 = 0x1FFFFFFF;
      q/ [) z, ?4 Q+ U: D* |1 z
  22.   if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig1) != HAL_OK)1 e; }$ y# Z5 P
  23.   {+ m# Q2 P# C! l% k0 |1 \1 ]
  24.     Error_Handler();7 v* f' i- u0 u( J7 o
  25.   }
    $ ^' h4 G9 |* k2 J+ |8 l
  26. 0 W1 L' H$ Y" E6 d; s3 ?, y
  27.   /* Configure global filter on both FDCAN instances:
    " e' q. m) x# g
  28.   Filter all remote frames with STD and EXT ID
    / x) r& @, \5 Z- o3 V) G. f
  29.   Reject non matching frames with STD ID and EXT ID */
    # r" N  d* U9 e  y' R* R/ G/ E
  30.   if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
    / e/ q, W8 \' m$ d* h, U& e
  31.   {) ]* P3 ?* o; h* h' {7 B
  32.     Error_Handler();6 @$ o- y( r; ^
  33.   }+ A9 \+ s  a& B7 [( K1 ]5 V

  34. 0 L2 L; o0 D+ n" A! Y
  35.   /* Activate Rx FIFO 0 new message notification on both FDCAN instances */3 g% r. R  Z. a9 q' [  j
  36.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
    0 k$ A; J' Z6 ?! N; ?2 l& ]/ x
  37.   {
    3 l' P, j9 @+ f. t6 I( _
  38.     Error_Handler();8 D+ V( O" N  }; A  z2 n' F' p
  39.   }
    . s" J" _; r# s3 ^! s) v% }- g( o

  40. 1 b% |* T- h) f- t
  41.   if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_BUS_OFF, 0) != HAL_OK)
    ; D1 A' o5 J; x0 R! s7 d
  42.   {) E, o7 D+ e6 w2 q
  43.     Error_Handler();# a/ X( }. _% |4 p! y5 H
  44.   }$ N2 k: ]# @' ?5 R4 o

  45. * G/ B9 B8 F- Q1 ^. l' R* Q
  46.   /* Configure and enable Tx Delay Compensation, required for BRS mode.
    ) _) c' A2 r0 ?8 g4 w
  47.         TdcOffset default recommended value: DataTimeSeg1 * DataPrescaler8 b& j! ^) A/ S% b; v& R! m) R6 n" b3 U
  48.         TdcFilter default recommended value: 0 */# l" v1 R" O. {2 e# }# \
  49.   HAL_FDCAN_ConfigTxDelayCompensation(&hfdcan1, hfdcan1.Init.DataPrescaler * hfdcan1.Init.DataTimeSeg1, 0);
    ' O  P2 e: f6 x6 J. ^+ j. Q" G
  50.   HAL_FDCAN_EnableTxDelayCompensation(&hfdcan1);" }+ J+ ^' P; x; N
  51. 0 h: Y) t" X- o' a- L& L
  52.   HAL_FDCAN_Start(&hfdcan1);: W' Q+ n  w% V) o- @
  53. }
复制代码

, v. X; S9 P, y' `9 I; D这里设置了用一个标准帧滤波器设置了标准帧的全接收, 也可以用掩码的方式设置全接收:
! `& _. i0 \( N' t3 ^" _* L$ Q
  1.   sFilterConfig1.FilterType = FDCAN_FILTER_MASK;6 E+ {( g6 `! _% v# H
  2.   sFilterConfig1.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    1 Y) F+ H+ E9 g$ W6 a; l
  3.   sFilterConfig1.FilterID1 = 0;! F, l; a  I. i# d9 m1 O: [
  4.   sFilterConfig1.FilterID2 = 0;
复制代码

% f9 y* ]; Q, t! Z7 K用一个扩展帧滤波器设置了扩展帧的全接收, 消息扔到RXFIFO0中, 设置了RXFIFO0的新消息来的中断, 也可以扔到RXFIFO1中.) C7 M- T- @  q3 n* p  @  c
! T& Z" F; Y( i4 ]; j+ Z( y: U: @
有别于STM32H7, STM32G474在STM32CubeMX软件中能设置的最大标准帧滤波器是28个, 扩展帧滤波器是8个, 这里程序中只各用了一个(index = 0), 如果想用更多, 不知可否手动更改stm32g4xx_hal_fdcan.c中213行这个值, 如把扩展帧滤波器数量从8改为28, 有兴趣试试:# e; W$ x+ c7 q

/ i- O; V& l. D
  1. #define SRAMCAN_FLE_NBR                  ( 8U)         /* Max. Filter List Extended Number      */
复制代码

* s& {9 v& S  d9 {4 W9 y+ oFDCAN2, FDCAN3的配置和FDCAN1类似.
6 Q) R6 I6 j6 Q' ~. E4 J' e. o! c% z9 T) }* |& p9 A# i: S8 L
Bus-Off处理
$ P7 z1 ]' X; O+ ]2 ^+ J) `1 l( k0 `如果CANH, CANL短接, 或者和其它节点的传输速率/采样点不一致, 会引发Bus-Off, 上面开启了Bus-Off中断, 发生Bus-Off时, 直接在中断中初始化FDCAN外设:
  N, T% [3 x' b7 e
6 K, T. x+ u5 n5 Y( ?. e- U
  1. void HAL_FDCAN_ErrorStatusCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
    ; m! ^; g( `) T5 {9 Y6 {0 }5 t6 T
  2. {
    5 ?. H1 z& s; c; {4 G( p! V
  3.   //__HAL_FDCAN_CLEAR_FLAG(hfdcan, FDCAN_FLAG_BUS_OFF);
    4 v: s' ~5 O' G# C: U: h0 X, R
  4.   if(hfdcan->Instance == FDCAN1) {
    ! ^" T% X& H. v" \
  5.     MX_FDCAN1_Init();4 t1 j6 m  G7 ?1 c, I0 g
  6.     fdcan1_config();0 `- m3 W! Y& ]/ l
  7.   } else if(hfdcan->Instance == FDCAN2) {4 r' {2 X0 a3 _0 E
  8.     MX_FDCAN2_Init();
    ' w+ P% E+ p- j) {0 V
  9.     fdcan2_config();( {6 W6 b- v4 K& x/ u
  10.   } else if(hfdcan->Instance == FDCAN3) {
    . E1 _' o; ?! p/ |; V( j
  11.     MX_FDCAN3_Init();
    * ~1 C1 ?& r* l0 S$ f
  12.     fdcan3_config();) W1 X1 H; x8 c5 y6 W! Y4 G
  13.   } else {
    0 s& o; _2 V5 R0 z: \; Z9 p
  14.   }
    & N' P, I- L  I: G# H. H
  15. }
复制代码
, _8 q" s& I* n- O. u7 i3 J3 U; ?, ~2 X
新消息接收处理4 l  {0 v4 V, i- V- n- r7 e# I
直接把接收的消息通过2M波特率的串口打印出来.) S3 ?+ ~$ {2 ~# @9 d: _4 g- h2 z

' Y' Y; J6 R6 t, g
  1. FDCAN_RxHeaderTypeDef RxHeader1;
      w: N% W/ o# e+ g0 O& q$ L  N% G
  2. FDCAN_RxHeaderTypeDef RxHeader2;
    % o* J4 D. a/ w8 }9 p
  3. FDCAN_RxHeaderTypeDef RxHeader3;
    4 r. D5 X$ q0 G
  4. ; Y; B# D: Q  V. L$ w7 S
  5. //RxHeader1.DataLength => can_dlc
    , g. R1 U  B7 ~, v/ H8 y
  6. //0x00000 => 0
      J7 l! E+ o- |) \6 V" L3 Z8 F# }
  7. //0x10000 => 1 1 w' Z/ s" u: j
  8. //0x20000 => 2 , w1 Z# `. l" T" L* {2 w3 c
  9. //0x30000 => 3 & X8 K) f2 |, u" x& F
  10. //0x40000 => 4
    * J! v6 c! d9 N5 D) O9 x4 X* j
  11. //0x50000 => 5 2 N* f, m' u6 F' B! x" e& Y& Z; w
  12. //0x60000 => 6
      y& y& K4 s4 |
  13. //0x70000 => 7 5 h6 T; p/ {$ H, _
  14. //0x80000 => 8
    4 C0 f- i9 y! {: q. R2 \' _1 k3 d! m
  15. //0x90000 => 127 `" [' t$ g" x# V6 t9 C) Q( D1 a
  16. //0xA0000 => 16  }* a  n8 h9 K/ z# p( D; k3 l
  17. //0xB0000 => 20/ H* [. i6 P2 P" e
  18. //0xC0000 => 243 ^* C) G2 _9 \, [* z/ B- m! ?' B
  19. //0xD0000 => 32% N5 j# C& Q2 _* G5 P4 Z7 T' ?
  20. //0xE0000 => 48( s* ~1 l0 s# L" `* Q- @4 k: b
  21. //0xF0000 => 64* B& X! d2 R: q! U/ V3 v
  22. uint8_t dlc2len[]={0,1,2,3,4,5,6,7,8,12,16,20,24,32,48,64};
    1 f+ N; C1 w2 _0 K4 B" D
  23. uint8_t can_dlc2len(uint32_t RxHeader_DataLength)) ]$ l- [/ P' j( C  ]! \
  24. {5 U( U: x2 ~& D3 k1 \
  25.   return dlc2len[RxHeader_DataLength>>16];
    7 ?: G' v0 F" x0 r) c% W$ D
  26. }
    0 K* U, s$ b1 L; N6 l

  27. ) e9 R3 P1 g* d7 i0 b
  28. uint8_t cnt = 0;
    5 L2 r% r2 f# Z- r7 Z$ m
  29. uint8_t brs[] = {'-', 'B'};
    * a+ F8 r7 U$ g; C
  30. uint8_t esi[] = {'-', 'E'};
      Z& ?# S- C1 @7 M7 g! I. N
  31. void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
    ) q* U9 U$ }1 U9 D' W2 T- W8 ~" s
  32. {& u( L4 v- k" E9 p
  33.   if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0) {7 N' e: b5 c; }
  34.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);' D* c) p2 U' X" i
  35.     //RxHeader2.Identifier++;
    1 |: n5 M+ m! J- j/ M
  36.     //fdcan2_transmit(RxHeader2.Identifier, RxData2);
    % @. e. T9 H% ~) v- t# ^
  37. ( }( x: P, s6 m5 R. ?
  38.     //HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    $ T/ [6 V7 ~( B# n* P5 [5 k+ L7 |  u, w9 e
  39.     //memset(&RxHeader1, 0, sizeof(FDCAN_RxHeaderTypeDef));
    % _6 [& q$ T- _$ o, z
  40. 9 ]$ L4 [  `) ^( k9 m& |
  41.     HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);
    6 m. H- Q# _8 A
  42.     if (hfdcan->Instance == FDCAN1) {& o; A1 _& J9 ^
  43.                 printf("fdcan1, ");; {) g3 A" R. m" _' Z" B1 J. e! t
  44.         } else if (hfdcan->Instance == FDCAN2) {
    4 i  A% k# F% x7 ^$ N) N
  45.                 printf("fdcan2, ");
    7 l: S1 {2 h; n
  46.         } else if (hfdcan->Instance == FDCAN3) {! Z8 `7 P. u& A( }; }
  47.                 printf("fdcan3, ");: Y: M) v/ E& x% K  S6 R
  48.         }( ^' i0 m+ a; U8 r
  49.     printf("0x%8X, %02d, %c, %c:",RxHeader1.Identifier, 1 S6 I$ @. w" u5 R
  50.                                   can_dlc2len(RxHeader1.DataLength), - \# V  {- f" Y% A0 b4 [
  51.                                   brs[RxHeader1.BitRateSwitch>>20 & 0x1],
    $ g. c, y: T5 V$ s
  52.                                   esi[RxHeader1.ErrorStateIndicator>>31 & 0x1]);
    , f  V; D" ^; q4 d( D! a( f( r+ ^' I
  53.     for(cnt = 0; cnt < can_dlc2len(RxHeader1.DataLength); cnt++) {
    , ]5 n) ]1 b$ i( F; v0 ^
  54.       printf(" %02X", RxData1[cnt]);
    ( e& B  c: C9 ~- V. B0 e1 i4 k
  55.     }7 c* }" r- o! K
  56.     printf("\n\r");
      W& }2 i  K; l2 v2 {
  57. 0 K& t3 w/ y0 w6 s  W
  58. / D+ m+ u- z4 r/ D) v' D
  59.     //if (hfdcan->Instance == FDCAN1) {
    1 r3 R, o' w: e+ P! _% {8 ?, @9 w
  60.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader1, RxData1);* L; l4 n. V6 h2 g; Q
  61.     //  //echo2 s) F* H7 c0 i
  62.     //  RxHeader1.Identifier++;
    ; Y2 g! H2 D8 J/ u! z& B) o
  63.     //  fdcan1_transmit(RxHeader1.Identifier, RxHeader1.DataLength, RxData1);* \' K3 W. Z3 W( m: i" Z
  64.     //} else if(hfdcan->Instance == FDCAN2) {0 k/ M& m5 o1 n9 U5 v
  65.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader2, RxData2);  S4 v6 A- T' L, K7 a# }
  66.     //  //echo& V" T: P1 j9 E' W0 _
  67.     //  RxHeader2.Identifier++;3 }- g, M' f4 [# U
  68.     //  fdcan2_transmit(RxHeader2.Identifier, RxHeader2.DataLength, RxData2);- v5 L" r7 A6 l/ [9 e. h
  69.     //} else if(hfdcan->Instance == FDCAN3) {
    " [3 i# R% b; B/ U1 h
  70.     //  HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader3, RxData3);
    8 w8 }% R6 L* |3 v$ B$ h5 b6 A
  71.     //  //echo' D- H3 U6 x; ^) M5 ?9 b5 K- t
  72.     //  RxHeader3.Identifier++;
    2 w! i9 b: v% C, @) V
  73.     //  fdcan3_transmit(RxHeader3.Identifier, RxHeader3.DataLength, RxData3);
    * V/ Z/ S1 A# E* }% X+ d
  74.     //} else {3 U$ `1 P0 a* R* {* A4 Y
  75.     //  % M, S, x/ R& D, U- c
  76.     //}$ V0 l) G2 b$ t/ {7 ?
  77.   }1 k, ?5 d. I' ?5 s) D& [) V
  78. }
复制代码

, b, R4 U1 b9 {& l5 m注意注释中 RxHeader.DataLength => can_dlc 的对应关系.
0 M; e; A2 ~. j) Y9 K& }4 s4 A, Q, V3 E+ L# g
示例如图:5 `+ D- X  g8 Z2 |

2 r" \/ U4 b3 ^7 K2 O5 b# E. B8 S
20210222190024669.png

1 M% ], n9 W/ x( s8 b% J
6 j3 z- W! K, p" k  X  H图中消息来自fdcan2, can_id为0x18FF0005, 64字节数据, 开启了BRS和ESI, :后面是64字节的十六进制数据.# o5 T, q$ w. Y

9 ?* g$ k3 u1 c' S0 n2 jprintf还是比较耗时间的, 这里仅做低负载下的演示, 实际使用不建议中断中这么搞.
7 z6 k0 s: ?$ U9 u  o
* p6 {$ g4 \! R5 t+ h1 {发送处理
: |" l+ u# r" S4 i3 r发送开启了BRS和ESI, 如果发送失败, 就延时100us后重发一次.
6 G0 o2 t9 L3 n1 O  E! Q! E1 y/ v
9 {+ b/ P& G: w7 |2 Y1 K
  1. #include <string.h>
    . {# s% b$ C) G! n
  2. ( }. P5 u  V) Z  R& G
  3. FDCAN_TxHeaderTypeDef TxHeader1;3 T- i* o# C; ^5 [" Z
  4. FDCAN_TxHeaderTypeDef TxHeader2;* Z5 z, v. a1 _+ S2 ~; I0 [
  5. FDCAN_TxHeaderTypeDef TxHeader3;* ^1 h  X5 b: n& V" x, P- {

  6. 9 v4 C2 w+ p3 H: d5 v; Q" Z
  7. typedef struct {
    9 ~6 ^) q9 H7 b+ `* W
  8.   uint8_t flag;, {8 U! u4 B7 x  z% A7 `+ K& A
  9.   FDCAN_TxHeaderTypeDef TxHeader;
    $ p, y# t3 L( Z
  10.   uint8_t TxData[64];% N6 A) }; ?  X) J1 \9 j
  11. } FDCAN_SendFailTypeDef;- }* s3 y% y- }) K% b
  12. ; ^. F' e4 y: [
  13. FDCAN_SendFailTypeDef fdcan1_send_fail = {0};& `. r( ]- s" G9 S
  14. FDCAN_SendFailTypeDef fdcan2_send_fail = {0};: W. G1 L4 g# a2 o: K
  15. FDCAN_SendFailTypeDef fdcan3_send_fail = {0};6 _* `2 E4 D5 D
  16. 1 e7 C0 D9 |5 d, O, [
  17. void fdcan1_transmit(uint32_t can_id, uint32_t DataLength, uint8_t tx_data[])+ c5 R, M+ h3 Y1 E) [$ K& ~9 C; }
  18. {
    1 g3 [" ^+ g! _$ l
  19.   TxHeader1.Identifier = can_id;
    2 J3 y; D/ L3 ~4 W, _
  20.   TxHeader1.IdType = FDCAN_EXTENDED_ID;5 j, |9 k( R) }' g/ A  s
  21.   if(can_id < 0x800) {  //exactly not right+ ^+ M- q  O. J3 X2 J$ ?$ F. ?
  22.     TxHeader1.IdType = FDCAN_STANDARD_ID;
    ! o& F- u7 c# @8 Z1 s, O! H( ~3 g6 y$ L
  23.   }- J* r7 T6 r7 m# _
  24.   TxHeader1.TxFrameType = FDCAN_DATA_FRAME;
    8 S5 x& x3 U; O: ]+ }6 o7 K0 P
  25.   TxHeader1.DataLength = DataLength;5 A, j% l% Z* M/ H
  26.   TxHeader1.ErrorStateIndicator = FDCAN_ESI_ACTIVE;8 b' m7 b2 H: }& Q# x  X% T) ?
  27.   TxHeader1.BitRateSwitch = FDCAN_BRS_ON;
    & P) J8 Z( y  ]( \% ~, M
  28.   TxHeader1.FDFormat = FDCAN_FD_CAN;
    8 ^' i% t; O7 Z) S- p+ G
  29.   TxHeader1.TxEventFifoControl = FDCAN_NO_TX_EVENTS;+ h  a1 L3 `" @) @7 E. A
  30.   TxHeader1.MessageMarker = 0;        //marker++;        //Tx Event FIFO Use0 _5 B; g% D3 h3 _6 U
  31.   if(HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader1, tx_data) != HAL_OK) {5 o1 X+ b9 k4 B, P. ^9 I
  32.     fdcan1_send_fail.flag = 1;
    / ?* `. k8 E+ k5 I: o1 J; b
  33.     memcpy(&fdcan1_send_fail.TxHeader, &TxHeader1, sizeof(FDCAN_TxHeaderTypeDef));6 [5 h& u4 v& \
  34.     memcpy(fdcan1_send_fail.TxData, tx_data, can_dlc2len(DataLength));5 K, o1 x$ f; {; i
  35.   }
    # a8 \3 \$ a* |' s  g
  36. }
    ( B* B* R* p) W, H& }& b7 \

  37. 3 s' [5 z2 u. I7 Y& Y
  38. int main(void)
    - n$ [$ G  Q: A8 ^4 s+ L, ?* R
  39. {. P+ M: j. N5 V0 R# p9 t
  40.   ...
    5 w3 x' E8 {; P5 C+ b0 |- x# h
  41.   /* USER CODE BEGIN 2 */
    7 e) I+ H1 l. u, s2 p( B9 I8 g1 m* d( \
  42.   fdcan1_config();
    , V, s, P! y( a- h& C  @; y
  43.   fdcan2_config();
    ' E4 B6 L6 M& q4 q8 f; w' l# c
  44.   fdcan3_config();& n: l5 F8 I& y% ?" K
  45.   Z3 }7 H0 J) Z& G% b
  46.   for(uint8_t i = 0; i < 64; i++) {
    1 D1 L+ I; b! k# i2 V+ O9 z2 M1 o
  47.     TxData1<i> = i;</i>! g$ E& E! t1 s
  48. <i>    TxData2 = i;</i>
    4 `9 y( e) o3 C7 I, u! q1 a
  49. <i>    TxData3</i><i> = i;
    : L7 p7 U9 v5 r- r; Q% Z, W
  50.   }
    " x4 I5 G. V+ t. a( g7 \) }( C
  51. $ W9 F2 i0 [. @/ q, L) Z! ]0 H! m
  52.   HAL_TIM_Base_Start_IT(&htim6);
    4 q, @( C! J0 r  g  L
  53.   </i>uint32_t count = 0;
    * w  }/ n) ?: S% b
  54.   uint32_t cnt_100us = 0;* `9 U( I0 C/ C/ I3 L' B
  55.   uint32_t cnt_500us = 0;0 {( X( l6 l' w" o
  56.   /* USER CODE END 2 */
      D+ `+ W9 f2 P& u. u
  57. . y8 Q$ T0 G0 i
  58.   /* Infinite loop */$ j5 Z8 U! _* I$ {' ?7 d- k3 o
  59.   /* USER CODE BEGIN WHILE */
    # X1 G# |: @6 y. f. w3 u( y
  60.   while (1)7 \9 A0 c. u3 H' P
  61.   {
    7 X: A4 [9 w5 w6 K8 `
  62.     /* USER CODE END WHILE */3 {3 T; U. O8 V5 }- k

  63. 9 c8 d$ _5 R4 d0 _# y
  64.     /* USER CODE BEGIN 3 */
    ! n' |  l5 {3 V+ L
  65.     if(tim6_flag && count < 1000) {! `8 m3 R+ w3 L4 h4 T  u
  66.       tim6_flag = 0;
    ) _) n- V. g( U
  67.       TxData1[0] = count >> 8 & 0xFF;
    $ @0 s1 a, {$ U
  68.       TxData1[1] = count & 0xFF;
    2 c  c0 Z6 a+ M) i
  69. / \1 Z- k9 H9 ?& ~' _9 F* g
  70.       ++cnt_100us;+ M; L: \$ u9 a; Z/ T& M( `
  71.       cnt_500us = cnt_100us / 5;
    2 }" x: W9 A5 i# Z7 N! G9 ?4 X
  72.       if(cnt_500us && (cnt_100us%5==0) ) {
    - G6 Y+ ?& j% W/ q4 ?  u& B/ y
  73.         switch(cnt_500us) {5 q/ M9 U5 d" }2 p
  74.           case 1: fdcan1_transmit(0x123, FDCAN_DLC_BYTES_64, TxData1);
    3 ?6 y  P6 g6 [  z7 f( N8 Q+ m
  75.                   fdcan1_transmit(0x124, FDCAN_DLC_BYTES_64, TxData1);
    . Q- G9 C9 m& n# Z: q+ ^' \2 @
  76.                   fdcan1_transmit(0x125, FDCAN_DLC_BYTES_64, TxData1); break;
    1 L: ^$ ?$ d" S& K& }8 k$ r& q
  77.           case 4: fdcan1_transmit(0x12345678, FDCAN_DLC_BYTES_64, TxData1); break;
    % i1 }, ]6 c8 U
  78.           case 5: fdcan1_transmit(0x12345679, FDCAN_DLC_BYTES_64, TxData1); break;2 m! R$ I1 k) d
  79.           case 6: fdcan1_transmit(0x1234567A, FDCAN_DLC_BYTES_64, TxData1); break;
    2 o, M# d% @7 t0 H# v! i. ?; c; W
  80.           case 7: /* next send */ break;8 U! I  N& n( h4 K& w
  81.           case 8: break;
    $ H0 c1 i- x/ [5 u! f; N
  82.           case 20: ++count; cnt_100us = 0; break; //10ms1 h5 k7 }4 u- A* |" w8 q
  83.         }
    - g  _+ h2 w/ k# z% ]
  84.       } else {  //fail retransmission once4 f* l4 A# w" k: N& P( B: A' _
  85.         if(fdcan1_send_fail.flag) {
    " Y- C  Y, w/ @9 W
  86.           fdcan1_transmit(fdcan1_send_fail.TxHeader.Identifier, 0 Q& f! v; G: w+ N
  87.                           fdcan1_send_fail.TxHeader.DataLength,
    " Z* A% N# q7 n) U9 \* ]( z
  88.                           fdcan1_send_fail.TxData);
    5 P! m! X# M- y: ]
  89.           fdcan1_send_fail.flag = 0;
    , R7 S! W9 a) K5 k* K+ S
  90.         }& T, w9 L& x1 V5 _8 L- O
  91.         if(fdcan2_send_fail.flag) {% \. J7 ~: o: V8 E& X, V5 ?
  92.           fdcan2_transmit(fdcan2_send_fail.TxHeader.Identifier, + `2 b8 O5 l) V# S
  93.                           fdcan2_send_fail.TxHeader.DataLength,
    ( y& _0 Z' u; T
  94.                           fdcan2_send_fail.TxData);- u/ m8 b5 ?- V( T  p, c
  95.           fdcan2_send_fail.flag = 0;
    5 y( g, `: h+ A. r& G
  96.         }9 o7 o% a3 S: ~* c( O; S5 ], u6 Y
  97.         if(fdcan3_send_fail.flag) {9 \$ b5 q) j; }/ {5 c
  98.           fdcan3_transmit(fdcan3_send_fail.TxHeader.Identifier, - R" q, k8 w+ R* r
  99.                           fdcan3_send_fail.TxHeader.DataLength,( q/ y" l7 A7 `' b! w
  100.                           fdcan3_send_fail.TxData);: M& ^. m6 S2 v$ f( G
  101.           fdcan3_send_fail.flag = 0;
    " C' |! f5 N! G+ |9 S
  102.         }9 x# }* l9 c# ^' `7 b6 M& B
  103.       }
    3 z; y& x' \- h4 X/ Z
  104.     }
    5 ~- }& i- @, O; w
  105.   }6 h# z4 a' _4 ?# }9 V
  106.   /* USER CODE END 3 */  & b2 K6 e: Z+ ^6 }
  107. }
复制代码
4 W% K0 O2 D+ u( e* R1 G9 ]
fdcan2, fdcan3和fdcan1的发送类似, 3个发送函数可以合并成一个, 这里没有合并.8 O- l" Y0 h; @0 a
2 J, z4 G3 X9 ^5 D
发送函数中的DataLength指的是类似FDCAN_DLC_BYTES_64这种的宏定义, 而不是数字64.7 E7 o! c, E0 h5 g4 _; s# D. a5 k

; V* _0 U3 A- A- K$ `: A. N1 z+ M这里用can_id < 0x800只是为了简便, 其实不正确, 这种情况下也有可能是扩展帧, 但通常不会这么用.
" u+ p7 `: ]% s2 w, C$ n8 \
! D! t8 J" W- ?) C因为发送最多可以缓存3帧, 所以可以一口气发送3帧, 如case 1处, 也可以一帧一帧发送, 如case 4, case 5, case 6. 这里是1.5ms/3帧或者500us/帧.
4 r' x& I/ p4 [+ n1 }' x1 L1 t$ C2 P' V3 ^( K
因为总线中还有其他节点发送之类的, 有可能发送失败, 这里留了一次发送失败后延时100us重传的机会, 具体情况根据现场可另行调整.
2 B4 m- y" O9 J% M; b
% j1 _9 O2 @) w: H. q( s如果fdcan1, fdcan2, fdcan3没有在一个网络中, 可以一口气 fdcan1发送3帧 + fdcan2发送3帧 + fdcan3发送3帧.
% |5 G4 G8 h7 o* o, A
) r' \3 e' A3 {, D+ o* F一般车辆总线中发送都是最快10ms内把要发的不同ID的数据一股脑发出去(当然也有20ms, 50ms, 100ms周期的数据这里暂不考虑), 所以这里100us中断计数100次就是10ms.
$ b5 \$ N9 g* K# l7 ^
- d  m/ L' [: I程序中发送1000*6=6000帧后停止发送, 10ms发6帧, 所以10s后数据就发完了.' c6 _! E  R  q$ M% }( C: a# y

8 L9 a; N. w9 \3 Q/ b: q使用Xavier配合测试一下
5 w4 z4 P& _! y( A5 g! v) r0 m把STM32的FDCAN1连到Xavier的CAN1上, Xavier CAN1设置:7 [$ y  C9 \: j$ e) x/ b

  G+ @% ?* C- p0 T
  1. #!/bin/sh$ g. ?' P( s* j
  2. 4 a9 ~8 `! ~  ^$ N; g3 D
  3. sudo modprobe can5 N: n' O3 g3 S% _, \6 N0 T
  4. sudo modprobe can_raw9 B0 F+ Y; e/ d, h2 D9 O/ m$ B6 v
  5. sudo modprobe mttcan3 q  L( N1 v0 d; e; [: q" ^3 p
  6. & T5 C) G$ ?# g) I
  7. sudo ip link set down can0
    - `4 I7 [- z( r3 s, t
  8. sudo ip link set can0 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 1003 g' J& D( O6 O& `9 u
  9. sudo ip link set up can0
    / Y. e1 B8 h6 A8 F6 t! U8 S5 a
  10. sudo ifconfig can0 txqueuelen 1000
    9 L) n4 s- P- m3 w  C
  11. 8 _5 S( W, ]( i
  12. sudo ip link set down can1
    + @, e( \" J$ C
  13. sudo ip link set can1 type can bitrate 500000 sample-point 0.8 dbitrate 2000000 dsample-point 0.75 fd on restart-ms 100. |, m) W$ o! t2 g" g+ I0 L
  14. sudo ip link set up can1
    / F6 P% @0 d2 O" u3 h) L$ r
  15. sudo ifconfig can1 txqueuelen 1000
复制代码
Xavier也是仲裁段500Kbit/s, 采样点0.8, 数据段2Mbit/s, 采样点0.75.6 m3 _% g. m. R) x$ [/ ~0 i/ x' I

  h3 b9 [; B" [0 u' [6 i6 rrestart-ms 100设置总线Bus-Off时, 100ms后重启., j9 f: Q2 i7 n
8 z" k; T7 }5 u. ]9 x
设置完后查看设置状态 ip -details -statistics link show can1:6 Q" v3 }/ }) l1 S$ }- r# }

6 A% ]+ Y; u+ j+ _2 g" A* k4 U
  1. $ ip -details -statistics link show can1
    : J" ]: O+ a% _# \( o/ W& u/ o3 a; X
  2. 6: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000# Q/ q& v1 j; D# Q. ^- t) L3 T
  3.     link/can  promiscuity 0 0 H. V  T1 g5 V3 y! ^' x8 I# t
  4.     can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100 7 B' }/ h7 k3 V  h. v! g6 B
  5.           bitrate 498701 sample-point 0.792 ' p5 [9 _+ z" D+ o! Z+ ~, ~
  6.           tq 26 prop-seg 30 phase-seg1 30 phase-seg2 16 sjw 1
    + \5 S' t: S% U: O7 z  b8 E
  7.           mttcan: tseg1 2..255 tseg2 0..127 sjw 1..127 brp 1..511 brp-inc 1' \6 }; k$ R! F, k' X
  8.           dbitrate 2021052 dsample-point 0.736 # x% R8 W0 w, k5 E/ B
  9.           dtq 26 dprop-seg 6 dphase-seg1 7 dphase-seg2 5 dsjw 1
    / q1 P$ N( _. {: E3 u
  10.           mttcan: dtseg1 1..31 dtseg2 0..15 dsjw 1..15 dbrp 1..15 dbrp-inc 10 N4 i! x" h2 m; Y2 g2 s
  11.           clock 38400000( Q4 u, ?6 ]; f) Z/ J3 B) _- z5 y! i7 |
  12.           re-started bus-errors arbit-lost error-warn error-pass bus-off# {0 T; H) T2 W# q5 f9 t
  13.           0          0          0          13         20         0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    0 h$ G! [  q& p8 @2 E% A2 y  a
  14.     RX: bytes  packets  errors  dropped overrun mcast   8 q1 f: w3 g) d5 q( K3 M
  15.     64578440   1013451  0       0       0       0       ) q& |4 S6 V+ R
  16.     TX: bytes  packets  errors  dropped carrier collsns ( B/ P2 f9 q% T! |  y' Y3 }
  17.     952448     15914    0       0       0       0   
复制代码
位速率和采样点的些许误差测试并无影响.
- b" x( F; x! p; u
' t- X5 [% q, T1 [, W使用 candump -ta -x can1 >24.dat, 这里-ta显示绝对时间, 然后下载STM32程序运行, 上面的6000帧数据全部存到24.dat文件中了, 共计6000行, 这里截取首尾部分显示:
- p! c: K& {$ N1 s9 I6 _
9 G) x( {1 {+ {6 T5 g
  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
    9 a$ w5 q; q$ f5 d8 L9 K4 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
    , q9 n  o# b% B, y8 d, b
  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
      G! ^! I! O. J
  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
    4 P8 h& v: j0 O  p% m) {  n
  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* G, B( R& r' z! f; A/ o
  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
    ' s( n9 A4 f* x2 v& O
  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 D* _* b6 N# ~# a& ^9 r/ c* D3 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: B- @3 u6 W% E% Q! `7 n; l

  9. + z2 _, l* W" V' z" \+ H
  10. ...
    3 U* `& B, V( D; v* N& y# {
  11. 6 v! [+ u+ f/ Q+ H. N8 {4 c3 m3 {8 h
  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
    . B  [# _4 s6 V8 ]6 j2 |
  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
    * v1 C3 }/ e/ n- @
  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 3F4 y" `* y3 m) R9 X5 ?7 `
  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! T: \3 x+ W* U) P
  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, ~" J* u0 I5 s4 a. `. u. s
  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 3F0 J- f( i7 p' ]# \
  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 3F5 H: M3 s7 s9 b) f4 z1 x, N/ |" U% 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 3F7 s5 e! V" q$ 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
复制代码
/ i( S( d! Z- y# Q- b" l0 ]1 m
这里前三行的格式问题, ESI的404行之前是-, 404行及以后是E, 暂时不解. 其它正常, ID顺序和数据都对得上.
, T: d2 l' O9 f. T' p. f& t$ Q
3 w8 a/ t4 b' W5 yXavier发送脚本, ##后面的3表示开启BRS和ESI:
7 ^# h, q# X7 P" n% `% l, G2 Y% F- Z6 k% s
  1. #!/bin/sh
    / G4 s- l8 o- w( ~% J4 e6 Z
  2. ' H& ~/ A$ O* N1 [  B6 j! ~
  3. while true; do3 M- Y2 V9 [0 L/ T% f6 W* `
  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/ w& _# @9 }  {
  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
    ' T6 @& K6 ]% K8 g% J
  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  
    # @. Z! }# l  t5 d
  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
    " M# |1 \  [& |' I* ?1 c! q
  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
    7 [3 L+ A9 c; q8 T$ f
  9.     cansend can1 18FF0006##3.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16.01.02.03.04.05.06.07.08.09.10.11.12.13.14.15.16  
      r  q: p9 b- I. k! H1 H
  10.     sleep 0.01& m" e" S0 y* w& A1 G5 g8 t. C
  11. done
复制代码

$ {3 K0 H. T6 U+ K" l可以在LPUART1串口中看到收到的数据, 如上面 新消息接收处理 小节配图.
, e7 H* [4 b# X, {# j% j
) c$ q9 y1 l) l3 W6 C% Z2 a8 u核心思想是:! m. O/ q. C2 l

. T+ E' {, F9 j6 ?) W" s( vMode 设置为Classic Master或者Classic Slave, 而不是FD/ Z9 r) Y# i$ o/ L- c
仲裁段和数据段的通信速率都设置为500Kbit/s. l- k5 h' A( A% H+ k* y
4 x! Y7 n) ?" c+ D

9 i4 g/ I* h: }. R+ |/ c0 W; ~
收藏 评论0 发布时间:2021-11-11 22:00

举报

0个回答

所属标签

相似分享

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