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

【经验分享】STM32 F4系列HAL库使用双CAN配置及注意事项

[复制链接]
STMCU小助手 发布时间:2022-4-11 10:16
先了解几个关键词简称:
8 m, V; K+ E" D9 h最小时间单位(Tq,Time Quantum)* F/ ]* t8 a# m6 d
同步段(SS,Synchronization Segment)1tq
6 a: v- O6 s  W7 f9 h. A传播时间段(PTS,Propagation Time Segment)1~8tq
' b+ `3 e% l+ {6 J/ h相位缓冲段1(PBS1,Phase Buffer Segment1)1~8tq
6 I9 W; @* t1 t# P! U4 |相位缓冲段2(PBS2,Phase Buffer Segment2)2~8tq
, h0 c; b) s6 O$ R' D, s* }再同步补偿宽度(SJW,reSynchronization Jump Width)1~4tq% G* s* M6 M4 f2 t- G
波特率分频器(BRP,Baud Rate Prescaler)6 g; F+ W0 y# B2 e. K/ b, \- W
STM32把传播时间段(PTS)和相位缓冲段1(PBS1)合并了,形成了时间段1(TS1)。8 E1 m4 w5 W7 |1 T
  n: V" H4 Y' Y( t) K$ A, D
CAN位时序寄存器(CAN_BTR)用于设置TS1、TS2、BRP、SJW等参数,这些参数直接决定CAN的波特率。
, G  n# C# m  l) {" S- {, T4 M5 k& j4 e  u+ _9 F& P. E
35T9T~SVL76_%I_XNV$IE.png
$ c3 L; l: ^4 I9 O* r( \- a& V9 D/ B
SJW[1:0]再同步补偿宽度
' K% w. M- y- J: T( I% Y  `
  c" N5 k( J: `TS1[3:0]时间段17 H$ J0 A) h1 p0 E

& \, Y) @0 h8 X0 `TS2[2:0]时间段2! i! y/ t/ c: l( }

$ W# T4 s9 M& j# {- |BRP[9:0]波特率分频器( J1 \9 G4 H1 ]4 s; u% O: x. e

/ ~. b- g/ `7 m9 M! \! v% X可以看到没有同步段(SS段),这是因为STM32已经将SS段固化为1。- K" k8 k. v  i6 H
2 N& W% m( o& D6 ^# y: Z
下面这张图是波特率计算公式:
5 n  q' e) c" W1 E% k* q; C; H% F3 Q6 N8 V3 U6 Y/ S, c
4f9a0ef7766841fc8671353d8cb869fe.png
3 J3 @% j' U* p3 f5 V/ Z0 E  O2 N$ O4 y' C/ ?4 `
整合一下波特率计算公式就是这样的:
% c: X( T2 C' P* p* s4 I3 @: K9 E! @
波特率 = APB1 / [(1 + (TS1+1) + (TS2+1)) * (BRP+1)]5 Y; H* F4 u( Q7 i

2 P* d0 o0 I9 n+ ?在简化就是:波特率 = 时钟主频 / 分频 / (tq1 + tq2 + ss)
1 h) }$ C# R3 e
8 [& E/ ~8 z1 n, m; f其中SS就是同步段,已经恒为1,所以:波特率 = 时钟主频 / 分频 / (tq1 + tq2 + 1)
& h4 P1 u/ o1 \3 B
$ o) P/ L: f: l. l% n: O  R下面我们开始实际设置波特率,这里要注意,CAN的波特率最大为1Mbps。
# i# e7 l0 n  {2 A' t0 x! y% f% ?
$ ^  J4 u9 Q2 o( ?! h3 O另外还有一个参数是:再同步补偿宽度(reSynchronization Jump Width) 这个参数,其实就是一个由数个Tq组成的一个段,用来对同步误差进行补偿,可以简单理解为为了提高精准度的,例如两个CAN进行通讯时由于两个板子的晶振可能存在误差从而导致CAN的波特率没有那么精准,所以就需要设置一个补偿参数去修正,这个参数就需要根据你实际的板子情况去调整了。* R% I, J. c( ~9 q8 w, [
" ]! {+ ?! b! M# |# {( ]: E
时钟配置
' U; O3 {4 b0 f. p& u0 @) ?, V& ?. ~5 F
{B$BW2T@1}~OPZ5NDXMJ@XE.png
3 m* V) e) S7 c5 u
$ ~7 B5 Z3 ^6 K" P9 d7 dCAN配置
9 b; ]# j, U( ^! m     CAN外设是挂载在APB1_PCLK1时钟上的,APB1_PCLK1是42M。CAN的最大速率是1MHZ,本实验配置为500KHZ。波特率配置计算方法:4 c+ W9 _& G  B5 |7 u$ y/ N

+ l% T/ D$ R7 QCAN波特率 = APB1_PCLK1/分频/(tq1 + tq2 + ss),其中SS是SS段,在STM32中已经固定为1个tq# Q! P% W! H* X/ o) H, o  y& x

. \8 ?7 y0 A0 H, W* V本实验波特率 = 42MHZ/4分频/(14 + 6 + 1) = 0.5MHZ = 500KHZ* |/ d$ |, u! V' q6 x

2 v8 w' z5 `# z. q0 @2 o2 Z FUMC{T1CY`SX4$M1A]4K.png
& a7 ~& Q' t! b5 G
# Z% k- `& K" Y使能CAN接收中断
, q% O* h* z2 z+ l3 g7 k$ ]7 R6 s1 r/ I. n- y: S( A
PG]X3XYH(31K7GDRVV_DOEB.png 7 z5 R+ V/ p9 ~& ?0 g& B) p
; s- O) ^) _6 `
配置CAN的IO,此步骤必须!!要不然HAL库函数MX_CAN_Init初始化会失败!!
6 M2 f5 Z3 C& k& C) E# A

! Z7 v4 t7 k' H 8H%}DJ2O5VZ9YMAYI%IZ(GT.png / z) E5 P2 k3 R( W- W* M+ J
; `" a; S# v; w- X
CAN2和CAN1是同样的配置,这里不再贴CAN2的配置图了。
3 m& U1 O7 V/ a% a% ]/ N' V! P) i
9 V$ {9 L7 \+ j6 n2 TSTM32外设CAN过滤器说明

  a8 z$ P: L* t" C) f+ {1 L# ZSTM32CUBEMX生成的代码默认是没有设置ID筛选器的,所以需要手动添加过滤器代码。下面一张图,STM32的过滤器组:
5 u9 E8 t, K. u# L" L
' u6 m2 J" G! h% z
N%LJ~A{T4H[`7HOVKDQOZYY.png ' h4 ]+ `0 u$ W" i# n

; e, E' K: p/ m, Q- Y" BSTM32F407ZG有28组筛选器,一组筛选器有两个32位的寄存器,筛选器组可配置为四种模式:

% `1 T7 k7 ^- S/ K8 t  ~; `1个32位筛选器-标识符掩码模式,这时候筛选器组的两个32位寄存器一个用来存放ID,另一个用来存放ID的掩码
$ C% J/ E7 C* D* y两个32位筛选器-标识符列表模式,这时候筛选器组的两个32位寄存器都用来存放ID8 ?6 @  ?; [6 I0 g7 a- B
两个16位筛选器-标识符掩码模式,这时候筛选器组被分成了4个16位的寄存器,分别存放ID高16位+掩码高16位,ID低16位+掩码低16位- z, e  R; z3 K) H' C
四个16位筛选-标识符列表模式,这时候筛选器组被分成了4个16位的寄存器,都存放ID的高16位和低16位
5 L6 W* K% S( x0 A$ _' Y- V1 d( [8 r* C/ g3 Y
贴上我的配置代码:
$ g" {. ?! Y8 K" |. S! T* J

3 p2 N9 S5 }: k: a1 X

  1. 2 c% }* l# q4 m- p
  2. #define CAN1_FILTER_MODE_MASK_ENABLE 1        ///< CAN1过滤器模式选择:=1:屏蔽位模式  =0:屏蔽列表模式! d0 O2 O) O2 s' O
  3. #define CAN2_FILTER_MODE_MASK_ENABLE 1  ///< CAN2过滤器模式选择:=1:屏蔽位模式  =0:屏蔽列表模式
    0 h& j, z" p& A; Q+ g- X( ~4 |
  4. 9 t: m$ p# m# S: i
  5. #define CAN1_BASE_ID  0x10F00266                ///< 主CAN过滤ID0 \9 V' m+ p; r
  6. #define CAN2_BASE_ID  0x10F0F126                ///< 从CAN过滤ID3 Y0 Z1 |0 p" F* C
  7.   D' y( n3 i" f5 G5 u
  8. #define CAN1_FILTER_BANK  0             ///< 主CAN过滤器组编号
    / ~- T7 t) v9 g6 R" o6 x& r
  9. #define CAN2_FILTER_BANK  14            ///< 从CAN过滤器组编号
      E0 l7 z5 W4 D  }* N# R0 a
  10. 7 |' [8 p" B# Y9 q" X
  11. /// CAN过滤器寄存器位宽类型定义
    ' t$ s: F0 z! E# s4 ^, K% F3 \! \
  12. typedef union8 Q0 d, K6 i2 B% b  w6 k$ o0 {2 H4 z# U6 c
  13. {
    8 a. m3 T, x9 }7 y6 ^- N/ h9 I
  14.     __IO uint32_t value;
    . _& ?* O8 |: M* H4 g- E
  15.     struct
    0 P- P2 Q- [& @
  16.     {
    ; v5 m$ r( e: u4 }" a
  17.         uint8_t REV : 1;                        ///< [0]    :未使用3 Z- L3 e$ W+ x6 W/ L
  18.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)
    & l8 H5 r. P( B" p' K% }' x' K/ m1 a0 a
  19.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    ( b3 Z* A3 I4 [
  20.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
    - w1 z( b4 V4 I
  21.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID; z$ }" b0 l: S* M4 `: [3 v* |0 h
  22.     } Sub;
    4 G/ e2 P6 W7 x5 B
  23. } CAN_FilterRegTypeDef;# e3 Z0 G3 R! E2 I
  24. : n5 z4 e9 m# m9 a
  25. // CAN_FMR寄存器位宽类型定义
    ( J2 B; a4 H4 K, u5 j5 R- ]( I
  26. typedef union ) m! b" j* A/ o8 K# B- S
  27. {
    + Z' W: \+ J1 `! v% t
  28.         __IO uint32_t value;
    ) J  z- @# K- [$ Q+ \" Q
  29.         struct
    ) k( S# t9 }- X  d/ q* `3 f3 R9 f" V
  30.         {+ P; x' b- [; i# |# [5 ?
  31.                 uint8_t FINIT : 1;/ K5 X, [9 @0 P
  32.                 uint8_t RESERVER_0 : 7;
    : e: w8 R- P( b3 A" X% L
  33.                 uint8_t CAN2SB : 6;6 J! ^  @. x' ?
  34.                 uint32_t RESERVER_1 : 18;8 v' R% g- R" C) K+ n+ o
  35.         }Sub;5 u6 h7 e9 {- D3 f! E
  36. }FMR_TypeDef;
    " i( }# N9 K2 I" n4 B1 c

  37. ; I; s; }8 ?, o, f8 s# q
  38. /// 设置CAN1的过滤器(主CAN)
    5 R" H/ Q' I. n
  39. static void CAN1_Filter_Config(void)
    2 W) D- s) d+ l  E: N# F! {
  40. {8 g) c. L: ?# K6 g
  41.         CAN_FilterTypeDef sFilterConfig;  P5 F' D: |# ~# H4 {/ d8 ~
  42.     CAN_FilterRegTypeDef IDH = {0};
    ; V% w  \7 ?; P
  43.     CAN_FilterRegTypeDef IDL = {0};
    9 r5 g- o0 w: R7 L: O3 U/ x
  44. . |; A2 m4 A, b. A7 n' L
  45.         IDH.Sub.IDE  = 0;                                                                // 标准帧7 M( o! o: n4 m
  46.         IDH.Sub.STID = 0;                                                                // 标准帧ID值
    ! ]% ~4 N6 [3 H8 w
  47.     IDH.Sub.EXID = (CAN1_BASE_ID >> 16) & 0xFFFF;        // 扩展帧高16位ID值5 D! `' Z8 a  Y8 l
  48.         
    ; i! V( u4 @: X  H! T( @) H6 v) {
  49.         IDL.Sub.IDE  = 1;                                                                // 扩展帧
    ( e4 z: e# @  t, F& a) u) p
  50.         IDL.Sub.STID = 0;                                                                // 标准帧ID值
    7 h. o' x& D/ w* x
  51.     IDL.Sub.EXID = (CAN1_BASE_ID & 0xFFFF);                        // 扩展帧低16位ID值4 U; |; B2 y) L1 `! i5 T( @; C

  52. ( P+ G2 N5 P0 Q5 w
  53.         sFilterConfig.FilterBank           = CAN1_FILTER_BANK;                                                                // 设置过滤器组编号
    ! f8 [1 I9 k" J( r
  54. #if CAN1_FILTER_MODE_MASK_ENABLE- K6 X* J$ y2 {5 d# t
  55.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                                        // 屏蔽位模式
    % c3 m$ ]+ c  o' a+ E4 y6 b& c$ Z
  56. #else1 b. x* r3 x4 \  }& E/ E' B$ P
  57.         sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                                        // 列表模式
    2 p( D- b9 i3 K0 o
  58. #endif2 r# V9 ^" W/ e) |% p
  59.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                                        // 32位宽/ n) Y$ D1 c9 @/ t- K& T" `+ x8 a% q
  60.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    % N: X& C( L$ c/ f1 A
  61.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位  u5 l' w1 g4 W
  62.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位+ L# E& R" \2 y* c/ A. v5 a! u
  63.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位* N, F/ D0 E: B& T1 b' p( F* C/ p
  64.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                        // 过滤器组关联到FIFO0
    + m1 Y6 \( [( n$ T8 e
  65.     sFilterConfig.FilterActivation     = ENABLE;                                                                                // 激活过滤器- I! W. Q/ I  y/ ^0 y/ z2 e
  66.     sFilterConfig.SlaveStartFilterBank = CAN2_FILTER_BANK;                                                                // 设置CAN2的起始过滤器组(对于单CAN的CPU或从CAN此参数无效;对于双CAN的CPU此参数为从CAN的起始过滤器组编号)7 E: l' Y" f! n1 U# }+ X$ B
  67.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    . C% v" u  h1 @
  68.     {
    , P2 P; r; F/ S
  69.         Error_Handler();0 K! H! |7 ]1 G* L
  70.     }5 Q+ K5 a4 {' O% ~
  71.         {
    + f- M7 ?5 h4 T) H9 q3 A/ p
  72.                 FMR_TypeDef regval = {0};
    2 C/ v' Z. U$ y, C0 l/ r0 i+ x
  73.                 regval.value = hcan1.Instance->FMR;
    4 g' ?! C2 j9 I. G! }
  74.                 printf("------ CAN1:> FMR:0x%0X  CAN2SB:0x%X  \r\n", regval.value, regval.Sub.CAN2SB);' x1 T2 G6 `5 ~7 K: t3 w0 P
  75.         }, j! U4 B+ _. }: z3 V* s3 R  \3 o; s
  76. }
    5 S8 |" v; F4 Y' A* ], X( n5 e- j
  77. 2 p0 v1 D  i: i- t" P+ _; o5 g
  78. /// 设置CAN2的过滤器(从CAN)9 j( z. ^+ R! V& J
  79. static void CAN2_Filter_Config(void)! }6 i. u; N* c$ u8 `
  80. {
    . l' s# w8 i; ~
  81.         CAN_FilterTypeDef sFilterConfig;* e. L& I7 Q0 V. M* s. a
  82.     CAN_FilterRegTypeDef IDH = {0};; }+ g& s3 U. t
  83.     CAN_FilterRegTypeDef IDL = {0};
    1 I& |9 @% f* @. w

  84.   {/ [! l' @9 w& G! P9 b
  85.         IDH.Sub.IDE  = 0;
    # `, u2 O2 m. m  A2 Q
  86.         IDH.Sub.STID = 0;
    ' Y& V- K5 P% \: V% q6 z/ [# N0 a
  87.     IDH.Sub.EXID = (CAN2_BASE_ID >> 16) & 0xFFFF;, [8 a. H! N- q- r" V) [+ c4 y  `( Q2 D
  88.         
    2 X, @& R, W6 U6 Q8 v# v3 }
  89.         IDL.Sub.IDE  = 1;* T: T0 X9 d7 {0 }6 G
  90.         IDL.Sub.STID = 0;, Z* j. i5 j' Z4 |* Y
  91.     IDL.Sub.EXID = (CAN2_BASE_ID & 0xFFFF);
    + }; ?1 ~7 L+ {

  92.   [0 B8 |+ S3 {: |. ?
  93.     sFilterConfig.FilterBank           = CAN2_FILTER_BANK;                                                                // 设置过滤器组编号/ ?1 s2 L! C0 H5 g
  94. #if CAN2_FILTER_MODE_MASK_ENABLE, b8 Y9 ]! X5 d; Z
  95.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                                        // 屏蔽位模式7 H! U9 S# |4 y
  96. #else
    - V5 z: |1 G! r
  97.         sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                                        // 列表模式
    % @5 K! u: W; V8 W& `( W
  98. #endif* T& B! I" {6 g9 {
  99.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                                        // 32位宽0 K9 g4 N7 L! Y) G/ i
  100.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    3 Q/ a: c- m; F! `" g; C
  101.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位
    , a$ p9 t9 P4 B) R. a! r. Z; s
  102.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    * n+ }0 d1 O6 }3 ~
  103.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    , N$ F. q1 y; M
  104.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                        // 过滤器组关联到FIFO0
    ! d4 c5 N. |8 a% Q) I& D
  105.     sFilterConfig.FilterActivation     = ENABLE;                                                                                // 激活过滤器; M" G: b4 ^$ T
  106.     sFilterConfig.SlaveStartFilterBank = 28;                                                                                        // 无效
    4 G& G# J5 b! e( [5 |9 O
  107.     if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
    1 t! L  f) k% ^. r& I
  108.     {
    ; _5 M* I% t' Z
  109.         Error_Handler();5 x% q* T  S, F! \
  110.     }
    + u9 a; t6 R4 h% n2 {
  111.         {1 `9 |! f# x: p/ D% n- O
  112.                 FMR_TypeDef regval = {0};
    6 W. h8 ?2 @5 C4 O
  113.                 regval.value = hcan2.Instance->FMR;* T! P4 L/ ~* ~: r2 v  r& v) w4 b
  114.                 printf("------ CAN2:> FMR:0x%0X  CAN2SB:0x%X  \r\n", regval.value, regval.Sub.CAN2SB);
    , a9 d. C0 D/ `3 |* h1 c9 U
  115.         }
    ; ]& r9 l- [; ~9 _3 c, |7 j
  116. }
    4 a6 _: W& i! Y0 P) a
  117. $ J5 k. w& N9 V# A& s) D
  118. /// CAN初始化
    5 w5 Q# R' v: m+ |- y! |6 x
  119. void CAN_Init(void)- f" j" p$ b: V2 ~9 G9 ]2 ~' e
  120. {
    / G% I/ v* L( p# K# y6 v+ {
  121.     MX_CAN1_Init();                                                                                                                                                // 初始化CNA1' A8 f% T. `; {( |
  122.     CAN1_Filter_Config();                                                                                                                                // 初始化CNA1过滤器
    ( O: E( _- e' N3 S8 Z
  123.     HAL_CAN_Start(&hcan1);                                                                                                                                // 启动CAN1
    9 W0 S& F: r* P5 y0 c0 a1 O
  124.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 激活CAN1 FIFO0
    0 b: [# Z" a/ h, M

  125. 4 N( j5 M6 ?3 K; G
  126.     MX_CAN2_Init();
    : S* O+ o  V5 L- }2 P, @
  127.     CAN2_Filter_Config();
    : r0 B/ s( @- u* O8 c0 y
  128.     HAL_CAN_Start(&hcan2);
    2 W' [# N' w( r. N, N4 ^
  129.     HAL_CAN_ActivateNotification(&hcan2, CAN_IT_RX_FIFO0_MSG_PENDING);
    0 K; t6 S# H* ~4 W( S
  130. }' s6 k$ Q# ~' f, f  F9 g
  131. / N6 @0 f$ d; a( h
  132. /**
    5 V5 x2 c, ]& D# w5 a2 l
  133. * CAN数据传输4 f4 m, D3 E" ?3 H3 @7 k& ~
  134. * @param  buf    待发送的数据! |2 r' |7 D$ @' r' w" c
  135. * @param  len    数据长度% ?: l; @! K0 a/ Y" M/ j
  136. * @param  number CAN编号,=0:CAN1,=1:CAN21 ]" \- v7 Y3 W& n1 R7 @/ Y
  137. * @return        0:成功  other:失败
    - j- F3 G2 _6 t& d
  138. */8 b5 a# B1 Q9 M  ?
  139. uint8_t CAN_Transmit(const void* buf, uint32_t len, uint8_t number)
    1 l7 t8 C& T9 d
  140. {
      D; Q, @8 |9 [/ b/ W% B$ L
  141.     uint32_t txmailbox = 0;- d+ e# U# G! G9 C
  142.     uint32_t offset = 0;
    7 y# A! f- i4 S$ X4 `4 {7 ^: O
  143.     CAN_TxHeaderTypeDef hdr;9 b$ }" p* L) T5 b' P
  144.   P9 e1 {. L# i2 f
  145.     hdr.IDE = CAN_ID_EXT;                                                                                                        // ID类型:扩展帧4 f5 Q7 Z+ Q- i# k3 q# L, @
  146.     hdr.RTR = CAN_RTR_DATA;                                                                                                        // 帧类型:数据帧0 `$ F! i: z& ?- X; ]5 w6 o
  147.     hdr.StdId = 0;                                                                                                                        // 标准帧ID,最大11位,也就是0x7FF
    ( {4 A  b" r! D; l: h( c3 m$ v3 n
  148.     hdr.ExtId = number == 0 ? CAN1_BASE_ID : CAN2_BASE_ID;                                        // 扩展帧ID,最大29位,也就是0x1FFFFFFF( ]6 k, F4 G3 X
  149.     hdr.TransmitGlobalTime = DISABLE;) t6 G6 [8 M% w1 Q

  150. 9 C/ a8 s5 L( l% L
  151.     while (len != 0)
    # o: Y4 c+ @3 |4 p) d- B- x
  152.     {4 s& D, o3 d6 Q2 J' m: x
  153.         hdr.DLC = len > 8 ? 8 : len;                        // 数据长度
    ' C! S* s; R" e0 @: L" o5 M
  154.         if (HAL_CAN_AddTxMessage(number == 0 ? &hcan1 : &hcan2, &hdr, ((uint8_t *)buf) + offset, &txmailbox) != HAL_OK)1 b8 V+ Y; {& y. B
  155.             return 1;) c8 t( T; C( Y& h/ r& H  f% c
  156.         offset += hdr.DLC;( M3 X0 Q9 u; |; Y0 L
  157.         len -= hdr.DLC;
    8 a$ ?5 j) v( X! l$ [$ @! ]
  158.     }& R* y! p9 w! E
  159.     return 0;( p$ a, q" }5 g. m2 z' h6 B0 C
  160. }
    $ v0 H: R5 C1 ~% M
  161. 1 V. z8 u/ P+ x- ~/ i6 K; B
  162. uint8_t CAN1_RX_STA = 0;                ///< CAN1数据接收标志:[7]:数据 [6:0]:未使用$ a+ a- H) f4 F. m6 B
  163. uint8_t CAN2_RX_STA = 0;                ///< CAN2数据接收标志:[7]:数据 [6:0]:未使用7 t9 O) `/ E' g5 J% t9 A/ X
  164. 1 I# d% z* c8 f' \' Z0 x8 i
  165. uint8_t CAN1_RX_BUF[8];                        ///< CAN1数据接收缓存
    3 J6 W' [0 v  |' g- G
  166. uint8_t CAN2_RX_BUF[8];                        ///< CAN2数据接收缓存; y9 c3 h8 B# h6 f2 A, `; H

  167. # k) B  f+ M# N" u
  168. uint8_t CAN1_TX_BUF[8];                        ///< CAN1数据发送缓存
    ( i% y" C- s; d& @- w5 O# b* l: g
  169. uint8_t CAN2_TX_BUF[8];                        ///< CAN2数据发送缓存3 y# A/ h+ N) `2 V: p& w3 ?

  170. - J& A$ c+ w8 `4 L& A
  171. /**
    3 ^# z, O( X7 \2 {3 z
  172. * CAN FIFO0 数据接收中断回调函数
    * j. D4 Q2 z+ D5 X
  173. * @param hcan CAN句柄7 n- l! v3 Z! ^1 M$ P
  174. */
    9 q; k1 x( A0 z2 I$ X  K
  175. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)0 k5 I' i2 e# n: a8 E3 E
  176. {5 _  ^- ]. {" c9 `8 C' `* u/ J
  177.     static CAN_RxHeaderTypeDef CAN_RX_HDR;) k! o1 s7 P0 \! e- W! [( h- ^

  178. ( K, w6 s, K, q; W& p
  179.     // CAN1数据接收* b; p/ a5 _, ?- Z% W" \" b
  180.     if (hcan->Instance == hcan1.Instance)/ F: ]4 i& l5 G7 K1 @4 {
  181.     {" d* L' n# @, B5 r1 R
  182.         // 数据已经处理* M% r+ }! B- a- Q. T
  183.         if ((CAN1_RX_STA & 0x80) == 0)
    & [9 ]1 V1 W! w1 x& l; l
  184.         {
    * \4 d* l# P3 N, S6 ^4 Q
  185.             // 清空缓存" G5 r# `" K3 a. ?0 z4 M8 ?( f/ P
  186.             memset(CAN1_RX_BUF, 0, 8);
    6 C6 m# q* u( g& |" L- t

  187.   G  r* A$ t3 V- k: u2 S
  188.             // 接收数据* l/ |" p5 t. q" _) a, X
  189.             if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &CAN_RX_HDR, CAN1_RX_BUF) == HAL_OK)                // 获得接收到的数据头和数据  {# w; R  w& n5 x5 \) E  a
  190.             {
    " W6 p0 z/ y. C/ l5 d6 x2 }/ l
  191.                 CAN1_RX_STA |= 0x80;                                                                                                                                // 标记接收到数据
    2 J- ^! p' g  Y" r* n( x" R
  192.                 HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 再次使能FIFO0接收中断
    0 j: X5 q4 h" ~
  193.             }
    6 q4 A1 I3 ~; [$ }
  194.         }# X" K% M$ u& H( W( a0 L  Z
  195.     }- m/ j3 o" v/ K! _1 [, Y$ o  p4 u, |
  196. % Y9 M6 j* H" W0 v/ g1 O! O4 v
  197.     // CAN2数据接收: a: x8 g; F3 B8 ^
  198.     else if (hcan->Instance == hcan2.Instance). M( h2 E8 e  `" L% T
  199.     {
    $ N: c( j$ ~3 y: y
  200.         // 数据已经处理
    6 v1 i" G! ^: w
  201.         if ((CAN2_RX_STA & 0x80) == 0)
    , t! o6 E8 z6 L2 z, d% {7 Y. x
  202.         {
    6 w2 \. x3 A3 Y
  203.             // 清空缓存4 i. m/ b9 S7 ]7 ?
  204.             memset(CAN2_RX_BUF, 0, 8);& b2 i; }1 s: X7 b- B  t
  205. ( h# S- e* P4 W$ K
  206.             // 接收数据
    7 h! g, F  ?  \2 C& e0 `
  207.             if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &CAN_RX_HDR, CAN2_RX_BUF) == HAL_OK)                // 获得接收到的数据头和数据
    9 ?' e  {- ]' t; J. \+ f
  208.             {2 ?2 |: C# J. |7 l; S" F$ t/ W
  209.                 CAN2_RX_STA |= 0x80;                                                                                                                                // 标记接收到数据  @! C) ]; l$ V: M
  210.                 HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 再次使能FIFO0接收中断, T) b' _8 N8 z5 ?5 g4 V
  211.             }
    . d8 m* e4 F) `8 r1 S
  212.         }7 _8 R7 R& L& o; k
  213.     }
    0 U  b% [  a1 W% T
  214. }5 [; _- R0 |, W# n+ P" c

  215. + ~. V& b7 _6 n3 G9 B: M
  216. ///< CAN数据处理函数
    ! C( e3 H' u8 H$ R" n' Z/ V6 y
  217. inline void CAN_RecvHandler(void)
    ( z6 H9 E* y6 L! Q
  218. {
    & A% Q+ K8 m' d) O. X! \
  219.     // CAN1有数据收到( v1 Y: y4 C) z% m# W& M3 s& ?
  220.     if (CAN1_RX_STA & 0x80)3 \3 A1 ]* O# @* o
  221.     {+ \2 K. q7 ?2 f% I, j4 Q- h
  222.                 int i = 0;1 b2 l/ h& {+ H3 r' R
  223.                 memcpy(CAN1_TX_BUF, CAN1_RX_BUF, sizeof(CAN1_RX_BUF));                // 拷贝出数据
    1 ^/ r' Z- ~! Q  J
  224.                 CAN1_RX_STA = 0;                                                                                        // 重置CAN1接收状态& e" `. F( P4 D4 Z4 h3 p" x# Y9 j
  225.                 for(i = 0; i != 8; i++)
    ( }3 Y; a( g% Z
  226.                 {
    1 S* O$ w" k( P! A0 l6 t
  227.                         printf("CAN1_TX_BUF[%d]:0x%X\r\n", i, CAN1_TX_BUF<i>);
    # ]- G0 c9 r3 E! r
  228.                 }
    , z0 `# j% R$ L
  229.                 printf("\r\n\r\n");( d2 N  l+ r; I+ M8 j7 N% f
  230.     }
    - _( p) }- R. x/ Y" T7 C
  231. ( ?: S/ K/ e$ K1 ~( l7 _
  232.     // CAN2有数据收到
    , V- v) R  H. g3 i" b" v; ^) F
  233.     if (CAN2_RX_STA & 0x80)
    7 P+ l: g! |5 Y* p$ g1 j# Y; n- m
  234.     {2 `6 m9 I. W/ J
  235.                 int i = 0;
    5 H( M" g  P! H" K" A" @0 J0 [3 ~
  236.                 memcpy(CAN2_TX_BUF, CAN2_RX_BUF, sizeof(CAN2_RX_BUF));                // 拷贝出数据/ w  {/ k! n# n
  237.                 CAN2_RX_STA = 0;                                                                                        // 重置CAN1接收状态
    1 g% o* i, `& n$ E5 M( I
  238.                 for(i = 0; i != 8; i++)
    % Y4 I4 ?# `0 t0 w, e; Q* k
  239.                 {" K+ }0 ~' t6 i; }7 m/ V
  240.                         printf("CAN2_TX_BUF[%d]:0x%X\r\n", i, CAN2_TX_BUF<i>);7 E) Q8 \  {$ O1 f
  241.                 }5 a/ h) Z- N+ z) \1 }
  242.                 printf("\r\n\r\n");
    : O1 h4 J7 v; @9 a* ~1 |
  243.     }8 o! z/ J3 {' s) L. T
  244. }) K5 Y0 m4 b- s& Y: W& \

  245. ' I/ Y- \  G: C5 T" K

  246. , b! C2 z7 w; R& s/ v

  247. ; W# _% x- l  x
  248. </i></i>
复制代码

( @' p1 R' U6 g8 n5 `
1 D' ]2 R: a. p) N
收藏 评论0 发布时间:2022-4-11 10:16

举报

0个回答

所属标签

相似技术帖

官网相关资源

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