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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?
$ K2 ?) n( v# K2、发送多包数据,网上基本上就两种说发( ^2 a9 Q* B5 U: P  `. o7 }& T
*两个数据之间加延时. H* P3 `3 g* O4 `' r6 y0 w5 D/ X
*查询邮箱是否满了3 R6 f6 `1 h5 F  n8 C
HAL_CAN_GetTxMailboxesFreeLevel()9 I' V% i; x. |& b
对比上面两种方法,为了效率我们选择第二种


2 Y) `& ]! u. \! ^; D# O


8 u8 n9 w# A7 Z* W0 U7 n! o

二、配置与代码: x: v8 E5 q8 T* U

, J! ^  m  O/ R9 G: p

直接上cubemx配置


; J( Z( G; R6 ?/ p  k

) k' H  v# N$ q

1_meitu_39.jpg

( c, S2 U/ v- ~2 ?9 z( k1 O
2_meitu_40.jpg
/ Z- S# l/ C& O: J+ ?/ f0 N# }
) L* X  w6 E6 E5 p1 N1 T$ ?* d
& B6 |1 y# d! `+ Z# t
直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下


0 Z# P- |1 s8 j( Z, ^& w6 i8 u

  1. int main(void)
    " ~; ]; D" ?/ I
  2. {+ p" ^' [  W. `  r
  3.   /* USER CODE BEGIN 1 */; \6 A9 U! r1 e1 d0 g$ z
  4. ; w! |# n  p: A7 j
  5.   /* USER CODE END 1 */
    / ^- o. \+ D6 s5 @& v* N1 c- V

  6. 5 f/ j9 J& D6 E2 P7 E, ^! R/ t
  7.   /* MCU Configuration--------------------------------------------------------*/
    9 W+ \9 I! U+ Q, ?- t# \. G4 ^  [
  8. ( C/ b# E0 W1 V' X$ u
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */6 X) K2 d9 I0 X9 Z1 O& ?$ `9 e6 E
  10.   HAL_Init();. v! K5 u/ M. ]  p  C  B1 V

  11.   c+ I! W2 C( ^9 q7 q9 S4 A' ]3 T
  12.   /* USER CODE BEGIN Init */
    9 _3 V. @$ Z/ G2 F  x' Y+ H3 k  ]( a

  13. 7 t: g; l8 F, z
  14.   /* USER CODE END Init */
    2 p/ H  Q5 M0 ]
  15. & o. b" K4 M) S
  16.   /* Configure the system clock */' r) S# I  H/ y* c3 o2 j8 \
  17.   SystemClock_Config();* O! o$ a8 J- ?! G8 v5 }
  18. 6 x8 e9 u( C3 I- }* @( t: R
  19.   /* USER CODE BEGIN SysInit */6 g+ o" {. ?" D/ W1 X7 J" ]

  20. 5 m5 D: n- W( ?. _! B
  21.   /* USER CODE END SysInit */+ c1 l  f: C7 @- k% L

  22. 2 i4 z# Z! E1 ~; E5 h% E
  23.   /* Initialize all configured peripherals */( ?2 G6 X! U) ^
  24.   MX_GPIO_Init();
    0 w% U- q. u( P/ z
  25.   MX_CAN1_Init();) ]! l; o  h% R  B( E# f' f0 D% o
  26.   /* USER CODE BEGIN 2 */
    % C9 R: ?4 P: v% B2 J
  27.         CAN_Init();9 x, Q, n' n) F" }2 o1 S! Q
  28.   /* USER CODE END 2 */8 S/ t# G3 {3 J# _
  29. " x% K: I" x: @- b. x& O' x; e
  30.   /* Infinite loop */2 g  u/ x: M9 W  x( z/ z1 u
  31.   /* USER CODE BEGIN WHILE */: l4 G3 U: i0 {, u& O  ?
  32.   while (1)6 f) H; r$ s* M3 k+ f
  33.   {
    3 ^2 ]% m; d) P# F1 N6 A
  34.     /* USER CODE END WHILE */
    ' z7 q8 q3 r  v8 q+ Y4 s. W
  35. 4 O$ M9 o  r8 O0 a0 Z# y6 a
  36.     /* USER CODE BEGIN 3 */
    ! c9 d) o  E4 W/ W& H8 N* v
  37.                 uint8_t TxData[100] ;
    . }) n: N& X0 T8 @' V
  38.                 for(uint8_t i=0;i<100;i++)
    / S) b' X: b+ `3 ?9 b
  39.                         TxData[i]=i;
    5 x0 T  c3 i/ H9 t. R; Z
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));
    ) V7 }. x+ Y1 o2 Y3 e6 l: \* E1 T7 y
  41.                 HAL_Delay(100);  B+ M  f$ V# M" k
  42.   }6 @; w/ C9 _/ M( ^+ B: @
  43.   /* USER CODE END 3 */
    3 u) Z$ Y" Z" I+ f& i( L% _6 y
  44. }
复制代码
: b1 `* f- u0 f

bsp_can.c


# L& Q( z) `. i  ~& y  Y
  1. #include "bsp_can.h"' B, w& c$ n$ Y! i1 i3 u! G
  2. ( ?0 v; ?& X0 X
  3. ) Q6 z4 S" J7 M- W! k, C
  4. /// CAN过滤器寄存器位宽类型定义3 n7 S7 J' w7 X% O/ p& I* Q4 h/ ^0 K
  5. typedef union
    . A* T* ?" D# x2 `9 |" g
  6. {
    - A# `; K* w8 V7 ~" L9 ^, F/ T
  7.     __IO uint32_t value;" H' `: [6 A4 D( e8 P( E
  8.     struct
    / W# A8 w, M! I% h) [! }, W
  9.     {) D( Q# W/ }" m8 D  O* d2 s
  10.         uint8_t REV : 1;                        ///< [0]    :未使用  a' @5 x& g/ |! s
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)4 F' d  z7 g4 W8 R9 ?9 P4 G" Z2 X# m
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)1 ?& \2 V5 u7 X# y6 ^0 i
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID: J& ~6 d" u. B% N
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID1 e( A  X+ f5 p  }1 U" a0 \: @1 s
  15.     } Sub;
    ! D' Q( ?* o" V! ?/ A# B) ]9 E
  16. } CAN_FilterRegTypeDef;7 @* P" t' Q& S" m

  17. " F6 o( q) F+ k# ~* i2 I
  18. / o7 k$ C0 @4 ]* K+ b% y1 ?5 Z
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF
    * f: J3 z. L3 E; K. W$ f

  20. 9 d& {! l$ P7 y2 X
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式
    6 O, a1 b# ^; U

  22. , y% B. U4 y/ Y# |5 l
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID; }) I5 ?; Y/ \* ?1 v* M. ^" ?
  24. . F- ]' m) M6 _! B& u; b  }/ Q
  25. void CAN_Filter_Config(void)
    ( [! X  C  [$ u9 z/ G
  26. {
    : o  h, p* y0 A, Z( r
  27.     CAN_FilterTypeDef sFilterConfig;
    . F5 W0 B: J) M
  28.     CAN_FilterRegTypeDef IDH = {0};* _) P& z% Q% S5 \
  29.     CAN_FilterRegTypeDef IDL = {0};# C6 U( K% _0 Q7 i4 z$ N

  30. 3 |4 B( U( {" g' H5 e  z0 v: v1 ]
  31. #if CAN_ID_TYPE_STD_ENABLE
    + j7 \5 F: X1 P. i3 T/ j  |& q
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位1 H6 `* A( a7 Z5 [: J* C1 C
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位9 ^' T! l$ B+ }
  34. #else
    , J# I# z+ v6 p: T+ r" T
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
    + t! F9 H3 N/ h' l
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位
    6 e- h# G( z) k- y% s
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位# [& u& ]! ^+ m% V
  38. #endif
    : [& c) S' M3 V" `+ q# F
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号
    ( B! l( X: F- \, A
  40. #if CAN_FILTER_MODE_MASK_ENABLE8 V  J  P$ \4 Y0 o8 i
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式
    # x' k; w% W" H! @7 z) s
  42. #else
    % j' T. T% k% _9 g* N
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式( L$ W0 G6 D+ o' x* m* i
  44. #endif
    ! O+ H* d. r( [
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽
    , N1 ]2 N, B! E0 ^1 w
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位& i+ O* J" G6 D* i2 R
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位5 ]) r0 G7 h+ e; e$ v/ V
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    3 O% `5 Y3 }6 `' F3 f, \  e
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    : p2 j0 l8 X- P) b1 q! h# c
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO02 t& @5 ~, F1 a
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器
    5 R5 M# e: M' A" \
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效
    ( N8 f% i0 L1 O% g3 l
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    7 }- D& s* a0 b' k5 W% _& V
  54.     {# e7 G2 F- z! I! G
  55.         Error_Handler();
      Y: K( y! q* N; T- N# L
  56.     }
    0 e" D6 e: \& F
  57. }2 r7 W4 _+ J8 F/ C
  58. 7 P3 q7 N+ t* b, X
  59. 8 Y: Y8 G- M7 O  i' ?) k) l

  60.   r0 U# [6 I" u$ K( p3 K: a' Z
  61. void CAN_Init(void)6 R# }/ e; j) g) Q2 }) C
  62. {3 N0 T; O, S1 `
  63.     CAN_Filter_Config();
    0 L- j5 W- ^( K9 t( k& d2 _
  64.     HAL_CAN_Start(&hcan1);
    1 Y) v. Q- o1 t
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断- T3 M6 J: [9 A0 k
  66. }
    5 u0 e  K& R2 Y
  67. - h+ }7 w3 S( F! W: m
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)
    . Z2 b% K! J  Z+ [* v
  69. {
    # m, z2 U" x* H( h5 x! t
  70.         static CAN_RxPacketTypeDef packet;7 y5 Q7 u! ~- l, K' D# p, U* K( M
  71.         . u, c% G) b: {' E" H# e
  72.     // CAN数据接收1 L6 R' r, ^5 S8 w7 [3 i
  73.     if (canHandle->Instance == hcan1.Instance)# g' Z" ]6 B. L% L2 P' K: F5 R8 U
  74.     {
    . ~# `% Y; M$ T' ?. h
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    1 M: f1 M5 g- z! q/ u; i0 l' o
  76.         {  h% V. `1 \# F- ~; u
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");; v* m" T& V. Q$ n" s+ [5 I6 r7 o
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);+ L7 K' T. [5 v, [
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    - g" V1 V, w) d  u3 L
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);4 M0 L. }/ E# C: i' R
  81. //                        printf("DATA:");
    / M, U/ L0 x" t. @
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)
    & O: O/ w5 w/ |: b3 s2 h+ d
  83. //                        {
    * ]" R3 I1 m! t8 P* @# R
  84. //                                printf("0x%02X ", packet.payload[i]);
    % i* r0 O' n: I
  85. //                        }
    ; i% x# H% |+ R( o: v
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断8 @1 f0 b% k; N; j9 r5 H% ]
  87.         }
    5 f; B7 W4 `" k; w( p) H& P4 B. Q2 o
  88.     }
    * v0 l! _+ e6 F- R5 `: |+ S4 \7 M, ?
  89. }# r9 H3 h' ]! z& R! e

  90. - S1 y. h0 a0 Z) S  ]
  91. , w' a5 S! F2 V7 }# s: B& Q
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    - E. r! U( E& J( ?
  93. {2 m9 x3 t9 w" G6 m
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
    , q: _5 N/ j0 X8 ~& A4 _1 I$ a
  95.                 return 1;
    " A$ f6 Z' F+ Z' N
  96.         return 0;
    " d- @% H% |4 X; Q( w' @! H' v% h
  97. }: z- [4 t  t, X+ \; V0 e

  98. / D6 u0 w( D6 p; M* N! a* [
  99. % Z" n* D- S+ a. `. {- M
  100. CAN_TxHeaderTypeDef TxMeg;% @% V4 r9 |! h5 A2 V
  101. uint16_t TimsRepeat;
    0 a9 T2 M5 c, I6 r' C  i/ d8 T1 n- B
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)
    * p+ T3 W/ f+ W$ u
  103. {5 e) _, _" J. O3 {- \# {( l
  104.         uint16_t SendCNT=0;/ q8 R" F% f& b9 T/ s0 l( H- {; E
  105.         uint32_t TxMailbox;
    , i* W; h- ~. x# D% Q
  106.         HAL_StatusTypeDef        HAL_RetVal;
    1 Z0 K* N7 o5 R, s# I5 }! V' {
  107.        
    0 J, j) o3 T) D6 n; r+ z
  108.         TxMeg.StdId = 0x321; //标准ID
    9 J  b, ~. C9 G( b( u$ V6 @
  109. //        TxMeg.ExtId = 0x10F01234;
    ( A) |$ E5 c( }( ?0 K9 h
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型4 I: ?3 s$ Z( \7 ^, N+ H/ c
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型( }+ L+ a4 F0 {! A
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧
    " s) o8 }8 d+ d
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧
    + C7 K3 k  h1 H1 Y% k
  114.         TxMeg.TransmitGlobalTime = DISABLE;/ |; t- Z$ v; o3 a6 v
  115.        
    # v- v0 W% m; ^. r; W
  116.         if(!__hcan || ! pData ||!Len) return 1;
    ) ^) s! ?# o7 z( n
  117. ; y+ z. t) J' E$ m' U
  118.         TimsRepeat =Len/8+(Len%8?1:0);
    # v5 ?; J) ?" v- i9 R
  119.         while(TimsRepeat--)) F+ V2 n: c$ V) z# S
  120.         {
    ' s: r! O0 r) C3 m/ j
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);
    * R( w5 f2 F8 o. L
  122.                 if(TimsRepeat>0)
    7 ~1 {5 p" P, L
  123.                 {       
    4 P( z9 G5 l- A5 ?" N
  124.                         TxMeg.DLC=8;% U* c3 z8 [4 X: _( N" |
  125.                 }  [4 f& k: S& z, Y6 ?
  126.                 else, s7 h0 b1 p5 Z4 Y
  127.                 {9 \$ l# z2 T) p1 S/ z- a
  128.                         if(Len%8)
    , G; l0 E! ^; m0 D) e6 z
  129.                         TxMeg.DLC=Len%8;8 s, [7 Q. V8 D' j$ G
  130.                 }
    + l- G. U4 |+ d5 r3 T" @; c
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  
    4 ^7 g, Y* U8 X1 |# C1 @/ b/ y$ r  k5 ?
  132.                 if(HAL_RetVal!=HAL_OK)8 @+ `7 E- i0 @& T
  133.                 {/ ^/ U* N0 S% e. ]1 B
  134.                         return 0;
    # ]8 j+ E; I5 m: {+ C
  135.                 }8 f9 u8 Z& d5 C7 ~, t' O  S
  136.                 SendCNT+=8;
    4 G; c7 F* e7 A
  137.         }
    # B' u" T8 ~$ Q8 F* t
  138.         return 1;
复制代码

' `2 b" t! i8 ^' ]5 d4 ^: u  m* t6 x1 V8 S" r6 {  ^3 U

bsp_can.h


, ?5 t0 R. B( W1 e6 S. B3 M, U

  1. #ifndef _BSP_CAN_H0 }0 M. N4 E) w# O7 p8 d
  2. #define _BSP_CAN_H
    6 |2 M6 H: l( e5 O1 @' c& j4 U
  3. #include "stm32f4xx_hal.h": t% f# u8 B9 c! R: A2 h
  4. #include "can.h"  ?. S( x( [) V7 _7 N
  5.   e7 [6 G: P9 Y6 F6 Q- A- Y
  6. //typedef struct+ Z8 p  ^% [3 T* r( d
  7. //{
    4 J+ ~* J" W2 e3 _& a
  8. //        uint32_t mailbox;# X: j7 f( H* E+ _6 ^- N, N; l  b/ p
  9. //        CAN_TxHeaderTypeDef hdr;
    & `! H3 F  B: `7 K: m9 C- `
  10. //        uint8_t payload[8];
    * i$ R' W0 c" e: K
  11. //}CAN_TxPacketTypeDef;( d5 G+ G! X6 {& f; w+ A( j: Q' ]2 u

  12. 1 \6 E* Z3 e- ]! N1 G
  13. typedef struct3 F( t, B- D' D; w- W! S
  14. {2 u% V* n7 T- P! L% e
  15.         CAN_RxHeaderTypeDef hdr;9 r/ ^  y" q" P* [2 S& s
  16.         uint8_t payload[8];
    2 g& ?; E% \$ c3 E0 ~
  17. }CAN_RxPacketTypeDef;
      H$ h% v; T4 N+ \0 ^- b
  18. - W# K0 r  B1 K+ o3 f' b# `
  19. 9 t9 V; f4 L( ^' s5 T
  20. void CAN_Init(void);
    4 a3 G9 t& L- `; U
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);
    % v7 Q3 ~& i/ X
  22. #endif
复制代码
4 b* V) F! c; j( A/ g

就可以工作了???非也4 o7 l( g9 ~* q. L
其实我发现还是有问题


; l$ I4 y. Z: z! c4 ]

3_meitu_41.jpg
/ B8 Q8 ]% W, g  H9 R9 p1 Z7 y) v' Z
  w+ |7 W( z) a0 f( M7 W

) Z, \7 a; q% N& N: _
为什么第2 3包数据到最后去了?

  z& B; o; X0 S& U

查了一些资料发现了问题:
$ }. q1 `- y' L9 K) H( Q7 s”发送邮箱“是用于CAN总线数据发送的,总共有3个,并且存在优先级关系。优先级越高表示其里面的数据会被优先发送。数据在发送前都会被送到优先级最高且空闲的发送邮箱,然后依次发送。最后说明一点:“发送邮箱有3个,且每个邮箱只能装一个报文”

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

8 @/ U* X  [) f( U% w8 U" u

查看库函数$ e7 E' B, z+ L2 f


( A3 a' `" c! y: v, _

  1. /**
      U% Y" l9 L0 n: W
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    / V; f. x1 _& t. W" K; J, s
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains5 Y+ ?# s! J' ~0 k: s
  4.   *         the configuration information for the specified CAN.# V: b' y4 a, W: S
  5.   * @retval Number of free Tx Mailboxes.& b/ I0 Q9 M. o0 b% V
  6.   */
    * `$ N! i- s- n( C, T* a# G* u
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)$ A' M( p# y  g( W' n" Q
  8. {
    - V' x% s, j( J( R9 |5 w: ?
  9.   uint32_t freelevel = 0U;
    2 }% \3 ~2 i# K2 X
  10.   HAL_CAN_StateTypeDef state = hcan->State;
    0 E7 x+ f% g: e. u& d9 r

  11. " v  R6 o6 C% W+ c+ A8 ^' Q
  12.   if ((state == HAL_CAN_STATE_READY) ||
    8 _& G- z" d& g
  13.       (state == HAL_CAN_STATE_LISTENING))7 q6 ?3 n  a- d
  14.   {
    9 n7 l  c5 C) H& w1 F. f
  15.     /* Check Tx Mailbox 0 status */' p# `& C! P+ y$ n; f8 Q8 i6 S) d
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)% j" {( ?* S0 ^) t# Y
  17.     {$ M  A4 D, v! s% ?# A: M: A& C# P
  18.       freelevel++;$ O: i6 N0 y. m6 y; [! @' w; M9 e3 ?0 k
  19.     }7 r$ \0 G& P7 p3 v
  20. : R5 P6 a8 f) M% z& f* ]) A
  21.     /* Check Tx Mailbox 1 status */
    1 v% X% P1 o9 i. ]& W  K% [
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U): Y. j% E2 y% \/ @! |
  23.     {) S% _/ D) [5 J$ y
  24.       freelevel++;
    0 Y9 w% g+ e* q. R+ [
  25.     }
    / V! t! t# w% p5 ]6 F. T/ h

  26. 7 E3 a& q- N# a% \; V5 F
  27.     /* Check Tx Mailbox 2 status */1 H6 `8 p" q2 W$ p0 k; ]) j1 V
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    9 b, v2 v% Y& ~' ~% w% F- v# y8 l
  29.     {
    / W7 F) @8 ^* C( d; }3 w6 d, K& o
  30.       freelevel++;8 D% D" \5 o% k) w9 V
  31.     }
    * T& o8 X, b- y! D
  32.   }
    % ~' H: b0 T* Q1 B* g+ Q

  33. / J) j8 Q0 n; @; O( L3 U
  34.   /* Return Tx Mailboxes free level */- z# R$ a3 m) u+ y3 M- Q  u$ d7 J& A+ c
  35.   return freelevel;* N( I/ [2 z4 F% M2 \. u
  36. }
复制代码

' \- V5 S) t% r. p2 {( ^. S

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


  R8 F, p+ ^1 {$ w" ^8 k1 K: ~+ `- @

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    9 p' D6 F) W) F" ?9 H
  2. {, r1 N) ]$ G6 E' o* w& z
  3.   uint32_t freelevel = 0U;5 V* \. }' W" b5 A1 g6 }
  4.   HAL_CAN_StateTypeDef state = hcan->State;
    - T7 H- [4 ]1 T. d, t

  5. ( w5 a3 d! C& r7 ]3 Q+ M
  6.   if ((state == HAL_CAN_STATE_READY) ||. V  ?# ~. n0 ?: `; ]  Z8 Q
  7.       (state == HAL_CAN_STATE_LISTENING))
    6 b8 W* ?/ C$ T) s: a4 o
  8.   {
      H1 i, V( x' T3 G& Z: j
  9.                
    5 S: t. a' f# t2 L5 j+ Q1 b1 r
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \+ t) l$ s7 d/ V$ j: c
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \% ]6 H& s7 G. ]/ ~. B; A  I* q- D
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)2 R" u( S1 _4 H' K
  13.     {# l) C1 }2 _5 n+ ~( o0 U) G% J
  14.       freelevel++;. i' J- c$ `8 d  V% g9 A; j8 H
  15.     }
    2 X( v2 p) O' e3 e! j: \

  16. - @0 ~# A, A0 }2 N/ U
  17.     /* Check Tx Mailbox 0 status */
    & Z9 f- S7 v. ]
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    3 A4 v$ _# T' Y0 R' k& H
  19. //    {
    6 c' a, K9 _( E6 N
  20. //      freelevel++;* r# \9 e4 m& H8 b% m" r: j  A' h
  21. //    }
    ' F  X8 O4 u/ E* m
  22. ) |+ @# O  |, O
  23.     /* Check Tx Mailbox 1 status */
    4 h+ z5 c. _% w
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    * G9 V! u* H) H" N) n* z
  25. //    {2 a! d' o4 q9 g1 T0 M$ q# S$ R
  26. //      freelevel++;; J- c5 c2 t, y2 e
  27. //    }" |/ {6 j+ v$ W; W8 l
  28. 4 M' M9 T/ i8 @# L# M' W" K
  29. //    /* Check Tx Mailbox 2 status */9 ]8 Y5 V7 F1 @7 m+ P$ J" n
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    - o+ c  J0 D, N
  31. //    {
    3 W8 H+ g' t2 V* r. Y8 L
  32. //      freelevel++;9 s/ R2 G* O. k/ v& n, K' h1 o0 w! \
  33. //    }; V1 l: q5 X  G- Z1 Y3 H& G9 [
  34.   }
      L4 A" y" e. \1 A) a: j

  35. 9 E; D! \, |0 j! W9 w
  36.   /* Return Tx Mailboxes free level */" L7 N$ C$ S& S6 S
  37.   return freelevel;2 e( m/ {9 z% {8 i8 ]% H! u, L
  38. }
复制代码
, f* e7 K4 F9 k; X, z

4_meitu_42.jpg

3 v  e! a2 A3 N, S$ S
三 总结
% C0 _# `5 `9 {. U

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

0 j" F, c* ?% ~1 n


- k! p1 {* Z& @, p9 c( i. W% n1 y

四、CAN以及库函数分析7 C) z1 r; Y2 k( F

CAN总线) H; u% E2 h, @
1、根据标示符(也就是 ID)来决定优先级的。9 C7 \$ Q  X; w7 d; l3 w  `" f
2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)# }+ F6 ?; O, s, i( F- L, I
3、可通过发送“遥控帧” 请求其他单元发送数据。3 m" B- ~/ K9 ~/ l% `/ W. J
4、CAN Model:


, A; ~& [# W) B1 J! wNormal 正常模式2 l1 R3 q/ a- b$ p
Silent 静默模式
; P7 _+ Y' w: s) \: {7 ^7 sLoopback 环回模式 测试+ c2 _0 E& D% h- S( ^0 v( k
Silent_loopback 静默换回模式 测试

0 h, G# K. N7 \) v8 z) }7 ?
5、波特率


4 J. L0 e' d8 Y2 P! v& }波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)

4 J" l0 z: L& o8 G+ ^

6、发送数据结构体指针

  
  1. /**' z/ X8 z( n" a# h
  2.   * @brief  CAN Tx message header structure definition
    - |" Q  F# U- Y, k' s
  3.   */1 p1 p. ^" m2 [
  4. typedef struct
    * ^3 l! o: U3 u3 T4 I3 W
  5. {* N  Z5 o8 I0 z8 O* K. N5 R# X
  6. //表示标准的ID6 T. T" O- t0 ]( T4 h' D
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.+ C7 s7 ^5 A& P8 |" o4 O% P) z
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */- F" R7 K; w% w; o- v, E6 X
  9. //表示扩展的ID( d; {* n4 C5 {& k
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier." h3 r; s0 o7 R3 v) Q6 e4 m
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */# F' z) ~5 i4 k& I
  12. //要发送的是扩展帧还是标准帧
    ) D  P/ ~% e! B* W! I. V/ k( {3 j
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.: }5 }: ^% F$ ]; N3 E# [; a' w
  14.                           This parameter can be a value of @ref CAN_identifier_type */
    ' A6 i9 q# n2 b9 N: Q% Y
  15. //表示发送的帧类型。如:数据帧、远程帧等9 s0 g* t- E9 S
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.; k* s* j' |4 `; P/ v/ A# F/ m. M
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */
    : E+ V) f/ v% w" ?
  18. //表示发送的数据长度( x- Y: S3 m& J/ ]. h8 M
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.! J3 r+ f9 x4 F; J
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
    & }/ V7 }" V/ a
  21. 2 Z$ C: c% k" k+ b% B2 f5 ]  J) c
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
    8 k- \8 O2 m, Q
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].( a! ~# L2 ?9 b# v" Y
  24.                           @note: Time Triggered Communication Mode must be enabled.
    0 x, d! O; ?) ^6 _2 Y
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.3 P6 S  Q+ h( T/ B" W
  26.                           This parameter can be set to ENABLE or DISABLE. */* X! n' g* b; U0 B6 ?

  27. 9 P3 d, z8 E4 T0 R
  28. } CAN_TxHeaderTypeDef;
复制代码
% R6 a5 u/ ?; a& n4 f1 M7 ^

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器
( e6 Z$ p' k0 B: ^$ d& k: U屏蔽模式
( b  o# |$ q: h4 _屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你, [* k! R; X" x1 O' `1 Q6 |
想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。6 C7 @1 @8 C6 G/ @
屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。


; `5 o  j9 H* N) G, h, u& }  d0 N

$ C+ m0 z* k/ }) E

8、过滤器结构体

4 L1 b2 g, C# F

. {* K$ l+ m- C
  1. /**
    & K: h5 M3 v/ I& e0 t
  2.   * @brief  CAN filter configuration structure definition
    " W- ?5 m: e+ F9 F
  3.   */2 K! P5 _6 y5 R/ O- c
  4. typedef struct
    & W5 g+ t% `! g- a7 F
  5. {
    ! u8 n$ l% G1 c
  6.         //这个是标示符寄存器的高 16 位
    & ?2 h! ]% B% s$ a" T. {
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit1 L& \$ ?, R/ O3 z7 R) A
  8.                                        configuration, first one for a 16-bit configuration).
    2 T2 ]' i. G2 P4 l8 I. K
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. *// M. T2 `" F+ \6 G  _4 m5 q/ w
  10.         //这个是标示符寄存器的低 16 位
    - h: K& m" _5 i, Y% p; [) j
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit  @5 l/ Z3 _2 ~6 k6 Y
  12.                                        configuration, second one for a 16-bit configuration).6 J5 U0 V2 L% N/ h$ l
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */) L3 y0 J/ [& R3 `, a1 U
  14.         //这个是屏蔽寄存器高字节的设置
    4 F! a& N; v: h- H. `' h
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,
    ! t; A4 G; o: ^4 d+ K
  16.                                        according to the mode (MSBs for a 32-bit configuration,
      i' X* \+ T+ o% \0 u0 y
  17.                                        first one for a 16-bit configuration)." W+ g0 L4 r- O
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    - Y) f, l4 I, T' r4 ?# s7 }; Y/ \
  19.         //这个是屏蔽寄存器低字节的设置8 o* [/ Q& W) C" H/ x# s$ f2 n) K
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,% M( N" r' ~9 ~
  21.                                        according to the mode (LSBs for a 32-bit configuration,% A( J4 m. \1 S; n& {
  22.                                        second one for a 16-bit configuration)." I% W  J/ f& X/ }! G/ U: G
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    0 @- R9 C. ?3 ?
  24.         //选择你要使用的邮箱,它有 0 和 1( W: G3 `7 t9 o# L6 P
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
    + F8 {3 B" \$ Q) X# D
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */- A/ N) N& e  k: J! i3 x4 G
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。
    3 x, T: ~/ b4 V1 f
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.
    * [9 q% I% ^  ^: J; G* `
  29.                                        For single CAN instance(14 dedicated filter banks),
    ; E8 g8 T2 r8 u6 D
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.% b$ w; W8 L) `8 ^. ]8 r& r: B
  31.                                        For dual CAN instances(28 filter banks shared),
    * p+ u' m  a; G9 K
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */% M4 m7 t6 q3 q* r  a- c
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和7 T% Q, h0 S7 Q
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :% x. ^* E+ @; n. P' X) {; V/ d9 J
  35. //CAN_FilterMode_IdMask。
    5 m* i* S( ~( t- G
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.1 t4 ~) H9 s# U- `2 b3 m
  37.                                        This parameter can be a value of @ref CAN_filter_mode */" O9 y, e- Z" H  V
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。3 N/ x9 K9 L5 t; v! W' ?
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.
    / j) L6 G1 E8 m
  40.                                        This parameter can be a value of @ref CAN_filter_scale */
    : v- I6 _4 S/ H9 t5 c% Y- I% U
  41. //表示过滤器的使能
    9 @$ m& Y4 H* P% Z% F8 [9 Y5 d
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.
    : Q, r! m0 a  Q7 M. x
  43.                                        This parameter can be a value of @ref CAN_filter_activation */
    ! q# o* q2 W8 c0 M

  44. * _/ d. S$ A) u  V1 a
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
    # z8 F; T/ u  E
  46.                                        For single CAN instances, this parameter is meaningless.
    : d3 q+ M# n: z2 y" V# `
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master
      r8 t  J% `& d+ B/ F  N+ L$ _
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave7 ~$ O. Z, S- ~; M& t9 \
  49.                                        CAN instance.
    # g! H. ]' J0 c* d  U6 M* m6 Z
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */2 e- [! c' E! A) W5 F2 q
  51. } CAN_FilterTypeDef;
    - a- n. \2 }  ?$ `. a+ i3 k
复制代码
* }* r8 x7 Q- G" a

4 S7 Q" j7 |  T! \* q% K
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 手机版