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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?* A, c) R* }! M" p$ k9 s7 ~% I8 q
2、发送多包数据,网上基本上就两种说发* Y1 X4 V% E5 v' ~
*两个数据之间加延时
  t+ H$ O. W% }4 V. E*查询邮箱是否满了& Q- {: a& }8 l2 X. q4 O
HAL_CAN_GetTxMailboxesFreeLevel()) V$ v7 P; }9 y
对比上面两种方法,为了效率我们选择第二种


$ S& E$ S. E5 |% W  }

; E+ c. m8 Y0 E1 F6 ?2 n0 Z7 l9 n2 ~

二、配置与代码
/ h, e  M" P% [0 O- P' V' ~
! e3 n# B& G/ `

直接上cubemx配置


; a7 Z/ S- h: n' ?: ^( T


0 g& d- S/ g) f4 ?! s8 W3 c& [, z

1_meitu_39.jpg

/ C6 l3 }) R1 I# h9 H. D- \
2_meitu_40.jpg

2 t2 ?6 O" }+ c5 c$ R" E- I
; e) ?5 w6 m- c' n9 l7 P# D" V6 @8 B
直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下

  C5 ~* D! d, V

  1. int main(void)
    : x- \* {: U9 J6 j3 U# U
  2. {
    % b. h8 D$ t" W
  3.   /* USER CODE BEGIN 1 */
    ( H0 J2 |  p5 B8 Y6 \5 B

  4. , h% \; P. L7 b* n
  5.   /* USER CODE END 1 */& y# K4 C- j( C; E  R* L( q! V3 ^/ V
  6. + D* k4 K- `" T- b
  7.   /* MCU Configuration--------------------------------------------------------*/
    9 j3 K, V2 U; z' i

  8. % j0 g. p2 z. `/ X- V
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */$ z+ {; O8 ~" ?4 p% M7 X
  10.   HAL_Init();; B5 P! {& c0 B# Q( j& }$ K$ x
  11.   T) _. N  q* [7 N- c* y; R
  12.   /* USER CODE BEGIN Init */* J6 P7 D" G  {+ x, G$ z& r

  13. 0 g0 n: F) `& n% ^! r% C
  14.   /* USER CODE END Init */+ z5 W$ ]9 w+ Y8 W4 C

  15. * Q! A& b/ `- u
  16.   /* Configure the system clock */
    ! P( F) N8 c; `5 M
  17.   SystemClock_Config();
    . H+ W' d; v% |# a: z
  18. & n( @# D( E" A, J6 ~& l; n
  19.   /* USER CODE BEGIN SysInit */
    " p, o) Z; H6 f# T% u( E
  20. ( }- h. P8 h- p3 T' o( S, n6 G7 S
  21.   /* USER CODE END SysInit */8 t- I  `" v) u/ `

  22. ) j$ V! z& ~- h5 L) \; q
  23.   /* Initialize all configured peripherals */" D7 H, B( b# v8 y1 c( J
  24.   MX_GPIO_Init();
    3 J  _3 \; r! j; O8 X; V
  25.   MX_CAN1_Init();
    7 {/ o* n! i, L+ @6 s: L. N1 o% S
  26.   /* USER CODE BEGIN 2 *// l4 l$ n' g# N, a7 L2 Q) W1 k
  27.         CAN_Init();! T. O; {5 U) @# ~6 E8 G( G& k
  28.   /* USER CODE END 2 */
    : O% I$ T8 J* Y% a, u& N
  29. ' D( d4 a4 V( b- \2 P/ X
  30.   /* Infinite loop */2 e( K: o- y" g6 P8 q7 V. `. |6 [! K
  31.   /* USER CODE BEGIN WHILE */1 `) a& K, `6 M2 m* d
  32.   while (1)
    4 k1 t, _4 o* [6 b& W
  33.   {/ Q9 x; a7 I; c# l
  34.     /* USER CODE END WHILE */
    / ~' Q. q9 j% Z. R# y  k0 m
  35. * i4 u: R# I6 T9 }$ H) l+ a( B
  36.     /* USER CODE BEGIN 3 */
    ; m. W7 k0 y  y0 M5 h1 Y6 l- w% @
  37.                 uint8_t TxData[100] ;1 N8 Q9 R6 G  J$ M! w# ?% f% v
  38.                 for(uint8_t i=0;i<100;i++)' S" m+ D8 T+ W" U; O; v# G
  39.                         TxData[i]=i;; v; [3 C+ ~- f* y. L
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));
    0 P& \1 o2 }- _1 ^2 u
  41.                 HAL_Delay(100);
    6 r3 x) q5 ^; F2 Q. S: W  d: J
  42.   }! }4 [3 z# u! Q& K: G2 Q8 s. B
  43.   /* USER CODE END 3 */# g' ]  z% H8 ^: T* {
  44. }
复制代码

# G9 s$ G( W( c3 u% P* A# q

bsp_can.c

) u# r/ ~: B3 X. Z/ p
  1. #include "bsp_can.h"
    8 S1 t! ^. Q( }! M

  2. ! I7 V# D7 o9 P2 U" U

  3. 5 ~2 q# y& S# ^# K2 P2 R/ |6 j6 m
  4. /// CAN过滤器寄存器位宽类型定义
    ) G4 Y2 J2 S% V, f( P, a! ^
  5. typedef union
      Y0 w6 U3 u; u: A# w
  6. {
    - }: E- E, X/ g
  7.     __IO uint32_t value;
    % Q, p& G. S) \. W; }1 c0 C
  8.     struct6 \# k( o0 p  v1 a- Q0 I
  9.     {# i# v$ g: m5 N2 n  ^) J
  10.         uint8_t REV : 1;                        ///< [0]    :未使用! A% _  r' i1 V7 g- V& ~; A5 J/ p9 Q
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)
    $ _8 B! j# [8 |9 T+ C  E" O
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位), U- X, M! t  @. X& \* x
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID6 w+ ~# B) f! b3 A2 H+ t
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID$ c3 C( s4 d& S' ]
  15.     } Sub;8 F5 m- V8 ~  \/ k$ `
  16. } CAN_FilterRegTypeDef;4 [) K6 ]4 D5 k4 R9 X

  17. ) `, h4 F9 V9 b
  18. . I+ m5 j" @& N3 _3 d1 }. b2 p2 ~( U
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF' B/ T% Q3 ~/ i8 f& K) R6 n1 h5 _# x

  20. + r" Q% e( f+ E7 a' }7 E; b
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式
    4 O+ ]% y6 w; b5 B4 U' Q/ y7 D) l

  22. # |& c, t9 E* j
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID
    # X% ], N' l$ V, P
  24. ; v, h/ f. `3 J9 G. p& p
  25. void CAN_Filter_Config(void)
    2 S$ |: w2 }/ z& Y, ?  H
  26. {1 q* A* E$ t/ j+ z
  27.     CAN_FilterTypeDef sFilterConfig;* y- ^# R7 R% E2 C5 K
  28.     CAN_FilterRegTypeDef IDH = {0};' E+ @+ a# F, ~  d+ y/ b* r2 m# B$ _
  29.     CAN_FilterRegTypeDef IDL = {0};: G. V; M( y4 r9 s1 M6 d( \* O
  30. ' u, v  P1 H6 Z3 C: W, F+ ]
  31. #if CAN_ID_TYPE_STD_ENABLE, Q- T% S" h! o+ v# v. I/ }
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位( k- k7 O5 a( k, G  w% L: v! j  i
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位
    8 m' P, C' a& [- Y2 s
  34. #else4 H  Y: y+ ^3 T* d& x8 \
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
      \1 o8 Q7 _5 J6 a% a: G6 C0 g
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位3 W# t, `* ^$ ?; u6 M5 q% ~  `
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
    # ~; ^8 l% \6 N  `- [, f+ T$ D6 g1 C
  38. #endif3 M+ \. G. B2 C0 b$ E
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号
    9 Z. W4 ^5 t/ X3 w* V! ~' ], H( }
  40. #if CAN_FILTER_MODE_MASK_ENABLE% H4 Q4 Z* B& [; s# ?
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式; E+ d. }4 e  F8 d/ A
  42. #else% l3 v" T# \9 o6 J0 _' b
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    3 j' H. H6 O/ W7 X( S! a1 z/ v; t; Y
  44. #endif7 k+ @4 @8 H) h/ b' d4 O8 G
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽  x6 T+ }- s4 T  r+ S
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    5 A- m' ], F" `1 O: i
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位* N' G6 K+ p( E3 A
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位" j, ]$ E" S# \9 K
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位& u. f! Z$ c/ ?' P# e
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0' f+ n7 U- d1 n! z$ q. P
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器
    + ^7 W" @# x* F! F
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效, C% w$ _0 W3 C- a* ?
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
    - t6 U- l7 z1 G
  54.     {
    ; ?- i" b2 N5 V6 u8 N
  55.         Error_Handler();$ h6 [$ K: K' ]7 G8 n, o$ N: X6 l; ~
  56.     }
    ' `; s- X( Y: t, c  {
  57. }$ }; n& S- M' G2 B4 b

  58. 6 O" _" j5 q1 F' f* Z9 I; l
  59. 0 X8 z" [; z- Q9 n9 y1 a( Q) |- s/ {

  60. * [7 w) k) e4 r5 A) i0 ?
  61. void CAN_Init(void)
    $ i, n; s( I" M- {$ Y
  62. {
    . O3 n4 K0 j! Z) W: o1 \
  63.     CAN_Filter_Config();) @6 e2 f. F1 |, O1 b" W
  64.     HAL_CAN_Start(&hcan1);: J* {' a5 h; `1 Z* u2 _0 w
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断8 \. n. S  F6 @, d. x6 ?
  66. }8 m/ [6 K7 e5 U0 ?1 h8 L

  67. 5 f0 Z' B1 w' o# R6 p$ c
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)
    / ]. D& }- H8 O" N1 X! \
  69. {/ I8 m( [* a) V0 b# k. y0 {" M# |
  70.         static CAN_RxPacketTypeDef packet;
    8 Q: _- m* d3 c4 J
  71.         5 ]" `7 a+ D! i, g/ S
  72.     // CAN数据接收/ P& W! ]( w/ g9 R% g$ p4 N
  73.     if (canHandle->Instance == hcan1.Instance)3 a3 h) V2 o; Q& a" X; S  T4 i
  74.     {
    ( E6 F9 g7 V4 ~/ b5 k$ T8 A% c
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    ) H" d9 k, Z+ T1 \2 Y
  76.         {4 i: z% X  [9 s, l0 V, v/ b) s- @- q
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");3 g7 E  q* p: Z% O8 E2 `
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);
    2 @5 w& t( {2 N- W' m$ |9 E1 Q
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    " b/ x9 q$ Q5 K: n& d# w
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);
    6 s" K% f/ Z2 R8 V. Y
  81. //                        printf("DATA:");
    9 _, f" e% H0 G
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)
    ' v, W/ Q) E& l; |1 p( @
  83. //                        {
    * }8 M0 X8 c$ g* u. x
  84. //                                printf("0x%02X ", packet.payload[i]);1 X! m- E" s7 B& g
  85. //                        }* v2 _+ E4 ~6 a/ \6 Q7 R' f2 I
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断5 ?5 ]4 a1 a+ @/ j
  87.         }
    # @3 D% n9 {* P6 v- M3 r# g+ o
  88.     }0 H* B3 u2 O' }4 H
  89. }
    ( @7 F/ r4 @/ X1 Y! B2 I

  90. * O& Z' b7 S5 e: _* H, B
  91. , Y/ l; g, l- s9 ~# Q8 a  }" v
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    + X6 Y9 J5 q+ Y8 i% e% K( ^- K
  93. {. }  P3 ^. ], d- {- F/ ~
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
    6 |0 l1 x; q- M0 Z. R$ c8 V0 k
  95.                 return 1;! n/ q3 b: o9 z
  96.         return 0;
    7 a( {) _1 |; ~, c/ a) a
  97. }- I% v1 `& ?6 N. `& @8 j7 b

  98. ( m* O$ X0 E7 L5 `& R

  99. 0 |+ `8 H4 m1 O% _/ M. p( `. J
  100. CAN_TxHeaderTypeDef TxMeg;
    ( J; y1 m) ~, R- a. T# f$ G
  101. uint16_t TimsRepeat;* U3 w  `  A  ]/ x6 T
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)4 ~- V# l% G; `$ Y
  103. {! n' t- Y8 R7 j6 [2 ]
  104.         uint16_t SendCNT=0;9 B0 K& i8 c2 G/ t
  105.         uint32_t TxMailbox;# X- X) x6 {% u2 `# l
  106.         HAL_StatusTypeDef        HAL_RetVal;% X- r; J7 N$ [5 r3 t
  107.        
    9 x+ j8 y6 O1 g# u! e# h/ k; K
  108.         TxMeg.StdId = 0x321; //标准ID
    4 j4 Z9 f% ^0 W4 l* Q/ |
  109. //        TxMeg.ExtId = 0x10F01234;( q" |& V0 a8 g$ t' Q. W* _
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型
    ; V1 }* N+ R: x2 a8 J  N$ Y4 a0 |
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型
    2 }) P+ h3 p# i6 K8 r7 }7 }, ^4 E
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧
    & B4 e" Y7 h: H+ v
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧
    4 p& T0 ?, b: M% `4 P( R% K
  114.         TxMeg.TransmitGlobalTime = DISABLE;9 w( O- }& F+ X! H! ]
  115.        
    - ~. o4 T) M, q# Q2 B% u
  116.         if(!__hcan || ! pData ||!Len) return 1;- ]) n$ I9 q. N" t! J# I( R

  117. ! D' J5 Q/ d) K( I! }! g
  118.         TimsRepeat =Len/8+(Len%8?1:0);1 ^$ X1 t- B0 e. J! t3 I" J( @' Z$ e& ?
  119.         while(TimsRepeat--)
    ' `% U0 X( y! `; d, t
  120.         {
    0 N, @% q6 h0 G+ S, g' o% c
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);
    3 Q4 q( R7 K, u- i; @9 X
  122.                 if(TimsRepeat>0)
    0 E+ J# s- K( Y/ s9 h
  123.                 {       
    ( d  B- F: ?. Y% _% U/ s. m6 q3 G% y
  124.                         TxMeg.DLC=8;
    # A+ s3 |6 z4 K" V
  125.                 }( m1 [' m: o8 w, t3 G& n5 x
  126.                 else# _2 @9 `2 |6 A0 C; o! Q1 R
  127.                 {& ?2 a* U$ y" B- M9 I
  128.                         if(Len%8): b. \+ p4 P, e4 t5 {
  129.                         TxMeg.DLC=Len%8;- Z  @3 k. ?/ U: r6 `; ^
  130.                 }
    # b- K# G/ D0 `& q$ s
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  
    / ]/ G9 S, f! z3 R& ?& n& R
  132.                 if(HAL_RetVal!=HAL_OK)
    & D; P$ X' x. s4 `
  133.                 {
    - x9 u' j( |8 p* N+ k, z- V; @
  134.                         return 0;) q) g2 b5 A5 f
  135.                 }
    ; }- ?6 `& b7 `; d
  136.                 SendCNT+=8;- A+ C/ G& _$ b* V. I8 ]: g/ t1 t1 W5 I
  137.         }
    / h* c0 m; u/ u# |* S+ B& f
  138.         return 1;
复制代码
( |* q) r7 k$ m7 I
9 A0 N+ q7 N; h$ \  l. ]) G

bsp_can.h

& o' @1 h7 ?" _6 a& ^* z

  1. #ifndef _BSP_CAN_H7 B/ {/ S3 d1 l/ S- f9 H1 m7 T9 g
  2. #define _BSP_CAN_H
    & S$ e! C/ e* Y
  3. #include "stm32f4xx_hal.h"; d2 K0 C1 X) V" }7 e' N! b
  4. #include "can.h"
    3 Q# H. u# v+ G

  5. % o1 M* j- l/ I3 z( U
  6. //typedef struct+ H' p8 Q2 R0 `: b: N
  7. //{
    - Z4 r* r8 h: B5 i/ I% a: d7 Z# u
  8. //        uint32_t mailbox;
    # C' P7 v7 H: s! o8 `
  9. //        CAN_TxHeaderTypeDef hdr;
    - n& v2 c4 |! _" ^( w% H, c
  10. //        uint8_t payload[8];
    ! r) E* A7 C6 E% m* Q
  11. //}CAN_TxPacketTypeDef;8 X* q$ E/ c8 Z8 s

  12. * a- O6 \" G9 g0 M8 N
  13. typedef struct
    , {5 V2 d* t4 g' K, K+ c
  14. {
    % `8 |: ]' f( t4 n7 }, t0 w0 O" X$ \
  15.         CAN_RxHeaderTypeDef hdr;
    7 O2 U% }* P, |1 m4 y/ y3 w
  16.         uint8_t payload[8];
    5 X7 ^/ w* s) N* W6 R7 x; a
  17. }CAN_RxPacketTypeDef;4 B" @0 A. t1 C

  18. + k6 j( b$ N3 K
  19. 8 O: C" D9 b1 q
  20. void CAN_Init(void);5 d* ]: J% V* D
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);
    4 Q$ O! |/ p" S7 Y' l5 K
  22. #endif
复制代码
4 z5 r& R( l6 s' W. L: A" K7 `

就可以工作了???非也
  N7 e; L2 w% D) o! s/ ?其实我发现还是有问题


6 h* t' q1 R% K0 e! @. V, N5 y; Z

3_meitu_41.jpg

0 p! O  R/ g2 o" j
5 F1 I! A6 u& G: X" L4 j6 N. L- [1 Q% V* k( h( Q+ P3 m" {
为什么第2 3包数据到最后去了?


6 K' E/ {4 T  J6 t" r

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

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

& x6 y4 x1 n- t0 a$ P! e- ]1 ~

查看库函数
+ e. n7 x0 W) V& N  u3 w


) }0 |- g# X# \9 \2 k. l: ~$ s/ a

  1. /**- S# ]( z2 W6 W9 G* C
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    4 k4 ~2 x6 y- \! e& \
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains* }! S" q. T+ P6 r
  4.   *         the configuration information for the specified CAN.$ h/ c8 k3 J' c2 ?& R* A
  5.   * @retval Number of free Tx Mailboxes./ T& M( \6 Q" ]. R) }& o
  6.   */
    , q* t. I2 j- v0 e2 P
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    ' q/ z5 i( E! @6 [) d
  8. {" U) N, f6 p" Q: x( d# T( @7 V
  9.   uint32_t freelevel = 0U;
    # Y2 U! D* L. b2 L( Q
  10.   HAL_CAN_StateTypeDef state = hcan->State;
    4 _5 f1 H  G8 b9 O, ?+ k! Q: }
  11. . |+ }& h' i5 p" P3 \
  12.   if ((state == HAL_CAN_STATE_READY) ||
    - |& t2 D# t9 B0 c9 `0 I% d( V( w) h
  13.       (state == HAL_CAN_STATE_LISTENING))
    / s. b9 ^2 p# j5 C
  14.   {
    , g6 _' `5 B- `6 W
  15.     /* Check Tx Mailbox 0 status */
    : j- K, \: j4 L+ _
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)0 [4 M' G8 S5 J8 F0 k
  17.     {5 p* `5 M* A  K
  18.       freelevel++;+ S5 D$ v" Q# p1 z6 U
  19.     }( x( n' {; [" U( y! }! l# }+ k
  20. , p" p& Z, U  Z% m8 `, J+ d6 D
  21.     /* Check Tx Mailbox 1 status */
    ; |: ?( v$ e) G+ u5 o" F3 k
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)! P9 h% L3 Z! G& a
  23.     {; w& ?" v2 L. h  h' V# ]7 v
  24.       freelevel++;
    ( `' p$ t( _  N% |# d$ ?, X
  25.     }6 W2 j; Z7 |# }& s5 k5 E

  26. 8 u" T7 p: n. A: d( F1 b
  27.     /* Check Tx Mailbox 2 status */
    9 L' J$ P* z" p
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    # H+ U5 G! V) v0 o1 H
  29.     {
    ' T( ]$ H& ]2 F- \- V1 d  F
  30.       freelevel++;
    9 m: i( H! T. {6 p" K+ @
  31.     }
    ' L" ]- y9 T  u( a( A/ J
  32.   }
    3 R/ Z  o+ W, Y+ j9 L2 [

  33. " u9 Y( ^# F; o2 {! X
  34.   /* Return Tx Mailboxes free level */$ i, d# F; ]$ F% w  Z/ U
  35.   return freelevel;
    2 F1 u5 M& s9 e. g% j
  36. }
复制代码
! v  a% f" r/ f0 I3 Z

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

4 i8 I% e- }) Y# D9 y

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    9 {  r" |* R- a; h0 @) [$ Z$ B
  2. {
    5 h1 t7 L0 W; m7 [  r% z' {
  3.   uint32_t freelevel = 0U;
    * z" ]3 |  ^7 }
  4.   HAL_CAN_StateTypeDef state = hcan->State;
    ) s  [8 C: o2 I

  5. + t% Y5 B0 L; {, L' d- [- B
  6.   if ((state == HAL_CAN_STATE_READY) ||' S& g% w* r) L
  7.       (state == HAL_CAN_STATE_LISTENING))9 n9 t4 u: p* D% F# j$ x
  8.   {1 d' z3 r$ @* m/ G7 T
  9.                
    ; `, u* u! ^8 g# _
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \8 i1 e5 i7 }) Y  m+ r! N
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \
    " d2 a1 M4 O. x
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    ; A, M) |6 J2 \* Y& s
  13.     {
    5 ~) `# j0 c. t( U8 W' v6 T! r; p
  14.       freelevel++;
    % x; R$ R7 f) Q, @+ m
  15.     }; R' c+ G9 w$ l3 l7 f
  16. 1 w& n* ?2 k( Q2 O2 D3 ^! H; k9 \; q
  17.     /* Check Tx Mailbox 0 status */3 \# P: r9 u$ d! i
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    # f- ]) S4 [3 y+ a
  19. //    {
    " ?" c4 Q5 P" _7 t: Y( l# U
  20. //      freelevel++;8 M( S& A) J8 k
  21. //    }
    3 [' m- u. p* V( u# U2 i) |) ?# u

  22. 4 V% o4 o; L  K; m/ B2 I) Q- M
  23.     /* Check Tx Mailbox 1 status */2 O6 i5 f& |, [1 J- N3 G( A
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    ; V7 e9 u: R% a
  25. //    {
    " E5 `2 {( D  K, D( r! S- T
  26. //      freelevel++;% W0 \4 A9 O8 K0 q; V- A
  27. //    }; x; p7 y* m6 N: a& W
  28. ) ?; m, s- C4 y1 h
  29. //    /* Check Tx Mailbox 2 status */; S1 |( ]* U8 s$ M" s6 z7 J1 k
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    ; C: a* w" O% Z$ N8 i
  31. //    {+ z) r0 g0 o- W) z
  32. //      freelevel++;
    4 h) Y* c+ q" K6 {: K. L' _* U& Z
  33. //    }
    / ~5 J7 r% i9 x# C8 Q
  34.   }
    " O8 I- C7 ~' U

  35. 6 B: r* c, b5 c1 G* ]
  36.   /* Return Tx Mailboxes free level */, [) c7 H" J! X& |
  37.   return freelevel;
    7 J* ~: m5 m7 @" |# I" _7 T4 G8 r
  38. }
复制代码
% [% z) L  G% E* z- E

4_meitu_42.jpg


! O3 V, J# k) G% v三 总结: [; d! r7 L( a9 ?' T

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

6 l( {8 m( `% L) l% {) x- @0 H


9 A' j! b& Z! p, d7 d6 B

四、CAN以及库函数分析& j/ n* d( N4 m3 k

CAN总线
! R+ o* f7 X$ [2 S7 A# x1、根据标示符(也就是 ID)来决定优先级的。
3 b+ s* z# v1 L) E0 k, e2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)
* q8 P2 V3 E/ p) t7 g3、可通过发送“遥控帧” 请求其他单元发送数据。3 c  ^5 B4 ]7 Y) L, e! Z. ~
4、CAN Model:


3 z' N' B* ~9 z6 `1 ~# WNormal 正常模式
" x  Q( C9 \, P6 qSilent 静默模式
9 }: X3 I' j( }. L/ dLoopback 环回模式 测试& P2 h# f# l' t1 L
Silent_loopback 静默换回模式 测试

  N1 d5 g5 D, u* e& _2 P
5、波特率


% H  d* o% L- U9 p% _, f& x4 g波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)

- n  b4 t. [+ A2 u9 ?

6、发送数据结构体指针

  
  1. /**" Z4 w# h$ b( S+ R: O1 m7 T6 M9 u
  2.   * @brief  CAN Tx message header structure definition
    % I6 Z) w/ F5 h2 H0 L  Q$ ~
  3.   */( m, f; |/ ^: v6 P' S) m: {
  4. typedef struct, i8 g8 _" ^* I
  5. {
    1 A! _4 h9 |- d, B) H9 Q
  6. //表示标准的ID
    " o6 _! ]7 p6 W0 M* S
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.5 J4 e$ ^. E( L- D
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
    ; u2 `$ @& V. e
  9. //表示扩展的ID+ _9 Y' S- Z: Q! z# H2 |/ D% R
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.8 K6 }* G# M! _  c, i& ?
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */  n- A* I( A2 Y! d4 z* N% i
  12. //要发送的是扩展帧还是标准帧5 e5 l: Y& c, B) K0 B
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
    " q- B2 w& g5 s$ p6 O7 W% ]' _* d
  14.                           This parameter can be a value of @ref CAN_identifier_type */9 T9 A; O7 J/ D! E1 ^$ h
  15. //表示发送的帧类型。如:数据帧、远程帧等
    1 I" C2 t8 T' n
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
    * z3 W% p, k" L4 n: L
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */' T, M9 A5 T1 L- q: E8 ]
  18. //表示发送的数据长度
    / M% x5 Q+ ^3 d5 H7 S% Q
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
    % x8 n1 T7 y; j. o5 e7 }
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */7 ?5 X) }0 z% ?# f
  21. & X9 ?$ _( H; `5 q9 ]. O
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start( }# H( d+ _' a2 F. F* _
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].5 E* u( Y! q4 M( t  ]) D
  24.                           @note: Time Triggered Communication Mode must be enabled.
    ' f; U- [% x0 e' J
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.- y- _( G2 R3 o( Q# j: T& h
  26.                           This parameter can be set to ENABLE or DISABLE. */
    2 Z$ a0 r2 w, c3 o3 @9 ]- L
  27. 6 y' V+ m* R6 S1 n0 H
  28. } CAN_TxHeaderTypeDef;
复制代码
% ~3 q' U. A3 u$ `$ m0 ?1 k, U$ Q

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器% U& M8 `4 E0 d. K, j8 _
屏蔽模式
5 a+ {7 ^; L0 v; n) [2 k1 S( f屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你
& l' a, i; \3 {! q想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。
3 T  S. s4 Y: b- X, w屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。


# J8 N5 v3 j; o  v


& n+ L; I* p3 K. y' l. L

8、过滤器结构体

( R/ ^% M( d8 j5 D
  a$ l$ s9 E7 i' @  G; b# s1 c
  1. /**3 W5 X4 G3 G% {/ V: Z) R
  2.   * @brief  CAN filter configuration structure definition7 H1 g: z& p. \
  3.   */
    ; h% N( l- f* ?: o6 p
  4. typedef struct
    ' U. L( }& P0 z1 b
  5. {
    / L6 q# Z5 T/ J% n- n2 k: R+ W8 ~
  6.         //这个是标示符寄存器的高 16 位1 N* M  f& }3 c3 z. m
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit
    , E! I; W5 F: O' `4 Y: v+ E
  8.                                        configuration, first one for a 16-bit configuration).2 Y# h: ?( Y5 w6 |
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */6 M* w* S3 O" A
  10.         //这个是标示符寄存器的低 16 位2 E2 {0 k, q; Z$ y3 f1 K
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit; K* O, h9 g2 I, x
  12.                                        configuration, second one for a 16-bit configuration).( I/ B0 e6 v: m" }) X% o% P* }
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. *// L$ o: r8 f# z
  14.         //这个是屏蔽寄存器高字节的设置
    ! _! _8 o; r( W4 F
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,$ l5 {3 F1 s4 r% e) C! A; R
  16.                                        according to the mode (MSBs for a 32-bit configuration,! J1 j1 e* I8 ], `
  17.                                        first one for a 16-bit configuration).
    - l$ N) l4 L0 X1 O+ H% P
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    # V2 j( F' u( G. h2 J6 @1 Q9 m
  19.         //这个是屏蔽寄存器低字节的设置
    " O, O6 _) ?- ^+ H; G2 r  t
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    : q3 n. j; I$ n# z3 R6 Q
  21.                                        according to the mode (LSBs for a 32-bit configuration,% p1 p5 R+ j* S) x7 Q0 x. |" a
  22.                                        second one for a 16-bit configuration).+ X" ]/ V% R( }+ k" \
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
      @* N: M3 m+ [7 E( f4 ?
  24.         //选择你要使用的邮箱,它有 0 和 1
    ( d0 `7 W$ n' D
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.7 ~' P5 L0 f) f
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */4 x% c) G& Z! [8 M# J. {
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。
    ' E7 L3 e6 d, H6 D( d' c
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.% b2 k; ]( T7 H  V  P* ~
  29.                                        For single CAN instance(14 dedicated filter banks),
      _1 r# t7 ^7 W- ?+ t! S% \3 `  v
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.# J" x8 s4 l$ R
  31.                                        For dual CAN instances(28 filter banks shared),
    # O0 E. {- @! o) K9 u' U7 l" G7 e
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
    & g$ n" Y* e6 y; C/ N
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和
    4 p2 E" {0 k8 a. t+ \
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :* _7 b& l) p5 A( T' c
  35. //CAN_FilterMode_IdMask。
    % J1 w% f7 Z9 t/ y+ `4 c1 ~
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.
    + {  R+ a# A5 C: j
  37.                                        This parameter can be a value of @ref CAN_filter_mode */& R$ m, F% U# U* R+ o
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。$ _; [. ~) o. E6 R/ [
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.
    1 M* u1 i3 k3 w, D; R: N9 A1 U
  40.                                        This parameter can be a value of @ref CAN_filter_scale */7 o8 ^# U2 l& @' F$ j3 f" w, B- c
  41. //表示过滤器的使能) a( w1 h7 e/ D  b4 ~# u5 K: e5 l
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.
    ! w# @+ x9 _4 Q( u( g0 l
  43.                                        This parameter can be a value of @ref CAN_filter_activation */
    - @+ |4 y4 D+ O2 n  m6 C
  44. ( }  _2 }, n# y& f9 g
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.( @, ~6 @# H" d
  46.                                        For single CAN instances, this parameter is meaningless.
    / P/ f! V/ h2 Z% o& t( A" [6 g' N7 U% e
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master
    % }2 q" Q: q- E; B# o
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave% g  D( E- l' o8 |$ J% i8 U
  49.                                        CAN instance.  v% v/ k6 ^4 R: G
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */) H8 F( {$ _; `! `8 {
  51. } CAN_FilterTypeDef;4 L8 W+ @6 G9 v
复制代码
8 Y1 K: D1 F% F9 z! [# ?+ `
+ t) P3 Z# O0 y  q
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 手机版