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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?7 P' W+ H  v* h7 t
2、发送多包数据,网上基本上就两种说发! C3 _2 a* k1 I3 `
*两个数据之间加延时: b7 F: l, B8 d" m4 m" a& i' ~2 Z
*查询邮箱是否满了
$ M6 A5 w2 e: C8 ~% H5 jHAL_CAN_GetTxMailboxesFreeLevel()
2 N3 s0 j6 i- @, X6 J: x0 o# g" Y对比上面两种方法,为了效率我们选择第二种

3 R3 s6 g  i' u5 @

" N6 H4 R2 P- W& K

二、配置与代码
1 E% V# R- P6 N7 t9 x) b3 t6 n- Y* H& Z0 o* x; n

直接上cubemx配置


" I/ b4 n! F# `- [" e


( ~7 Q+ U* L- q5 o! N( [+ ~

1_meitu_39.jpg

$ W5 B7 h, `# [# l5 G4 n) n
2_meitu_40.jpg
$ O8 J$ w  J! Q8 {) b" i' D

! D6 T! [1 U% b
4 g$ z; N& C( A+ ^直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下

  w5 f( m9 I9 a0 r+ ], I% M2 c

  1. int main(void)
    5 c# u+ ?7 i. S- k
  2. {* s) P& e( d+ l0 ?) a0 X& D
  3.   /* USER CODE BEGIN 1 */
    & ~8 G4 a' P( k% @, f/ r
  4. ; N! J+ k5 o( Q" g! o3 v+ J1 }& U2 _
  5.   /* USER CODE END 1 */
    ! N9 y4 `+ q0 \1 x9 I6 I6 Q/ j( K+ v
  6. ) p5 z# M" ]: R* g+ i) s/ `' I! e9 }
  7.   /* MCU Configuration--------------------------------------------------------*/
    ; ]' L4 v. o$ G3 g

  8. & [" r. U7 E3 }( M9 q/ Z/ y2 j# c
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */, _6 l; N. p/ a- w
  10.   HAL_Init();
    # [" n% `& e: w) k7 D5 L- I
  11. $ \! l* `9 t4 Q: Q2 s
  12.   /* USER CODE BEGIN Init */
    % k; P2 W+ }7 C3 A6 q, k
  13. 7 h5 e: l6 k1 |: l, ~2 f6 G
  14.   /* USER CODE END Init */% z, h* r8 C0 B9 P6 q, F" G) b/ Q
  15. - F+ B5 B8 l1 ^  D* n3 w
  16.   /* Configure the system clock */
    ( d1 U. F0 P7 y
  17.   SystemClock_Config();
    ( w0 t- p5 B6 \7 S& L
  18. * A% l2 w/ Q, k) n/ q
  19.   /* USER CODE BEGIN SysInit */
    5 r% R& B3 @$ Q2 _, W) ~% F

  20. 8 w4 ^/ S6 L* o$ F. O
  21.   /* USER CODE END SysInit */
    " o7 M5 S5 h; S4 ]8 C! S& g( e
  22. " i: F# R+ x' V
  23.   /* Initialize all configured peripherals */
    ' D# A* p# j2 k/ _& N, Z; V) ~' J
  24.   MX_GPIO_Init();
    * `% j+ v9 B% v
  25.   MX_CAN1_Init();
    4 _8 a, `+ c( S- I
  26.   /* USER CODE BEGIN 2 */
    8 T8 V: `7 e4 L) J3 y- D" }
  27.         CAN_Init();
    ) u/ R' q7 W8 ?- e. k$ Y7 ^9 J
  28.   /* USER CODE END 2 */" Z  ?1 }8 ^; N6 C
  29. & E9 v5 k; l' j* ~' l9 s! U8 m* y
  30.   /* Infinite loop */
    # k; L3 z4 Z% O3 Z* @% `
  31.   /* USER CODE BEGIN WHILE */
    0 m9 I' m" Q- J+ l% {5 A2 d: c9 L8 |
  32.   while (1)
    9 C7 F# \# I9 Q9 ]  ]& W
  33.   {$ L! P- _! e) r* n1 W8 _& j) @
  34.     /* USER CODE END WHILE */$ Z6 w! z8 [# ~' m. D% P0 ?
  35. 5 t7 E$ g0 q, F
  36.     /* USER CODE BEGIN 3 */. ^3 U: z# M6 A: a) K
  37.                 uint8_t TxData[100] ;
    , s8 \; C- a; F6 V9 d) C2 e
  38.                 for(uint8_t i=0;i<100;i++)
    2 Y; t1 I, m. V4 W
  39.                         TxData[i]=i;
    % i$ V) v2 o& s
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));- U& |# `6 M4 \3 l  f$ k9 e4 _
  41.                 HAL_Delay(100);
    : r- ^/ h5 L0 Z
  42.   }
      M5 M3 `1 {  h# \* m
  43.   /* USER CODE END 3 */
    - A& Z' t, w8 \- [! H8 F3 D
  44. }
复制代码
3 o* {$ v# L9 ?8 p- S6 a

bsp_can.c


6 p# L% V  t$ V% z7 q# b& ]
  1. #include "bsp_can.h"4 R0 K: n2 T1 [

  2.   x4 L7 W7 I8 s$ j& b, [

  3. # u2 Z. t( G' z& \7 J; C
  4. /// CAN过滤器寄存器位宽类型定义  r, A0 M/ }2 H- _; ]7 e/ s
  5. typedef union' U% n' D# m6 a7 Y( P/ [0 ~; O6 [
  6. {
    , y; W+ Y4 N. e. }
  7.     __IO uint32_t value;
      r7 L9 V6 j% G0 m* I
  8.     struct/ n1 V& n" x& J
  9.     {
    ) c( }3 l6 p' _# G  n
  10.         uint8_t REV : 1;                        ///< [0]    :未使用* T& q( [! u, b2 ?3 K& F
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)9 Q/ u' q) R6 c1 }' B
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    9 S: M' L& g* W) L$ {* r
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
    8 R/ {6 n6 C7 t: I9 {
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID  {5 s# }, I8 `4 t5 H2 p; q
  15.     } Sub;
    ! ^3 x, s8 k! F1 {1 ~
  16. } CAN_FilterRegTypeDef;
    ( ]2 W, h5 {0 v5 g
  17. 3 h  _, `5 k8 Q$ U- A1 _: R
  18. ! V9 e% t( |0 y; L# H
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF
    " t* e! q* I+ l; f6 z" L
  20. 9 x, m2 Q3 u$ K2 ~( {
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式. E- j3 q0 H2 B6 x, n! a8 R1 X# l
  22. + @7 I* b0 I: e$ c! V; t- z
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID
    ! _3 m2 I4 C% n' F. o
  24. 3 W" F+ _2 I1 r) K9 v- g
  25. void CAN_Filter_Config(void)
    & u  F/ C- I5 n3 ~. f
  26. {7 X# h* l% \$ i. a9 h4 ^
  27.     CAN_FilterTypeDef sFilterConfig;8 }" c: a+ |) K! I( |8 g# f8 k
  28.     CAN_FilterRegTypeDef IDH = {0};4 F0 `  k. {' y
  29.     CAN_FilterRegTypeDef IDL = {0};
    . y8 ~: d9 l+ [* q, N

  30. ! M- y6 y) o0 e) Q& q2 b, s
  31. #if CAN_ID_TYPE_STD_ENABLE9 Z, A  W! }2 a5 t2 d+ D# W
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
      \4 w) a1 e, x& L/ w$ X5 A
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位, @; o) \/ b3 |: |- W
  34. #else
    5 A. w$ K5 r. }4 F$ I# p4 i8 a
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
    4 Y" q8 @. |. `$ U- y+ O5 b+ I  d4 w
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位
    ! w# A! b& D+ d6 e! ^3 H# O
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
    5 W! B' r2 s2 F; N+ ?" E' U
  38. #endif
    , v/ [: `& ]8 s' Y* J+ E$ c
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号, J5 E9 @8 e, E3 {$ N, i
  40. #if CAN_FILTER_MODE_MASK_ENABLE+ o# V! W2 T* f0 E( F% O
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式/ [) a7 j2 x9 [# J. ^
  42. #else
    4 ^& z* B5 k% F, v1 m
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    7 j4 \8 E# l! [
  44. #endif2 t1 [+ N0 ]4 x$ U$ M! k7 o7 y8 Q
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽
    9 @' q8 l: D, v! Y
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    ( I1 ]& f( d0 m1 l  d6 n% w4 V
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位* C3 P& h- E9 [9 ^% k% c- x- h; a
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    1 h; w* x5 Z* l( b! p+ p
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位+ ?; L+ J& I5 c0 n
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO08 `2 t3 a+ Y; R0 `
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器" k2 R. J# y, r8 |# L; z3 |
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效# o1 w: D6 q, y0 R
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)* j% }. \1 n) t, v3 l% B- |/ t+ q
  54.     {
    % {& O( Q0 u, t7 {
  55.         Error_Handler();0 O! K& E0 u, ?) J& ?; o" {
  56.     }9 X( }  X! g* q) L$ @" M
  57. }2 N  K( _1 b! |/ K/ T6 T7 ?7 a& z' X+ i
  58. : _! j5 q# H6 I1 k: K. d

  59. + \# w- m6 P' ?: s$ G8 K
  60. ! W: |; i8 q! v/ x
  61. void CAN_Init(void)2 K# G+ O5 K5 v3 T2 @, i
  62. {
    4 E1 a3 x7 N# z- K
  63.     CAN_Filter_Config();
    * y4 \8 ^- |& q$ Z& Q( T, T: N
  64.     HAL_CAN_Start(&hcan1);% p5 }/ [$ a! `
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断, t% C3 i9 u, c$ `) U
  66. }. Q& o6 I2 {& ?

  67. - W- X9 Q4 }  |1 v+ d+ M
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle), K" K3 G( X" @$ _4 }
  69. {) y/ |: U& G- }4 W( \* G2 Q7 K
  70.         static CAN_RxPacketTypeDef packet;: V& Q# q) [  d# S
  71.         + Q6 R6 S0 @* _" A5 s$ e! u% J
  72.     // CAN数据接收
    9 B- Z; a1 P1 V
  73.     if (canHandle->Instance == hcan1.Instance)% f0 A# \; I( b) o9 X" F+ v
  74.     {
    8 i' }  `" S& U7 r. A
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    / v5 a0 Q* M; Y, _* y
  76.         {
    ) _3 b2 {9 F. s( c7 a7 p4 x
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");  _2 X% K+ c4 M7 o. i% B' V/ A5 \7 |
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);- z/ z) d  u: M1 K% P8 P
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);* a: T9 L  k' C( G( _/ R- P# m
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);
    5 ?- M4 h# Z, Z) D
  81. //                        printf("DATA:");
    % m+ P8 [6 `5 A# D; P
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)
    ! s! [: |* Z" R7 z
  83. //                        {# u( o- [. C# Y% {& M! U7 B
  84. //                                printf("0x%02X ", packet.payload[i]);
    3 K- @$ W9 o2 i, S5 w
  85. //                        }- Y! l8 i* q- e' \
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断
    2 x, Q) a' W! U! f" K- b
  87.         }* |; J7 L: e  q3 n4 d' u( e
  88.     }7 C. V1 L8 g, q
  89. }: e6 M" m: k/ Z: v# K
  90. , r! T( D1 X# e6 q- u8 `! q
  91. 8 X1 c0 Q* N5 J3 C; A, p4 u
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)# D4 j! O) p8 `  `; B  `! v
  93. {0 `/ g6 U+ {; V, `% O4 N2 ?7 |. ?
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)* v% [( p* T1 X
  95.                 return 1;/ |7 O# _7 F3 t/ I4 O
  96.         return 0;& H1 ]5 d0 g& W2 h! h" P
  97. }( w$ y+ N/ O8 F# E( ~
  98. 6 o) z+ K, n# g/ F# x; D
  99. * e! g+ A2 d* y
  100. CAN_TxHeaderTypeDef TxMeg;2 N# W+ d; t& V
  101. uint16_t TimsRepeat;0 q4 t4 w" p- |8 c
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)
    ; v) t1 ]& Z1 ^! M, P
  103. {
    ( L4 s5 t. j3 d. O, i2 \( B
  104.         uint16_t SendCNT=0;$ f; M& x( f* x+ Z
  105.         uint32_t TxMailbox;- z# E; `, w, A, U
  106.         HAL_StatusTypeDef        HAL_RetVal;
    0 y1 ~, g$ ?" {- f
  107.        
    2 O4 [; g! V. k
  108.         TxMeg.StdId = 0x321; //标准ID& a! _, H' R8 V' F' |' |, w
  109. //        TxMeg.ExtId = 0x10F01234;1 h2 S1 S5 j  M* P8 C* T7 T
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型; w# _9 p5 W0 F& @7 |3 w4 q- m) H
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型
    1 F8 T$ j* `) I, h# P8 J
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧
    , E$ w: z: E- U( |1 K' x' I
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧! ]3 D% [- k3 o; h
  114.         TxMeg.TransmitGlobalTime = DISABLE;
    6 m" V+ P2 F" b$ E+ l( G
  115.        
    5 y6 ^( t( V5 Z
  116.         if(!__hcan || ! pData ||!Len) return 1;
    $ V% v  `6 k; a# V8 A

  117. 1 ~4 _3 O% v( Q. @
  118.         TimsRepeat =Len/8+(Len%8?1:0);/ ~" k/ N0 g. q) b+ |% c
  119.         while(TimsRepeat--)' E* c+ P& m+ {9 w
  120.         {
    6 _: u/ J& ?2 E& N) g+ B
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);
    " z3 i0 Y6 \3 g+ I* i
  122.                 if(TimsRepeat>0)- k% P. D" F" Y1 I7 `, W0 J7 O0 W
  123.                 {       
    % \/ {7 w1 S& c& X. W
  124.                         TxMeg.DLC=8;
    - B3 [1 T% |2 `$ `
  125.                 }
    ) @, ]1 h( z7 g( R; K
  126.                 else+ i- E  t! T3 k& h2 ?5 H" c7 ]
  127.                 {
    % L# o+ @/ n7 d  Q8 c/ v9 W  D
  128.                         if(Len%8)
    / }2 R: y0 O# u! m) m4 l. u
  129.                         TxMeg.DLC=Len%8;
    : v7 W, x: y( X" }8 X
  130.                 }
    * O# l# a% w( V$ R/ P* z
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  9 K4 L, d$ l7 y1 R
  132.                 if(HAL_RetVal!=HAL_OK)0 l) Q9 L- h+ Q
  133.                 {( y! B- b9 {+ l# L: Q
  134.                         return 0;
    ( X* w. g7 v( A1 c# [
  135.                 }  x$ H6 d% Q0 W9 e& [. l
  136.                 SendCNT+=8;
    , E; M7 ^" o8 r# u2 E
  137.         }
    - Y' ?$ u( f% p( z
  138.         return 1;
复制代码

  r/ c: I3 }6 H2 ?2 H
5 \% T' ?4 v" j  p. [4 Z

bsp_can.h

" u4 W% K1 b! K& l4 W. Q1 H4 k

  1. #ifndef _BSP_CAN_H
    9 i' |# B& F; C- a
  2. #define _BSP_CAN_H4 G- e, k- T& q9 N# s4 M
  3. #include "stm32f4xx_hal.h", L$ ~0 i1 }. e2 Z
  4. #include "can.h"
    5 ^2 E  f5 V+ [+ M3 J

  5. 2 O* k0 B; J( a6 U, d: I, N/ b" x3 t
  6. //typedef struct
    + P, V  g/ r' p# |' V& |
  7. //{7 n4 w2 ]' r3 z1 |
  8. //        uint32_t mailbox;6 T0 K/ X3 r/ n' q2 Y. B8 X1 _
  9. //        CAN_TxHeaderTypeDef hdr;* Z+ H4 h1 E* W+ U* R2 K
  10. //        uint8_t payload[8];2 C1 ]7 |9 f& {4 N( D2 X
  11. //}CAN_TxPacketTypeDef;
    / X$ J' U$ ^! ~% ^$ C4 w

  12. 5 _2 V5 A: o; E  v
  13. typedef struct7 q5 {' N# R2 r) k" c- S! J% z4 X2 k
  14. {
    2 x% C3 z& G. k: U+ B
  15.         CAN_RxHeaderTypeDef hdr;* {. W0 n5 @; {- U# e; {
  16.         uint8_t payload[8];/ ]: i+ n! v& _; A3 ^8 k
  17. }CAN_RxPacketTypeDef;- S4 |" `0 ~3 |- v, m$ ?

  18. 6 t8 c1 o# W# g6 h2 @. ^! }) h

  19. " U) z* M8 j! L( a' _
  20. void CAN_Init(void);/ W8 O# g9 s/ P1 w) f
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);/ e/ T( X7 y6 c) y: t
  22. #endif
复制代码

6 o/ [' m$ G, Q8 e3 v8 x

就可以工作了???非也8 V6 M- Q$ H0 m6 M& b0 M; C6 s4 t
其实我发现还是有问题

+ l$ l9 M- W6 k/ h4 _

3_meitu_41.jpg

9 E7 J. j* z$ w9 P" ~9 p: E3 v6 E$ U) \& K/ L' o5 ]4 q, N' W
7 j( ^' m  `8 W! u5 S( u% b1 f
为什么第2 3包数据到最后去了?

2 b2 W; s4 L! O

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

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

- p$ p% p5 o% J7 ]

查看库函数
5 E7 Z$ K& {, M0 H. E' H


# d. B! W0 r8 a. J$ u* x. g# z

  1. /**2 t; X( h! K) R  X' ~2 s' ]
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    1 v2 I5 M4 D* H4 P" x8 w
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains3 r1 O1 W% W1 D) T; D1 Q
  4.   *         the configuration information for the specified CAN.. K1 p+ J4 Q6 z1 V+ E# s3 T
  5.   * @retval Number of free Tx Mailboxes.2 j5 v$ ?% a( J# U/ ?
  6.   */) N4 H) L& p; |6 h- _
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)- |, F3 U/ ?* P8 f  c' F
  8. {5 q* U! Z* P$ j: k6 B/ m
  9.   uint32_t freelevel = 0U;
    . N! f  X3 I8 Y
  10.   HAL_CAN_StateTypeDef state = hcan->State;+ g& ]1 a( Y: \7 \# X

  11. 9 k3 u- Q+ q! s6 a$ V7 e# j2 T
  12.   if ((state == HAL_CAN_STATE_READY) ||
    * }5 n* g1 J1 y$ j
  13.       (state == HAL_CAN_STATE_LISTENING))
    + f9 k! @8 ^7 m* i: W5 G$ T
  14.   {
    / H1 m) Y( G+ |2 X: `! F6 @4 Z
  15.     /* Check Tx Mailbox 0 status */' g4 N% i  H; h2 f8 _
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    ( l4 `9 z  ?5 g
  17.     {, [0 O0 |% H! V6 k
  18.       freelevel++;
    3 N9 _7 @* T* Q2 s2 S
  19.     }
    : t: g. k; g* O# m& q
  20. / m; Q- b1 `" I5 ]  J
  21.     /* Check Tx Mailbox 1 status */
    $ }; ^" u$ [) |3 f& @9 P3 H4 b& C
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    . D& |- u2 d8 e) q7 U' d
  23.     {
    4 B) a! B( g6 D
  24.       freelevel++;0 s# c9 Y- |0 r. P. b- g
  25.     }, v3 `0 g& p  @7 T
  26. # O* e) k9 z- Q& N
  27.     /* Check Tx Mailbox 2 status */, J2 V  n4 l' {$ P, F  h
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)/ o+ g& X2 r( a; q& o+ c: V
  29.     {) i% F! U1 R2 T. E( s8 o! W, L
  30.       freelevel++;) Q( @. v9 X! D
  31.     }
    7 a7 G( D  J* {; U% p
  32.   }$ B( X! ~8 ?/ O; }$ d% ^
  33. 0 |4 @' d* j, C) J
  34.   /* Return Tx Mailboxes free level */
    " G- h( j: d; M! l! A
  35.   return freelevel;6 E7 }" D% [) M% r( V2 o
  36. }
复制代码
3 c  |% S. Z" |) U: j

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

6 Z: f# c/ }* P. U! S3 }9 t

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)+ a: v" s  ]  ^4 U4 ?) o
  2. {4 l0 P/ [3 U$ c6 D3 y: P7 V) N
  3.   uint32_t freelevel = 0U;; ]% ~5 Y; ]' M  x" H
  4.   HAL_CAN_StateTypeDef state = hcan->State;5 G; z4 W. D7 K% _! l
  5. + x! O" ~( A& b5 b0 q; f
  6.   if ((state == HAL_CAN_STATE_READY) ||
    8 q5 R* m& t2 r/ F  [
  7.       (state == HAL_CAN_STATE_LISTENING))0 @- J' ~" U' ^1 ]7 z
  8.   {0 R8 F- w, k: V7 B, S
  9.                
    / y# @+ [  x1 S2 B2 E5 m) P/ \
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \# z& X5 X0 A. w9 T
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \
    & S: b: h3 `4 Y1 h) G. l
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)5 q5 g  r( F$ h9 G, r: k
  13.     {$ E+ K7 {: z7 v& S  O3 _- T
  14.       freelevel++;: _0 V' v) U/ T. }! W
  15.     }
    5 A# v* K! v1 ?+ T- u5 [3 Q
  16. 0 s( \+ V$ g. T3 Z; ?
  17.     /* Check Tx Mailbox 0 status */* t+ g7 F3 c' h5 q9 e& j
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)( q1 x% J" J6 i; f
  19. //    {  ]6 r) Z  F* E- \9 C4 d  S
  20. //      freelevel++;2 [( J7 i6 l1 [) z: @! r
  21. //    }
    ! |0 ^/ }5 {0 q) O# g
  22. / b! \1 o0 E2 f% Q
  23.     /* Check Tx Mailbox 1 status */3 H; G9 E* `8 E. w4 j  W
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)  G6 Z: G) N5 F9 z
  25. //    {! c( B6 G  P. a. n% E- }
  26. //      freelevel++;6 h- C' [6 ]4 b
  27. //    }
    6 X) a2 I; z8 S5 h
  28. ( \, W% N# ~! W* Y- M; f
  29. //    /* Check Tx Mailbox 2 status */" n0 m2 |0 @, L) }) ]8 J" }
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)# c0 N; L0 O+ O: W
  31. //    {. ?1 e* [6 d( R' V' w. Z
  32. //      freelevel++;
    / Z, I0 h2 K* z" y% E$ r- F$ B. }6 L
  33. //    }4 w" Q- [: R# {, N2 Q  u2 n
  34.   }3 `! l- R! W- [
  35. 0 x( F1 y! f6 y
  36.   /* Return Tx Mailboxes free level */) c, k+ s8 z" }' p" b0 Y. v
  37.   return freelevel;
    $ s3 }: {+ v) @8 u0 g
  38. }
复制代码

# @# R/ Z6 ]+ P+ y  n, O2 V9 z

4_meitu_42.jpg

' i4 T9 {. u2 l* c$ m: O
三 总结
" X; n$ }6 j. ?4 W7 O

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


1 O! \& {) T* h


" Z7 t( N8 T1 a$ E4 C* M* l

四、CAN以及库函数分析
7 M- J8 |% Q9 v9 I

CAN总线
' A2 `, B8 X# p$ m3 S, _1、根据标示符(也就是 ID)来决定优先级的。
. d8 u& B. m" V1 n5 x1 `' n2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)
' u, G- w: Z  Z# J! Y( Q3、可通过发送“遥控帧” 请求其他单元发送数据。) |, [& l. L2 U$ e5 a) n
4、CAN Model:


2 X! T+ l( O( c- O2 {- w$ z* W$ vNormal 正常模式! @; g7 B* e- j, V% B; C: b
Silent 静默模式1 U+ J- ?6 s" Q! q* D" _
Loopback 环回模式 测试. ~7 t+ C0 _3 Y$ ]7 M0 _9 ~
Silent_loopback 静默换回模式 测试

4 E/ ~8 k5 s# h. }, E/ t
5、波特率


2 P5 I% G4 D" S0 o% i" K波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)


3 T$ v  y& n' v& p

6、发送数据结构体指针

  
  1. /**3 }4 j5 N; y+ z4 G" L% `
  2.   * @brief  CAN Tx message header structure definition' s: g% ^& B) z$ x( t
  3.   */
    - F1 Z$ Z7 n# T
  4. typedef struct
    . ^: A. ^1 Z) L. {* O
  5. {
    . I: n8 U7 h. D; t7 X) u2 ^8 }
  6. //表示标准的ID( q. b( |3 y  c( F$ S
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.$ N) r, b  @2 b, x7 ]7 v
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */: F- F1 P' ]* X2 @  r% p) X+ P
  9. //表示扩展的ID; p8 J" f! `& ~  Z( F( b
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.. k' [. u# u5 J* Y0 q1 k8 W7 C- E
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
    $ b- c  `9 Q- D/ E4 T6 Y
  12. //要发送的是扩展帧还是标准帧
    0 L. B* V) ~( Y$ X( `
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.$ g0 \3 Z3 M; @' }2 W$ W
  14.                           This parameter can be a value of @ref CAN_identifier_type */! h& c9 F5 `- Y8 {6 W
  15. //表示发送的帧类型。如:数据帧、远程帧等
    ( d4 I+ v+ R$ s) y' g
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
    3 \/ {2 w9 R$ ]
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */# a9 Z! Q& ^! V+ v
  18. //表示发送的数据长度
    : w$ [' h6 ]. ^& `5 |1 M
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.: c1 t$ x+ V7 m7 Q9 I6 ]
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */1 t2 ]2 Y- }9 Z3 T! H  R, P  I
  21. * F. s. d% O4 @* K+ A' L( y3 T
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
    " \8 i, e, T& J/ q" q
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
    * `/ y$ e; M. _' C* v& O
  24.                           @note: Time Triggered Communication Mode must be enabled.
    . I2 K' o% N1 ^- F: Y, ?& f+ _
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.# G. {( _3 x- t- H( L4 T
  26.                           This parameter can be set to ENABLE or DISABLE. */% G# Y4 n5 |7 V# ~
  27. : Y6 V& t' _- x) P
  28. } CAN_TxHeaderTypeDef;
复制代码
4 S1 C: n% F: s3 c7 b) m

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器" i& e+ V( u) d) _  A; j% p* y5 @
屏蔽模式
5 @6 z# Q+ I0 m$ {! ]& L4 \屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你- |2 A" n  b- Z; o2 H( C& {
想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。9 D% e8 ~! w; L3 M" y
屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。

  x! n) v0 _( u" b

1 S" P" j2 Q3 r  S

8、过滤器结构体


8 V8 Z. |+ G0 l9 |
0 a1 ^4 v& q0 m, @* R2 }
  1. /*** N- K- a" D$ e2 B% y6 q( ?
  2.   * @brief  CAN filter configuration structure definition
    9 f9 c: C8 E8 H) }7 U( I3 A% ^
  3.   */
    5 L: C' i+ z  C/ Y
  4. typedef struct
    0 Z/ L6 M2 C2 s; L6 M& w# _5 }, t
  5. {
    % q2 ?2 k0 P4 F! F0 ?$ c9 Y
  6.         //这个是标示符寄存器的高 16 位( k& `  [/ V* U3 M+ b
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit
    6 u4 u! ]7 r" {3 F3 |; x
  8.                                        configuration, first one for a 16-bit configuration).
    ) g! d& I. Q! }# F
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    # b! m6 ]+ G7 r" z5 i) \# C
  10.         //这个是标示符寄存器的低 16 位/ `+ W& ^5 \, {
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit% d) X* ?6 \4 |- Z8 @  y2 _
  12.                                        configuration, second one for a 16-bit configuration).
    5 k5 \( I2 \$ E8 H1 |  d& [% g
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */- `* ~* o: o: p5 V( s6 z: |
  14.         //这个是屏蔽寄存器高字节的设置
    & @, v+ S( O0 O* R
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,0 N6 J: i; l6 F7 G  c% G$ J
  16.                                        according to the mode (MSBs for a 32-bit configuration,- ^* F- D4 v9 y, W' O6 j' i
  17.                                        first one for a 16-bit configuration).
    : d& M  E! f. g+ f, D$ ^
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */: h& M) d; |3 ^
  19.         //这个是屏蔽寄存器低字节的设置, \4 {- o8 w7 l/ @
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,* `2 }+ X3 l2 k/ x& ~4 c- a% j
  21.                                        according to the mode (LSBs for a 32-bit configuration,
    5 h7 D& h; |, @. {, G" |0 k0 h7 h
  22.                                        second one for a 16-bit configuration).
    % d( c( \' K( @2 \8 n
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    1 R/ y" l  X0 `; S4 O! ]# y+ F
  24.         //选择你要使用的邮箱,它有 0 和 12 Y! P, U2 X+ c1 g9 U5 h% t
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.  a# D; |/ _" m% A3 W
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */6 l6 G" \8 @% o6 U& S* {
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。
    6 e( c+ k% C( ?  `) G: b& ~0 m
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.6 F$ a0 ^$ ^. e7 H) x
  29.                                        For single CAN instance(14 dedicated filter banks),
    9 O  |) K0 _6 O' [9 ?! @  V+ r
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.0 A+ P! y5 ]1 C/ {, w# V
  31.                                        For dual CAN instances(28 filter banks shared),( h# Z) \8 R& S2 D2 g3 o; a( }
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */) [; x7 \! J& U% j
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和7 j. I) |, E9 U/ v& {% q$ a' }
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :
    " d$ Y# m, D+ p& ~2 o3 z
  35. //CAN_FilterMode_IdMask。- i; i4 A5 e% b/ X$ T& n& n
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.
    & \6 ]* }$ b- M' s9 c; q( ~
  37.                                        This parameter can be a value of @ref CAN_filter_mode */
    2 F1 D3 j2 M+ {; V( O
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。
    # f1 R. B. }! D2 u! W' O
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale." w2 Q7 C1 `" i7 j% V
  40.                                        This parameter can be a value of @ref CAN_filter_scale */2 c+ l8 d  z; d  v; t
  41. //表示过滤器的使能
    / I5 l3 O% k9 \0 j7 m6 p" X
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter." I% A/ O9 c- U1 Z) L3 _
  43.                                        This parameter can be a value of @ref CAN_filter_activation */& y& u1 N% \4 Y5 c$ c; p7 e! m
  44. ; Q6 ]  @/ m5 r3 w% p
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
    ; f0 w5 _3 ~0 F* C1 Q: y0 X
  46.                                        For single CAN instances, this parameter is meaningless.& l( G' O- x' M
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master  T& q# L' J- H1 M  |
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave, `9 p7 S' S; O
  49.                                        CAN instance.- t' v- }. s3 d% O1 U" r' J, D
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */: a' P4 B. p; X8 x0 Y; L6 R
  51. } CAN_FilterTypeDef;, Y5 g2 ~, g5 U- X7 Z
复制代码
* p; Z( m0 {& n

1 w- L+ C; H2 e  Q
2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

1个回答
yklstudent 回答时间:2020-9-29 08:29:13
不应该中断方式发送多包嘛
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版