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

cubemx STM32 CAN通讯,多包数据收发送的处理!

[复制链接]
STMCU-管管 发布时间:2020-9-28 13:43
一、遇到的问题

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?
% ]5 e8 {; D3 K$ {: Y/ }/ D2、发送多包数据,网上基本上就两种说发
! s: H# q/ a' ^* z. r; G5 }*两个数据之间加延时9 j4 Y' n" |( S0 H* I8 a& g
*查询邮箱是否满了
" ~2 v  B) v1 X$ i& g; eHAL_CAN_GetTxMailboxesFreeLevel()2 ]9 ^/ Y( ?+ r2 z' W7 S9 n" E
对比上面两种方法,为了效率我们选择第二种

& ?! T# E) o. f* ]% x/ p


7 ]/ D7 e" C) k: C% d- l

二、配置与代码( b$ B+ S' ]4 \1 a1 ~; R" e) j
" k) W6 j+ E( _" p: a$ f) X

直接上cubemx配置


* v( t5 |2 G# D$ c7 `/ p

9 m# X5 q  Z; I

1_meitu_39.jpg

# o+ T) c- G6 m# O/ i
2_meitu_40.jpg

6 n9 a/ m; T7 Z7 Y
& @3 t3 ?: \: P9 X  c1 X8 ^' G% @% r
直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下


+ R5 L7 j# H% r  L: m7 f

  1. int main(void)- d- M) y* u7 h" d' }2 N0 L
  2. {3 x7 [9 \3 V6 |- z
  3.   /* USER CODE BEGIN 1 */
    $ F9 Z7 u% N/ R: G( X% @
  4. ) l) c' P% w2 D1 C% J
  5.   /* USER CODE END 1 */2 p. s* v$ p6 r7 T

  6. ! `$ L$ p! ^/ \
  7.   /* MCU Configuration--------------------------------------------------------*/! z+ L* H* Q( `- N' @

  8. . _, a2 K+ [, A' D
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */% P8 Q# \# c* z( h& A  `6 w7 q4 I: D9 r
  10.   HAL_Init();
    $ V$ R  t: d2 ~

  11. 6 }9 i4 m1 L- J( [" ~
  12.   /* USER CODE BEGIN Init */! h& D/ g7 K, o8 w' I4 k/ O' a" j

  13. : X1 [# W* o) b( \% z! [* R3 ?
  14.   /* USER CODE END Init */
    $ T1 x8 Q% p# O, U
  15. 1 t& ]% x5 T% {1 v
  16.   /* Configure the system clock */
    ; O8 C) N7 r6 k( P. ?( U
  17.   SystemClock_Config();+ g# u3 {0 Q# R1 X+ N( [' l

  18. 2 e0 `  h/ w! E/ r
  19.   /* USER CODE BEGIN SysInit */" R/ W0 X# I( v+ j- }, H  N

  20. / D! h3 j: E( ]; Q4 W9 l
  21.   /* USER CODE END SysInit */1 ]! I6 y* Q) X4 {

  22. 8 {" L! H: M( z; a
  23.   /* Initialize all configured peripherals */% t4 e- t+ W. V. n
  24.   MX_GPIO_Init();
    1 \1 j+ l: h( H3 z8 j% j
  25.   MX_CAN1_Init();
    & @5 N9 b3 e& E0 B; u  ^. S) x
  26.   /* USER CODE BEGIN 2 */  D0 Y. o: ~1 y! i6 _
  27.         CAN_Init();$ R2 W" _' y0 e  G! Z
  28.   /* USER CODE END 2 */
    / _- N3 M6 _5 r- U8 W3 n

  29. - q$ N6 {* y& J. u- N% y4 J3 h
  30.   /* Infinite loop */
    % A0 V4 L  Q/ C7 r
  31.   /* USER CODE BEGIN WHILE */
    - L' e& h* b$ ^& Z. g: k
  32.   while (1)
    2 h* v# u. a) U/ q; m+ L$ Z3 O4 X$ P
  33.   {
    " _* z. ^( E( U( H- r
  34.     /* USER CODE END WHILE */) g  G& W: y0 I( L" m% i

  35. / b% P+ C) e2 `% q: S* D& L
  36.     /* USER CODE BEGIN 3 */
    - l* Y/ K4 W: q% T3 P
  37.                 uint8_t TxData[100] ;. K* I* M* i( P" c& t5 A
  38.                 for(uint8_t i=0;i<100;i++)
    ; _1 Z6 T$ K8 A% F# J% b( E
  39.                         TxData[i]=i;
    2 p" n* `- {$ V2 b" ~  v5 L
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));! c3 G' h) ~: C
  41.                 HAL_Delay(100);5 b5 F  d9 x  t/ L3 ~% {
  42.   }0 v4 ^0 X- Z( u# w
  43.   /* USER CODE END 3 */: b4 z- R' P4 f5 K3 i
  44. }
复制代码
8 @+ O6 r; l' h  T  v

bsp_can.c


/ V1 n) t+ I( J
  1. #include "bsp_can.h"4 ^3 v4 o+ s  H: ]2 U
  2. 1 H) V5 V' Z$ u- [7 L. t0 z

  3. , ?- B6 R$ j3 N0 q: u4 \: p
  4. /// CAN过滤器寄存器位宽类型定义
    3 P, Y3 p( H) a3 [: Q, K: X; \
  5. typedef union0 E" U! E  |( P5 k; q9 L
  6. {
    ! B9 ?# S0 |6 s. v3 C
  7.     __IO uint32_t value;+ ~( N3 K# E1 w7 F% h
  8.     struct
    + t2 N1 |4 g+ d6 O" G, q1 K
  9.     {0 l5 [) N- H' l- W( k
  10.         uint8_t REV : 1;                        ///< [0]    :未使用
    ' t' t: E9 R# S- H- _. n* ~/ g: i
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)
    - b* L. L# c7 ?
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    ' Z9 E$ u1 ^9 Z4 y4 W
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
    " P* f! j% }4 n1 I% I% {9 W: R
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID
    2 ]( s4 Y( S9 r' w2 f/ ]& K" B# r9 X
  15.     } Sub;
    - n% s' h8 z; D9 D
  16. } CAN_FilterRegTypeDef;# Z7 j1 d2 u, r$ s7 A/ u; Z. n2 {
  17. ; r% i3 ?# d4 a

  18. 4 K! L/ p% _5 \. h
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF
    : h( p9 k+ y/ Q" `4 X
  20. ! H2 L9 m3 @# R: F. T* ?$ Q
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式2 m) V6 {0 a" \9 W) D
  22. 5 J8 G% H- `8 i0 t3 m( ]2 s. c
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID8 R, T8 X: |6 k1 ]  q$ m4 A0 f3 ?
  24. ! q7 h3 e+ v. y, [, L6 B1 M" @8 k
  25. void CAN_Filter_Config(void)
    : @' l; D7 q2 ?9 ?, Z. L1 K5 U# F, `
  26. {( B' ^# |  X/ x3 @9 t8 _: J3 L
  27.     CAN_FilterTypeDef sFilterConfig;3 A! r0 [" i7 s. @5 O
  28.     CAN_FilterRegTypeDef IDH = {0};
    4 W7 E  G# B" N5 v1 J" Y. W1 b" x) ?
  29.     CAN_FilterRegTypeDef IDL = {0};
    * T( _  ^1 ~6 C6 R7 G0 r
  30. 1 U) q3 |2 p( o0 o3 s
  31. #if CAN_ID_TYPE_STD_ENABLE
    4 b5 Z4 l" J! V% T) G2 h4 Y
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
    # r7 g7 L' V4 h! M7 O
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位
    , \) D3 F/ D( U9 l% Z& b8 u, y& }
  34. #else
    + |" r' E% |$ g& H3 A6 g/ b
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
      {% g: _; y) M4 w9 {
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位2 A, Q- S: v6 X" ]( \6 w9 a  T
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
    * p  {- B  ~( l$ _) ^+ M
  38. #endif
      U% `& E4 \. B- d3 e! Y4 \
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号! e7 b4 N* o; q4 @1 P. E9 h- ], x
  40. #if CAN_FILTER_MODE_MASK_ENABLE5 F9 w; v  O8 x5 H- R& }/ y. {
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式
    - V5 N/ A1 D4 ~) N& T* F
  42. #else
    : H% k( m6 s( b& G# F2 g$ [7 f/ S; @' ?
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    % E" _- k5 t1 U" x6 x
  44. #endif
    ' X6 I4 B7 J% X: j) O
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽  G+ P' k8 ^. o. P& x
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位) f. V7 p; I1 t+ j
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位. c; o+ t( G" v  Y" }0 p1 D9 o
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    $ O( T/ L0 l- R- E; Z
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    . D6 ^% [: u" @+ B* h
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0
    / W# r$ w4 E5 e8 {
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器
    / p3 W! G2 X( u: O; f
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效  E: V: D$ o* Z$ H& F& x, u
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)- H; T6 h8 V6 g0 F4 A# m
  54.     {& }+ ?3 S; `3 Y3 H2 W% B
  55.         Error_Handler();
    1 k7 \" Z1 [' K, {
  56.     }
    & C& x( S5 _% V/ c, ^" ?2 x7 L& q
  57. }
    4 ]9 q" b$ _) S! n

  58. ( Y3 Q! S& \0 [  |  V0 z6 S
  59. 5 u1 h& j7 c# e' ^( \; i
  60. . X$ j3 ~/ [3 f! d8 G
  61. void CAN_Init(void); z. M4 s. h! _, v& K, g+ T1 @3 ?
  62. {* Y3 z0 `+ H1 j, l. s0 k! D
  63.     CAN_Filter_Config();
    , S- A* m) N& k1 o) m  u2 Z, |
  64.     HAL_CAN_Start(&hcan1);
    ! ^  S7 ~, k  |$ F; Y
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断
    9 j/ u2 X; k) A; S
  66. }: Y5 c. ?, y9 S. @2 u9 S
  67. ! z: `0 v3 r3 |6 H; O7 m) C
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)! v1 H% t8 `4 x+ \( q
  69. {
    # g& I7 I. s+ {  E
  70.         static CAN_RxPacketTypeDef packet;
    6 ~) o' N' j# C1 G$ j: J, e
  71.         5 L9 T  ^; T6 v6 P" I# _
  72.     // CAN数据接收( I% g. \2 O0 u9 k
  73.     if (canHandle->Instance == hcan1.Instance)
    / B( w4 Q2 ?: j. C% [0 v
  74.     {
    0 I1 n7 b+ V$ H
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    , w! ?, N( c' L5 Q3 e+ {2 K
  76.         {
    & X( @5 |9 r! F1 o1 y
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");
    3 U& R( n4 z( |# R. w, v6 D
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);
    , l; b0 E. E$ B* u; J  `& A+ N2 l* L/ R
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    + q' m: z/ ^3 _
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);" T) I2 }/ X7 I3 v6 K
  81. //                        printf("DATA:");
    7 h" e6 b! j/ C2 I
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)( u6 o) I  d" ?6 R4 Q& r! u
  83. //                        {! y6 `) R/ Q2 d* i" A6 t, Q
  84. //                                printf("0x%02X ", packet.payload[i]);
    7 X$ T6 Q( r  r& y+ h' i
  85. //                        }
    2 E& M3 i# W6 ?; A' y1 U. J& U  p
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断
      V; S9 t1 k; w
  87.         }* T( E0 M- |& T
  88.     }: P4 C+ }! ]3 ~2 S) l
  89. }( A2 N0 H, H! f$ p3 Y+ w' L

  90. ! f: P" R9 N- s# j! C

  91. ! U; [: _! n; N2 e- L) {2 j9 X; t
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    ! y3 ~2 b: \* R# e4 I+ K* H$ |
  93. {
    " _5 Q5 B* J; V4 [& M6 g% g
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)# u: o: o( x* Y* A
  95.                 return 1;
    # |$ l3 k" r+ |3 H* O' }- B
  96.         return 0;/ k9 Y$ W, Z: d+ j" |
  97. }
    / z- I0 z; T/ ]# O  P

  98. 6 o3 l( K8 @) m& J5 H5 N7 X
  99. " p) _, @/ n2 E, ?
  100. CAN_TxHeaderTypeDef TxMeg;
    : F3 N% a0 q# m5 u
  101. uint16_t TimsRepeat;
    " b/ |* o( R* h6 ~' a
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)8 U% I. ]* a0 k& C& O( a- f" ^
  103. {6 `" T4 s3 r; s7 O: A# L; E
  104.         uint16_t SendCNT=0;
    - E$ B4 P& H) z; f2 l2 g# T7 [
  105.         uint32_t TxMailbox;
    . m& ~" _/ L; S3 H8 b7 M
  106.         HAL_StatusTypeDef        HAL_RetVal;( w* }3 M1 c$ x# h1 i8 m" t7 t
  107.         5 x( P6 R9 D' I5 k8 s8 Q4 }- ?3 F
  108.         TxMeg.StdId = 0x321; //标准ID* A/ A( ]4 ~! _' [+ }, h
  109. //        TxMeg.ExtId = 0x10F01234;
    , z( L+ p6 j- Z& D8 H% I
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型4 J4 C8 E& _2 R5 e
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型6 h" |( w1 G; r9 L/ \7 _
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧: A# h! y( T7 A2 \4 O% K1 u
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧
    , e3 f% |2 c/ F, l1 E0 \
  114.         TxMeg.TransmitGlobalTime = DISABLE;
      m+ T0 b5 m. y# h9 b
  115.         . R! A# q* ]5 f4 a% A
  116.         if(!__hcan || ! pData ||!Len) return 1;+ {# @! \: B( {$ g4 n% [* t4 e

  117.   g8 ^# `7 T) g
  118.         TimsRepeat =Len/8+(Len%8?1:0);
    2 ]0 v% M4 p0 t3 H; B, k3 \" Q
  119.         while(TimsRepeat--)
    7 A: Y5 n2 q1 G) C3 G& ]1 i, ^
  120.         {
    3 L5 h# }5 B) k# O
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);0 R7 g6 x" ?' Y- |7 l) |
  122.                 if(TimsRepeat>0)
    , D' K5 W, T+ K* S& i0 H$ S
  123.                 {       
    1 T+ w- v# z: j
  124.                         TxMeg.DLC=8;
    * \4 A: b4 A1 \4 @5 P/ i
  125.                 }
    5 A* S7 I- d5 Z1 x' A3 x
  126.                 else& d( j6 Y5 [2 ^/ F% m0 Y5 j; f) y
  127.                 {
    : _3 L5 ?5 M7 [6 E& W7 b+ N9 @+ @: c1 p
  128.                         if(Len%8)2 N' T% t' V( ^9 ~2 d/ c. \: S! j
  129.                         TxMeg.DLC=Len%8;6 V1 ?$ p# N. {; V
  130.                 }
    + [* q( e7 Q1 V0 [& i
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  
    0 I8 N" _. Z: O; A+ c: P4 t1 `
  132.                 if(HAL_RetVal!=HAL_OK)
    1 O0 l8 i& P- \) W( y
  133.                 {
    3 Y" W. y2 M. h+ v' F5 D
  134.                         return 0;9 E! b1 T8 {% q
  135.                 }
    9 e5 Q1 _: o$ Z  N3 ?8 l8 r* ?2 [9 k
  136.                 SendCNT+=8;4 p8 D3 d6 v) h. v  j, D* T
  137.         }& A9 [, K5 ]) N/ A- ]
  138.         return 1;
复制代码

. L+ x# }; _4 Y8 I( p  `1 ]6 D1 ?( l& i& E2 g  _9 J% @

bsp_can.h


4 Y9 B6 M0 p( O* b3 C% j0 b. I" q2 K

  1. #ifndef _BSP_CAN_H- H2 B, [: |$ q) I9 h+ k7 X7 D
  2. #define _BSP_CAN_H- `5 {8 \0 q( L
  3. #include "stm32f4xx_hal.h"7 o9 A- X& L! O9 a( U
  4. #include "can.h", Z6 \$ M' ]( Q& H2 |! x

  5. ) G" t3 I' M/ C) `- ^
  6. //typedef struct
    0 |% R: o9 N  Q. {  ?$ F* ~
  7. //{
    & J& r1 G0 @/ I" H# y$ n
  8. //        uint32_t mailbox;
    . b# D9 {9 N- w8 Z
  9. //        CAN_TxHeaderTypeDef hdr;
    ( F( q! D& v. _' a4 v/ x, L1 U
  10. //        uint8_t payload[8];
    1 \# k' e1 `9 @* Q, _6 N
  11. //}CAN_TxPacketTypeDef;
    2 O# J6 w* k$ f' J8 w6 F5 G

  12. % ~& ^. Q# c5 I
  13. typedef struct
    ) R9 p5 {$ ?8 S- U8 X. A
  14. {
    8 T5 V! P: W( X5 F# F
  15.         CAN_RxHeaderTypeDef hdr;
      m: v' `1 C0 C3 M! C) {1 H# }. V+ d
  16.         uint8_t payload[8];
    % n, H+ P! x6 {7 r2 K9 H: |( u% U
  17. }CAN_RxPacketTypeDef;% S. p3 _2 [  {: e5 X9 g. n
  18. * v; h! v) h4 t  I! d" |. G. \) C

  19. 2 Y4 Q5 f2 ~- `
  20. void CAN_Init(void);- F* y: R. P% C$ A) Z. k
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);
    ' E# v; x1 h: f2 L
  22. #endif
复制代码
" G. F: X" Y4 o2 p7 i

就可以工作了???非也
- d' H& v! \/ A9 ^' n+ d2 `其实我发现还是有问题


3 E! Z( X% K3 L# k

3_meitu_41.jpg
5 o. f6 `! q# R! o/ u- K: W
2 [1 B5 ^( Z7 W" \0 z( Y# t& e* g0 a

1 P, q2 X4 V6 X! k7 s% ?& I
为什么第2 3包数据到最后去了?

3 v5 n8 ~# w; h

查了一些资料发现了问题:
/ C! O9 n' p- T”发送邮箱“是用于CAN总线数据发送的,总共有3个,并且存在优先级关系。优先级越高表示其里面的数据会被优先发送。数据在发送前都会被送到优先级最高且空闲的发送邮箱,然后依次发送。最后说明一点:“发送邮箱有3个,且每个邮箱只能装一个报文”

原因是,三个邮箱有优先级,我发送前会检查三个邮箱是否都满,没满就发送。导致 第 2 3包数据在两个优先级低的邮箱,导致才最后发送

; Z7 ?. s  S9 N  C; `; r- i0 v

查看库函数
, n& f: ]8 J2 K$ {& _# n1 ~0 k& ~0 z

7 j4 g$ O5 K3 \9 }0 }4 b" W/ x) T

  1. /**0 H/ y. ~% b9 s" ^% g3 c& H
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    ( z  H0 ]8 T% N. h
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains1 c5 I. w; T' w; \6 M
  4.   *         the configuration information for the specified CAN.
    , `/ f. N% J; S2 e6 z* z: s
  5.   * @retval Number of free Tx Mailboxes.8 s  Z3 f6 ~5 `0 ]' X
  6.   */
      ^, U2 i9 I) R5 n) _; U
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    ) D# I+ n6 V9 S- {
  8. {# d7 f7 I! {- l$ i; F
  9.   uint32_t freelevel = 0U;
    5 n1 A6 S7 I. m) o$ c3 C$ t% N
  10.   HAL_CAN_StateTypeDef state = hcan->State;
    0 M& g: L+ H1 U1 {" l1 h4 }; q# b

  11. 2 j% h4 U- P) h/ t6 P
  12.   if ((state == HAL_CAN_STATE_READY) ||
    & W1 S2 O+ K" ]
  13.       (state == HAL_CAN_STATE_LISTENING))- i, l) s, E$ ^  w# _
  14.   {
    ' n) o# k) Q2 y  e9 X. r6 u
  15.     /* Check Tx Mailbox 0 status */
    * a0 e% a5 |! X1 v
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    ( a" ~- h$ ?/ g! _; @$ `8 m2 m
  17.     {
    " x+ E" `2 c. h
  18.       freelevel++;
    3 j. t, f6 F# i' c# Q# i
  19.     }0 ^: T# E% C9 ]

  20. 5 w5 v. J7 z9 [
  21.     /* Check Tx Mailbox 1 status */
    ' |0 d6 Q6 x  r
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    ! J! D3 Z& B& ~# `- E, s
  23.     {
    # q' K1 `; n- N5 y
  24.       freelevel++;
    6 p2 H  _1 x. [3 ]4 G/ b
  25.     }
    0 b8 E: C7 C# k% R2 c

  26. 2 h, v/ ], o1 a, z  a6 F/ C3 H
  27.     /* Check Tx Mailbox 2 status */
    ' @% T9 p- G) o9 X1 \* {
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)/ x  M; s  i$ b' N3 F  Q# i- |9 ^
  29.     {
    3 m( Q4 k2 A* a+ j- i) H
  30.       freelevel++;- b9 g2 Y, g* v+ K) C. f# Q/ Q2 m! e
  31.     }6 p% T- f% Z1 q0 M" o) y# B: w
  32.   }
    ( H/ M3 n& O% W- r

  33. % J" @' T# B" ]) Y; G9 d. R
  34.   /* Return Tx Mailboxes free level */1 [& F/ r* U7 S  L2 }9 f' r
  35.   return freelevel;
    ! l! m) Q- c  r9 {8 K+ A
  36. }
复制代码
: K% M+ B+ c; X% y* d+ k

解决办法如下:当然你也可以自己封装一下


' w( U( h0 W9 j5 x3 ^) Q

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan); E- ~4 ?  }2 J+ v* b( E( O
  2. {
    : M) s" H! I5 t5 d" w4 X" G
  3.   uint32_t freelevel = 0U;& a) Q8 a' W- z  U* M3 ?+ i
  4.   HAL_CAN_StateTypeDef state = hcan->State;- m" C" K4 w$ E

  5. 0 Q* _5 a# ^3 Y' i
  6.   if ((state == HAL_CAN_STATE_READY) ||
    $ B# E' G( e+ d. J
  7.       (state == HAL_CAN_STATE_LISTENING))
    : e) o! T. C8 ^- S
  8.   {
    , y, `: O7 N- j( b
  9.                
    3 p1 H* r0 R5 [1 E% m% K) K7 R, U
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \
    8 G1 L: m; {( a" b$ J
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \8 l# J2 q' P) b- p9 r2 F# P
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)# A8 f% ^1 X$ j/ f) r: ^
  13.     {% e% E! r2 m7 a7 r9 L
  14.       freelevel++;
    $ Y/ G1 U* a/ V+ |
  15.     }& [" R# a! D2 q5 c5 F/ [- Q
  16. ! o9 }, ^$ Y- R5 z9 ^
  17.     /* Check Tx Mailbox 0 status *// @# l. U) y$ q, J3 T
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    ( |% u7 K1 }/ `  Z
  19. //    {
    7 F7 j  m5 e$ ^( R
  20. //      freelevel++;
    2 T2 w9 B% e5 t. [* }/ ?9 C5 T
  21. //    }, E* n) K* a6 C2 h& C" ^0 I

  22. ) V7 ?2 D: ]0 I, ?6 A$ `& U. O
  23.     /* Check Tx Mailbox 1 status */( f0 V# T+ M/ Z, X, [
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)6 R; O6 V% a, ?7 I0 a+ Y
  25. //    {
    $ u3 u( d1 g6 d4 Y! M6 H% Q
  26. //      freelevel++;& I8 C/ q& M4 P, }  \7 X* j4 u
  27. //    }2 Y1 b3 c; R2 ]* E2 W* a
  28. 7 I5 r) |9 h# g: h7 `# X+ [: e
  29. //    /* Check Tx Mailbox 2 status */! y% {/ s( z& K9 X( {
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    4 o. a5 \* A4 k. Q* L( p$ f, v& _
  31. //    {
    8 B: v3 Z. R2 a
  32. //      freelevel++;
    7 E; |- r! G( y, p5 d
  33. //    }- n. \) t3 ?  Q; x6 R. b
  34.   }
    ' {# `( s& L, N5 h( G' }1 B' ~! ]9 v$ N
  35. + f* Z2 R. ~# v2 H- M" p
  36.   /* Return Tx Mailboxes free level */
    ) \% E7 t$ A% B. A0 l3 x8 l" m
  37.   return freelevel;/ ^- L8 [: `7 Q$ b9 ?. Z& E6 y: X
  38. }
复制代码
, o# P. A. w8 \) D9 x5 Q5 P

4_meitu_42.jpg


& Y, Y" r/ K) T0 t) g+ V三 总结7 D3 e' p6 M* s  o5 P

CAN数据在发送前都会被送到优先级最高且空闲的发送邮箱,所有发送完后 我们不能检测三个邮箱是否有空邮箱,而是应该检测三个邮箱是否都是空的才对。

: o/ v/ ~/ Y+ X% j


7 P# R; M( k- E0 H( z. D

四、CAN以及库函数分析, G$ B% v+ h, |5 v6 H* e% n# _* b  H

CAN总线2 N4 p! j4 t) h+ s; S" b
1、根据标示符(也就是 ID)来决定优先级的。+ E: _) ^& t& v0 p! b! l# N: Q7 g
2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)
! R1 D; N' V6 @: W2 _1 ]* S# @- A. i3、可通过发送“遥控帧” 请求其他单元发送数据。3 l7 F; J% H: f0 }; J& w4 j
4、CAN Model:

) `. i$ T3 w" }' ^; o7 {& G( O
Normal 正常模式6 S. O* d* [' v" Q. S3 \3 Y
Silent 静默模式5 l# N; h8 d6 L
Loopback 环回模式 测试
  G" @3 J1 L0 KSilent_loopback 静默换回模式 测试


6 N; g3 b3 W. N2 E* z5、波特率

' W5 |$ C* f4 E: h3 Y
波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)

2 e8 j% ?1 ~1 u1 P* l4 d

6、发送数据结构体指针

  
  1. /**
    " Y+ y/ R% ]: R5 F- a
  2.   * @brief  CAN Tx message header structure definition3 s1 s9 Z5 H& [5 [' `4 {9 V3 N" b
  3.   */( Q9 O8 }5 f  X4 ~6 d% c7 ?1 Y
  4. typedef struct
    ' T+ j; ^+ ~+ x; d. G( ]$ F0 b7 O
  5. {
    3 {9 C: ]: l9 r. `
  6. //表示标准的ID4 |+ \+ _1 M: _. E( f
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.
    5 ]2 k7 P5 K# ~3 W3 x6 a
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */! L* C5 y/ I: e  |4 U+ G( c
  9. //表示扩展的ID
    + d  ]0 g7 c0 x8 S6 ?
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.3 z0 U" k5 R; i. ~: x, r6 N: c# a
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
    : e# o# n& t9 r! J5 x) g
  12. //要发送的是扩展帧还是标准帧5 z5 V6 v0 |2 D7 @* q" u
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
    * W, \1 }- k+ G0 K* H; m
  14.                           This parameter can be a value of @ref CAN_identifier_type */
    , q* l# ^3 U- z) ]9 C+ J; d* f
  15. //表示发送的帧类型。如:数据帧、远程帧等2 G, Y8 c3 F; U! N  j7 U
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.$ J, V( f& i0 A. |$ O, q
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */
    ' r/ f' l+ N2 ]* ]" |
  18. //表示发送的数据长度
    % f" ?( A& n5 @9 u, Y
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
    ( O2 H) C" R9 W; N- L+ ^) Z
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */9 l  Q9 y4 h7 I+ v+ H4 T
  21. # V# ^7 ?5 _- Z
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
    : i" J6 W% b5 ?5 j0 k0 p/ H5 N- Y
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].3 S9 ~! O( [5 E- L( T9 S) e
  24.                           @note: Time Triggered Communication Mode must be enabled.# n! f& v: T4 I7 c3 u+ `# ^; o' a
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
    : w% E& X% S- a5 e: p( B
  26.                           This parameter can be set to ENABLE or DISABLE. */. O# X7 }- O, W3 T4 k' W, A# H

  27. ' R- M6 \8 _( m" X9 y. Q$ c' y
  28. } CAN_TxHeaderTypeDef;
复制代码

3 `) O% l, I6 T8 U( O* O, N3 t

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器$ }& A& N( M6 T& Y, I: _% a
屏蔽模式8 F/ e: d2 o4 d+ b! ]* [6 G
屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你, {% N8 ?3 Y8 p$ l6 t( E* l
想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。2 L" ?* T0 o% i8 V4 M0 @4 M
屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。


+ M; o: ]: Y- ?8 P+ m" D6 Y+ a6 n


% }5 h3 J, |; }! K

8、过滤器结构体

& R6 o- x, `" `6 {+ x
, P0 A8 g# y' p1 ]4 Z% C
  1. /**
    5 _  J+ e5 `6 N* L0 J1 {, o! f8 `
  2.   * @brief  CAN filter configuration structure definition+ E4 {# u$ u; z* }) Q0 G5 Q
  3.   */
    ( S8 L) [; v5 t9 J
  4. typedef struct
    # [& {' ^4 e& z
  5. {
    ( g. c, |  t( S" x; _; Q
  6.         //这个是标示符寄存器的高 16 位& E+ r- x* a2 F; F$ H- S4 J
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit0 L% h* q& z2 e% e' w3 D
  8.                                        configuration, first one for a 16-bit configuration).
    - B/ q5 n( p% v2 z& {7 Q3 m
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */, _* X" U( |1 A$ n  v0 Z0 |+ m
  10.         //这个是标示符寄存器的低 16 位+ `6 {2 r; m7 F3 G' k; a
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit( Z! }* R7 M2 i2 \8 Z! _2 C
  12.                                        configuration, second one for a 16-bit configuration).
    7 j6 u) ^+ T+ }7 y' V7 ^
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    # K6 z4 G/ t, {) T, c
  14.         //这个是屏蔽寄存器高字节的设置
    3 y$ z8 l7 T1 D, k
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,' n; m4 v+ G; }
  16.                                        according to the mode (MSBs for a 32-bit configuration,
    # S5 V! w) i9 V5 J- y
  17.                                        first one for a 16-bit configuration).0 B' T7 P6 s' p4 s( ]
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */% d* K6 ]6 d8 Q% ~# l+ f/ P& }
  19.         //这个是屏蔽寄存器低字节的设置# Y: d( Z6 l$ o) ?- C9 C
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    " E, U. s8 [8 c; q+ z. v' B9 v. \
  21.                                        according to the mode (LSBs for a 32-bit configuration,
    / w9 `3 f- S) K1 E! t/ Z' j& O
  22.                                        second one for a 16-bit configuration).
    0 T$ b2 r% G8 u+ c( c( d  r8 ?
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */5 r5 `1 L. Q$ l. r
  24.         //选择你要使用的邮箱,它有 0 和 1
    , B# b; x6 D2 X6 s: j
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.* m# |5 a3 w1 e( W4 r" Q  H
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */- f# v, G/ w. n6 E' T1 o
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。
    ! F/ ]$ E* _0 b; H9 y
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.8 r$ J5 a2 Y% ]: J, E# C8 E+ w
  29.                                        For single CAN instance(14 dedicated filter banks),
    5 M* _" S" R2 J2 Z& q4 s  R
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.
    . n+ \3 s, Y& y& l/ b0 m* O
  31.                                        For dual CAN instances(28 filter banks shared),2 C7 e" q5 B5 o! [2 L
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
    % C- K6 F- L4 W
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和7 F6 X# D) s9 s0 {3 _# i+ P" C+ a
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :
    ! q& W# Q; G7 }4 K
  35. //CAN_FilterMode_IdMask。
      _- p3 t. I0 U' n7 M" E
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.
    8 Q9 v8 O% S: G/ i# a
  37.                                        This parameter can be a value of @ref CAN_filter_mode */
    8 @9 P7 n- Q" q0 Z- P8 A+ ~; A
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。
    # U& U8 k5 u! |4 J8 |. m$ G. m& P! X3 G
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.; Q9 b+ w( }# E' S+ p4 K
  40.                                        This parameter can be a value of @ref CAN_filter_scale */# y8 F7 L' e+ d- F7 e
  41. //表示过滤器的使能: g0 o, @9 I4 ?  t. I
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.
    . L' Y) X9 g. z/ N
  43.                                        This parameter can be a value of @ref CAN_filter_activation */
    / m: r) G6 y3 W2 e8 \
  44. 2 q8 f2 C8 c' r# e
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.7 y1 @1 \, z  M1 x  i: u
  46.                                        For single CAN instances, this parameter is meaningless.- B- ?; r& s8 s  J+ t. C
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master
    5 j. L% ^1 f( n
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave9 |: X. v( D4 I8 t& U+ Q+ l! d
  49.                                        CAN instance.( X* g* W+ {' I- Z3 i4 v) {
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
    " X/ k7 H1 r1 V1 G+ l
  51. } CAN_FilterTypeDef;
    ; p; O9 h- |. @- A  o: p# m
复制代码
; W1 Q+ Q. U( N! ^, G- V* J& \
% Z& v7 a) j' r' [  c9 g! ^! X
2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

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