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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?( u' Z$ p" v7 B3 P4 F
2、发送多包数据,网上基本上就两种说发
. d! s5 C* k) t2 W6 p*两个数据之间加延时' V# d, z4 w) f% f
*查询邮箱是否满了5 ]- p% G, M! ?4 G+ N4 ^/ ~
HAL_CAN_GetTxMailboxesFreeLevel()
/ c9 l: A$ {) d- m8 G对比上面两种方法,为了效率我们选择第二种

8 r' g) ^. _# N% v$ p


  D- ]- o- J0 q* p+ p

二、配置与代码
+ Y: \/ T6 B* L
! T( p! K3 s# b7 D9 b4 ~

直接上cubemx配置


6 ^) Q5 B! Q* ]2 W* M# Y. O/ X7 G( S


1 C) B0 j( Q+ L

1_meitu_39.jpg
' E/ D. R; W3 z7 U! n
2_meitu_40.jpg
" g, U2 Y3 d0 k6 E6 M. b& @
( {: N& J3 C( b& G% L4 P  M

$ V/ n$ s7 ~5 o直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下


$ K/ ^! l& L8 E4 z

  1. int main(void)
    ! S6 B1 W" K- s6 w# X: R
  2. {5 n4 r% i0 }# q5 [
  3.   /* USER CODE BEGIN 1 */0 {) y- B- J7 I$ k& u+ f. s
  4. & r; A/ \4 ?% P7 p* ?
  5.   /* USER CODE END 1 *// b* z/ p7 V; ^& k
  6. . D& k! C/ }% t( A. N
  7.   /* MCU Configuration--------------------------------------------------------*/
    9 y- E; W9 l( [7 p5 H# O: ~9 l

  8. 4 i; a; F, E% Q2 ~6 X. F# s* J
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */4 ^% E/ V  @  i4 j
  10.   HAL_Init();
    & e; n- j: {& u/ q4 r/ a
  11. . N" @* T: N* j; s' X4 I
  12.   /* USER CODE BEGIN Init */
    ; `# t% U1 r& I$ J  I7 g3 R
  13. # }. B# F8 X7 Q4 x1 q3 q! ]
  14.   /* USER CODE END Init */; a% x# {  |/ d# V  ]/ S

  15. 6 W) B+ r" u! P& B7 l& e) C; I# Q
  16.   /* Configure the system clock */' z4 J: y6 ~* c- D! Y9 }
  17.   SystemClock_Config();. \9 q- @7 y  e( L6 T

  18. ; f! J6 i7 y1 I
  19.   /* USER CODE BEGIN SysInit */3 E" v2 ?2 ^0 N: j" C+ J

  20. , ~0 `+ T+ L+ s& C% S' a
  21.   /* USER CODE END SysInit */! B' S- o! b/ q2 \

  22. ( K5 {3 X% i& X6 ~) y$ E) O& O4 }4 l
  23.   /* Initialize all configured peripherals */
    8 f* c: Z5 `9 z! k: o: _
  24.   MX_GPIO_Init();6 `% p2 b1 @/ h
  25.   MX_CAN1_Init();
    ) z# f6 |/ C# f+ l  q
  26.   /* USER CODE BEGIN 2 */$ x! c! D' S# d$ A# S! ^+ W" ^* F
  27.         CAN_Init();
    : z' k( A  h( I3 h% K! \
  28.   /* USER CODE END 2 */8 U1 i4 U; H# I# ]

  29. ; u; c7 E8 s5 x. N, P0 b4 R
  30.   /* Infinite loop */. q" q7 F( f9 v5 u/ x
  31.   /* USER CODE BEGIN WHILE */
    6 ^/ i0 d* {+ |; P' J/ j9 \
  32.   while (1)
    # \$ j* a& l4 p( v. r. [# G  g' @
  33.   {! ~$ j% x9 Y. X
  34.     /* USER CODE END WHILE */
    $ i5 @* s# E. U+ R5 C4 o) O
  35. - z7 R  `) S! _, q# j( H  Q3 t
  36.     /* USER CODE BEGIN 3 */
    # p( y; V5 g& N7 Z9 w" `: J$ M; f- |
  37.                 uint8_t TxData[100] ;
    , I7 V6 p6 ~$ d4 P( P: B9 U$ ^
  38.                 for(uint8_t i=0;i<100;i++)
    3 L8 u2 N9 B) @6 o7 J% k
  39.                         TxData[i]=i;7 i; o$ j( A5 ]" H0 `7 i8 l
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));) |8 q- g  q. F- D  q, L/ r$ Z( N
  41.                 HAL_Delay(100);# A% J! d( R. a0 Q
  42.   }
    / e- n  R, f! l/ y! G! ~- h! E
  43.   /* USER CODE END 3 */
    ! i; D5 Q* A  i9 ~: F
  44. }
复制代码

2 m9 l9 a, M0 s( s  L+ z

bsp_can.c

5 g: X5 c6 H8 ]: \  q' }
  1. #include "bsp_can.h": g: U5 f6 ^0 A4 P# n
  2. 6 O, F; c( r0 {$ L. j2 U- y

  3. * z* u3 I# u# a8 z" |; ^  X6 Y4 ]* |
  4. /// CAN过滤器寄存器位宽类型定义
    ; J! L6 d( `' N
  5. typedef union7 d7 R2 E. ?( }8 l- |
  6. {
    . h# j0 L+ L! X: B" ^
  7.     __IO uint32_t value;+ H" q2 V! u# g3 t% a+ N- t9 e* {1 t
  8.     struct
    - W6 m2 ^" f7 `
  9.     {
    9 O/ y3 g1 v1 g
  10.         uint8_t REV : 1;                        ///< [0]    :未使用# l8 S+ B/ f$ S6 {
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)  m+ F1 L* Y% s- _
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    / Y% {, l! n9 E3 Z$ p
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
    & t3 K. _( @8 l, z5 j, R
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID( z  w0 y1 z2 K( E3 X0 p1 G
  15.     } Sub;$ ?7 V) m( @0 J
  16. } CAN_FilterRegTypeDef;' ]. `7 ~- I  ~$ ^& o

  17. ; u  c, P+ t1 }3 |1 E& ]

  18. 1 d6 e$ f5 f/ E# W! V# e
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF' q. Y' I3 F% q/ |* S. B
  20. " Y4 m" ~* g$ m3 t9 p
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式$ `' `( h7 P7 x& c& E2 F

  22. ( \1 |! N$ z0 ]- o2 L
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID
    ( l4 |) l1 H' E: W6 U  j7 `" a; \

  24. ( U/ K# l: F5 ~( S; z/ h& `1 O0 O
  25. void CAN_Filter_Config(void)+ p1 I1 o' j. e4 B
  26. {; {0 \( s9 Z8 j; E
  27.     CAN_FilterTypeDef sFilterConfig;  U  P6 ?% l& M8 Y) T9 _. \; n
  28.     CAN_FilterRegTypeDef IDH = {0};
    ; ~. T4 H% g" C) t5 G3 l# G
  29.     CAN_FilterRegTypeDef IDL = {0};$ x4 p: ]6 j. E) H% y
  30. , n/ v" E5 o* Q" }
  31. #if CAN_ID_TYPE_STD_ENABLE
    ) F. }' M$ \9 B0 H8 P( S9 ^" }
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
    ! o8 q" m1 v1 l- I$ l6 K) h# t
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位
    3 Y" J% G3 s2 r9 m- T
  34. #else) E: p6 T8 X0 m
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
    7 w5 b4 q6 c/ k) T6 Y
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位7 [0 Z: w+ P% ~* \, Y  m0 C( a, f( K
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
      b$ g+ y3 Y0 P2 t7 Q& q1 _! e
  38. #endif
    * T2 v7 H! K7 s6 R
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号/ H  L4 u$ V3 `% u7 X
  40. #if CAN_FILTER_MODE_MASK_ENABLE
    + a" O9 D1 L8 j" C2 u3 Y
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式
    $ w8 x* T2 Y, E* |
  42. #else
    - {1 e- C0 B! G* M; |: s( [; j
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    & H( [$ ]/ K3 ?1 n
  44. #endif$ f+ g" J( c* b& J
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽# e0 i% k# |# \
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    9 ?) m9 k. N- J# }6 a6 `! @( [
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位
    6 x  u- i4 z# }* k
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位3 s4 j/ E2 o1 U! [- m' U
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    / i$ n8 R7 x- W: B. C' i3 d3 E( B1 |
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0
    : J0 J( n/ [$ ~* G# H% x
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器
    " U* F) ~- U8 ~/ d4 n, f
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效
    9 j" H7 l/ B4 ]3 D& ~
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)1 A/ ^/ e2 e4 B% N, x$ n/ f* D  h9 X
  54.     {
    : Y" I  e+ v, m. ~
  55.         Error_Handler();# \8 h6 H6 a* e* S
  56.     }
    1 L+ T% l; ?. Z: h$ y. {/ J( Y
  57. }' r0 k$ Y3 M1 ~" Z4 D

  58. 0 A4 P# p6 @) {7 `
  59. 7 Y: y) F- c2 V2 Q( x1 P/ p6 i6 U+ k
  60. $ c. F4 ?( _& x6 [$ L1 I" j4 X& ?4 t
  61. void CAN_Init(void)
    / _4 w3 _; B* d
  62. {' V4 o$ ^$ C  ~- P. u) e
  63.     CAN_Filter_Config();5 V% e9 u' v6 Y( b  v  a5 [' Q# ^
  64.     HAL_CAN_Start(&hcan1);
    % L) s& c& E) O  q* o  S  D& ~: I
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断$ n# v5 |8 ~0 K+ e+ K  y
  66. }- U- Y* A& D$ t& z& Q5 O7 S$ }
  67. 5 m; F3 X" M' I" _
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)0 F, P! y  k& l" d9 U5 {
  69. {
    9 F; E* j# p* f2 G+ }' a. m9 M
  70.         static CAN_RxPacketTypeDef packet;
    ' d: u- g* F0 `2 u6 g2 C
  71.        
      J( {" b" t# {+ I7 z
  72.     // CAN数据接收
    ! l  B2 V+ P. P) C
  73.     if (canHandle->Instance == hcan1.Instance)
    - ^0 `( Q% t! J* E9 t
  74.     {; |! U4 J; _+ H2 V5 `6 J1 c9 @8 h
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    9 I* b. M# F3 k) M
  76.         {* t$ u2 \- X$ m! n
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");
    . ^, h, Y. R, E) z& _
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);
    : i4 u" F* _7 P0 p% o7 V6 |0 E: o
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    " q, u. p( j7 l/ D8 [
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);
    / L0 p/ {3 T( C& E/ ^
  81. //                        printf("DATA:");4 }; r, o( G. l7 q3 f# F9 z% g
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)
    7 `1 w3 O! @6 r9 `5 b
  83. //                        {
    , s$ c/ i  a5 s6 a# |
  84. //                                printf("0x%02X ", packet.payload[i]);- e& K& F, b2 n: l% x
  85. //                        }* I* T' v0 X% c5 {, W! v
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断& b. J% k" P. E% s! W
  87.         }3 I& Q; U: ^" d8 J* g7 T) w
  88.     }* v% t$ {% D0 ?' u+ {; n
  89. }. a8 G" l/ T& ]* [: Y
  90. 1 {$ o) q0 M+ P/ T% w( s  i0 u
  91.   `# ?$ U6 }# L6 M3 k. i
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    ) x* C2 q* ~, ~0 J/ D# V- e% T
  93. {% A- R4 `2 y& C. }, |- u
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)$ Y, c0 f2 O$ X& z7 g) [" v4 C
  95.                 return 1;  G! g; `! Z1 n6 }4 O" g' C
  96.         return 0;
    , `  C( K% f" \- k' ~
  97. }
    / U0 G2 D" R) W3 R

  98. % Q. s+ h5 G* Q0 h* k

  99. ) i2 o  |1 I: B; t9 {9 S( C
  100. CAN_TxHeaderTypeDef TxMeg;, N. Y# O% @4 F! l- e4 E( \% v+ L
  101. uint16_t TimsRepeat;! ~+ j6 K; ^3 y- W% t
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)% T  Y) m1 ?. k7 V" o
  103. {3 o5 {- t- j9 O: y- X2 h
  104.         uint16_t SendCNT=0;
    . e5 i! |* o  ?$ Q
  105.         uint32_t TxMailbox;% @9 i, x) B# T; y& T
  106.         HAL_StatusTypeDef        HAL_RetVal;
    % N' V, z& h/ Z% @
  107.        
    8 p/ k: F: ~2 n: y  ^
  108.         TxMeg.StdId = 0x321; //标准ID
    & h& X; v9 T6 |) s
  109. //        TxMeg.ExtId = 0x10F01234;/ Y, W8 C3 W' x3 _, @, Q
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型
    , g1 V& Q! F$ s/ u% {
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型
    2 h5 g" |/ y9 U3 {# E
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧3 p0 m1 L: H" v1 r
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧. h# K5 |1 [- e; J6 i9 u' G& {4 d
  114.         TxMeg.TransmitGlobalTime = DISABLE;0 V) J1 B! L1 k" h# M2 f
  115.         : k3 |' e7 f; b" U2 j4 l" l  A/ s
  116.         if(!__hcan || ! pData ||!Len) return 1;' S1 u& t# y6 r8 r5 k5 i5 d6 M' u, d

  117. 4 [" z( M; J2 r: B; D
  118.         TimsRepeat =Len/8+(Len%8?1:0);
    1 y8 y' W2 t, s- `" |, }7 ]9 n
  119.         while(TimsRepeat--)5 h0 S# R* K8 j
  120.         {
    / s- N& r" l9 I2 z5 N* N3 z; w
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);
    ) j7 f9 F1 L5 a
  122.                 if(TimsRepeat>0)1 m# ~  O7 z, J( Y5 U& j! M" P
  123.                 {       
    % c  o  Y: K* j4 S8 q
  124.                         TxMeg.DLC=8;
    - w; b' y" o8 l% V+ n: O
  125.                 }6 k4 W* f3 w1 o" ^* B: w' _
  126.                 else6 i7 i. G7 ^+ Z& T; X
  127.                 {/ ?3 h9 C2 b4 i9 A2 E
  128.                         if(Len%8)  Q# N) x# I/ p
  129.                         TxMeg.DLC=Len%8;7 R1 G6 t6 ~6 y* K# ^# \! o
  130.                 }
    6 N) i  v9 Z! c7 k% I$ q
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  
    4 Q9 T: i6 L: t* x) e% x$ Z
  132.                 if(HAL_RetVal!=HAL_OK)
    8 d) _7 c4 n6 p
  133.                 {2 {" s, b9 c6 v. Y" k1 A2 b
  134.                         return 0;
    ( t) l/ ], z1 f
  135.                 }
    - t6 q; N# c9 @
  136.                 SendCNT+=8;) p4 @0 c  \$ `8 ?
  137.         }) l7 h+ d* K0 u! m9 g
  138.         return 1;
复制代码

- k( y! p$ W5 K" w1 _9 O/ m: i9 Z

bsp_can.h

2 ^0 E: l* B1 L" y- o

  1. #ifndef _BSP_CAN_H9 k" D' H: _9 N: I- E$ O2 W
  2. #define _BSP_CAN_H
    ! Q3 m4 i- |9 @- ]1 ?
  3. #include "stm32f4xx_hal.h"2 z& w7 `% l- }- p& @$ G) n; H! u
  4. #include "can.h"' Y8 R$ R! P# x, o- K% b- Q

  5. : y6 A( k4 s; e% T6 [
  6. //typedef struct  l- v; d' r2 ^6 ^; j' g
  7. //{% n% g1 C# w; b8 A
  8. //        uint32_t mailbox;
    1 w4 b7 E7 h. r( I% K  o9 k. z
  9. //        CAN_TxHeaderTypeDef hdr;& N7 ^; G8 l! I3 B  c( @
  10. //        uint8_t payload[8];1 I% w2 n7 u6 E6 {! }6 A6 @+ W
  11. //}CAN_TxPacketTypeDef;
    3 m  P2 ^3 |5 n
  12. & P) t) r$ K, ^, ?: S
  13. typedef struct
    / F7 D5 D& y6 e' ^
  14. {+ k$ ?1 [% {# r
  15.         CAN_RxHeaderTypeDef hdr;
    / Z& h: t  i* R$ ^, }* c
  16.         uint8_t payload[8];- j: K/ I: W8 R# k+ S3 f: ^/ Q
  17. }CAN_RxPacketTypeDef;
    % |5 z; O( d- ]. \; n

  18. ; e- B4 w2 [. g# h! U# n

  19. 6 z9 b1 P1 D% K/ K* a
  20. void CAN_Init(void);; |1 \: R) B6 X: A- B9 j2 z( ?- }, v
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);% J; H( P) C! j" M) }& [# z
  22. #endif
复制代码

% g4 @6 M4 Q; G9 h3 ?

就可以工作了???非也' K! Y; b9 s! y. y, M
其实我发现还是有问题

2 ~% K2 z9 A6 x: z+ N8 Q

3_meitu_41.jpg
, h5 Y( H, c- u' m4 z% G

5 t: b9 K: H1 u% E% d& ]6 X% _, C7 h% s0 t. O
为什么第2 3包数据到最后去了?


* ?1 N1 Z6 V( O! o6 @

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

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


, W' X/ ^: _! w! i

查看库函数9 y9 o$ W9 p  D- ]+ A

( X9 D9 h. W; l

  1. /**8 r+ h$ ?, D# {$ R. z) N
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.$ C. V: m& x* W7 N1 G9 Q0 h
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains2 ]( T' |) B  E9 U
  4.   *         the configuration information for the specified CAN.' p; O, z; D0 ]  d7 |( v
  5.   * @retval Number of free Tx Mailboxes.5 k* Y5 c+ n2 \9 j
  6.   */
    0 {& \. ^5 C" i5 T' k2 @$ l& t
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)9 C1 x1 e6 Z) `  n/ t* o
  8. {
    ' C: A( J* s7 u& W$ O: P9 p
  9.   uint32_t freelevel = 0U;
    & \! M/ K5 \+ T* T6 [
  10.   HAL_CAN_StateTypeDef state = hcan->State;
    : J8 L7 {* w/ }5 k& w' E

  11. # ?8 U0 ^) F2 p0 r+ Z/ U3 H
  12.   if ((state == HAL_CAN_STATE_READY) ||& S( D. c$ Q, O0 G5 i4 v
  13.       (state == HAL_CAN_STATE_LISTENING))
    6 @$ e  }/ z' r- ]: i: ~- E  O
  14.   {% @4 c6 P, X5 d1 z3 [0 y2 k: I
  15.     /* Check Tx Mailbox 0 status */
    + d! `, t' J% C1 c, n# g
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)- O5 @* e" K. o5 {) D& e
  17.     {
    3 x- C% M+ S  J; Z) H
  18.       freelevel++;/ o/ `8 k2 W8 d* T( C
  19.     }
    1 ~5 f( U/ z4 f& p

  20. ! l" o/ P7 E# d4 M' X9 U- j
  21.     /* Check Tx Mailbox 1 status */
    5 o2 |' p& v! r
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U), m6 D! I8 y  N& X/ k3 ]3 k/ d6 Z
  23.     {) z* p* O: x6 P2 Y& O
  24.       freelevel++;
    8 H/ Q. \3 O" K; H+ X/ F! @+ R
  25.     }+ Z/ e, w8 M  L3 I. `' F) X, K

  26. " x' T4 c7 j" J9 C+ w+ p
  27.     /* Check Tx Mailbox 2 status */
    0 g; p( z1 E; k: y  l* W/ y
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    ' m4 x# j3 R+ s; q$ L* R5 V. N% o( k
  29.     {$ H, W" P6 N) I/ e
  30.       freelevel++;
    ) G6 G3 E2 f3 H6 k$ B
  31.     }) s* m* l+ w4 P! k! y: ]
  32.   }) i& [- a) G% n1 Q0 I( b, n4 |2 g

  33. " h! M; g- F% V: u
  34.   /* Return Tx Mailboxes free level */
    6 z' V1 q$ `4 A: q
  35.   return freelevel;
    $ M( e3 W8 V5 f4 n
  36. }
复制代码

5 J. h# v. r% P0 \. h

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


* o8 C3 k: G$ s( ?/ l# j

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)9 z  W, H; I0 S. s% ~
  2. {
      v" ^' u. o. V5 }  \: Y  Z
  3.   uint32_t freelevel = 0U;
    3 {+ x6 s" J5 m( ?& F
  4.   HAL_CAN_StateTypeDef state = hcan->State;
    / h# ^! y4 u4 h

  5. $ A. A4 w0 c* Z. w8 X5 V/ _' _
  6.   if ((state == HAL_CAN_STATE_READY) ||
    & k$ q$ K' \! @% K9 E5 S/ t8 Z
  7.       (state == HAL_CAN_STATE_LISTENING))
    ' K8 d- J* Y6 T# L
  8.   {
    $ v& T" J3 z1 ?- K9 y6 r
  9.                
    , m) ]+ s; W  z. h7 c) ?0 Y0 Z
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \8 J+ h- ?+ a% N" c7 D: s" c( N6 W5 @
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \9 T* ^+ T* P1 [4 u( ?5 C( g
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    ( H( B1 B3 n* w& l2 c: w
  13.     {
    9 k: ?3 R. U4 B
  14.       freelevel++;
    ' `8 K8 v0 d5 o% Q" m
  15.     }
    4 l% i$ Q! x. |& l: |8 m% L1 d) Z, E

  16. 2 d. ~- L! u$ v, h4 N+ @3 _* G6 n
  17.     /* Check Tx Mailbox 0 status */. p4 e( t4 f1 R& v/ x' _1 h" C/ u
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)* r$ u8 z; d% E; U( u% T. ^: ~
  19. //    {
    3 [2 Q. J3 i- x1 H$ D. b# Q$ |
  20. //      freelevel++;
    ' U& a3 p5 |* e
  21. //    }
    ) E' g. e7 u/ O; ^

  22. % G$ u9 D- y6 Q9 {. Y) ^! ~
  23.     /* Check Tx Mailbox 1 status */
    . @* W% ^) B" {: }$ w4 j
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)4 t3 D& K/ O+ j5 q. j7 q3 o
  25. //    {0 x7 t8 A' w: R
  26. //      freelevel++;
    8 i; _7 u2 e, y
  27. //    }
    ( c! C6 ^' B4 j* S" @& Q8 U

  28. 7 t+ c  f; ~1 `
  29. //    /* Check Tx Mailbox 2 status */7 F  L: U  a) J4 |: F! Y
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    2 O1 _+ h7 ]$ P
  31. //    {) J) w; E- O( j
  32. //      freelevel++;
    8 S/ r! y; P5 h/ o
  33. //    }, v+ d1 ?' _" `& i/ N* P  ^
  34.   }
    / X1 N' N3 D' z& f* R
  35. 7 S% [+ U' b5 Q6 E5 C3 B
  36.   /* Return Tx Mailboxes free level */. w1 }" Z4 Y# m' g3 K3 F
  37.   return freelevel;1 `- D7 u0 n) r) e6 D
  38. }
复制代码
  o. W. t$ m; E* N: T9 `9 d

4_meitu_42.jpg

9 m# t: F) G' ^( k
三 总结
% j$ w3 B+ D. C; a0 u

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


1 l. @8 J9 H8 V, t


: h, Q0 u  Z: C

四、CAN以及库函数分析# n+ ~5 ~5 ]9 S( e% S! f* D

CAN总线# n" W1 T: E) k
1、根据标示符(也就是 ID)来决定优先级的。8 M. U- Z. {  z  K) i/ R
2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)' X( ]2 p: X9 @. R  D* e
3、可通过发送“遥控帧” 请求其他单元发送数据。
8 c$ D# j9 `& \1 _9 w7 d* _# F% i4、CAN Model:

0 [0 _) E( P) z8 s
Normal 正常模式
  `3 u( @3 [( C% w7 TSilent 静默模式
# s, _3 G2 f- o5 bLoopback 环回模式 测试5 X  t) n- u" S) A! w; Z2 ?
Silent_loopback 静默换回模式 测试


/ Z. W3 n; T+ ?8 E. `8 [% ~5、波特率

6 P9 X6 F; H) N4 s: T7 F
波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)


) K5 H- V( Q2 W; \: ?3 e

6、发送数据结构体指针

  
  1. /**
    8 c4 d, O* B3 ^  v6 x+ K
  2.   * @brief  CAN Tx message header structure definition
    9 ~; W( y, |- p
  3.   */
    1 u: a; m9 M/ A6 `5 g
  4. typedef struct
    % D" ]' ]8 y* I
  5. {5 T5 ~7 c, o/ ^' g; k
  6. //表示标准的ID% y$ u% `0 I' f- ~
  7.   uint32_t StdId;    /*!< Specifies the standard identifier./ p! l" F$ Y: J3 ?* E  j
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */( {' y5 h" K- |. ]8 d
  9. //表示扩展的ID
    9 r. b7 a8 c# X3 p+ z
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.( `- F3 e; v5 C6 W' ]
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */# B! T1 h. J6 y% t9 a& C
  12. //要发送的是扩展帧还是标准帧7 m; w' D7 K- I1 @+ N
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.
    9 x* l, X1 p0 }) l+ b0 G3 X
  14.                           This parameter can be a value of @ref CAN_identifier_type */
    3 _" K, t. L; }9 I
  15. //表示发送的帧类型。如:数据帧、远程帧等, o& l8 M3 j" v. Y
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.1 U0 B! o6 W9 w1 Q1 L/ F# F$ {1 g
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */8 f- b% |! K/ T& l/ P/ n. ?
  18. //表示发送的数据长度/ E! A8 |. p, H! k9 U4 |4 z% a
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.* ]* Y2 U" a3 w
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
    - F: x& u3 @# }6 M* G) M8 N

  21. # I0 z! J3 `& B3 i5 k: c% P* j9 b
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start+ q% }' l/ H+ m- W5 ]  V# t- a
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].6 F, g. D1 m, P1 Q4 C/ z+ f
  24.                           @note: Time Triggered Communication Mode must be enabled.7 a% Z0 \! ~  ~) t" |0 m) H3 y: b; B
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
    : ?. @% z: P+ x- ]8 |
  26.                           This parameter can be set to ENABLE or DISABLE. */) @4 I) R  L# @9 P5 j# l7 o+ R) P

  27.   ^/ g6 R- o+ n/ _+ Q6 ?
  28. } CAN_TxHeaderTypeDef;
复制代码
. |" k# ~# r8 J1 N/ R- ^

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器& y5 }9 Y3 z, D! \
屏蔽模式# K5 Q4 @7 n# L  D% z) z5 R# ]# h
屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你
8 N9 X  L! s! H想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。
+ T0 Q  ?1 D, y6 N/ V' v- X6 V屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。

# x3 |7 o& Q0 r


- G3 O9 ]7 ?  J; |9 Z

8、过滤器结构体


+ z5 r$ P' l1 l2 R6 b* o$ }
$ x2 z: N: N3 T
  1. /**1 f) ]6 I* o) t9 R1 v" }" v  n
  2.   * @brief  CAN filter configuration structure definition9 t( l# z" ?8 j# f" T1 o  h# C
  3.   */
    + _( X; [) ^- f$ A. }
  4. typedef struct
    ! ~- A: N) w' y  A
  5. {: A: d3 \+ M4 V0 Z. p& Q: I, x
  6.         //这个是标示符寄存器的高 16 位0 O. `' s$ e9 m  `/ I
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit' P" N+ m6 ?; a8 Z
  8.                                        configuration, first one for a 16-bit configuration).
    0 N; z! ~8 v+ c" p4 z5 Z
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */1 q, N# f! d5 {, R: `
  10.         //这个是标示符寄存器的低 16 位
    7 _% \: I+ ~, I; _
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit" t( L; W, q- e. w
  12.                                        configuration, second one for a 16-bit configuration).
    & K2 v$ g. E  E6 i! r
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. *// S, V( @5 l" u* L7 R- S
  14.         //这个是屏蔽寄存器高字节的设置3 L2 K8 N( @1 m. _0 l) O) z4 A2 x6 l
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,2 F" {8 l! Z/ e) X9 u
  16.                                        according to the mode (MSBs for a 32-bit configuration,3 V1 J% H9 ]: d7 }) K
  17.                                        first one for a 16-bit configuration).' R$ |* a; J1 @2 N' W+ \' Y
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */) C3 U4 j' }  m9 `" A) l
  19.         //这个是屏蔽寄存器低字节的设置
    # [% |! ^, _" p
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    9 ^0 o) c# T' W
  21.                                        according to the mode (LSBs for a 32-bit configuration,
    ! Y: e9 b3 L0 o+ t7 E# V* U
  22.                                        second one for a 16-bit configuration).4 m; t( y, m" a
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    ; f# _7 \. V2 A& u: _/ ~5 B6 w
  24.         //选择你要使用的邮箱,它有 0 和 1
    9 Q! p+ g1 @0 z
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter./ B  H6 J: z) t- M5 h4 R& a( p1 `
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */
    1 Z0 j5 b! H9 r) B8 K5 }
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。 9 ^; D8 S% L4 f1 j4 x
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.
    ! U$ _9 \% b$ P: D" r9 i1 ~9 t( e
  29.                                        For single CAN instance(14 dedicated filter banks),
    7 Y# K& y/ c& D" A" l! }0 C: M
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.
    ! w5 M% a; C7 `6 r0 m
  31.                                        For dual CAN instances(28 filter banks shared),
    ; C8 |9 e. r& l; o7 E
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */. h  |& Z) \; U7 `1 v3 ^
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和
    * t! N2 J# x$ T9 N" Z
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :1 z' @2 T( G8 }! W, v+ w
  35. //CAN_FilterMode_IdMask。8 w4 H% y# {7 d% E/ ]( z
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.2 X$ A! `8 }: D% T' k7 l; S
  37.                                        This parameter can be a value of @ref CAN_filter_mode */
    . \# I7 N  [, D% r
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。" z' S/ R" q. E% R9 f6 k5 ?6 Y% N
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.  _) ]3 w9 O# S2 t2 [9 T
  40.                                        This parameter can be a value of @ref CAN_filter_scale */
    ' v' o3 l3 w7 E0 T1 H
  41. //表示过滤器的使能
    0 @) t+ [3 v( I% z) y9 |$ l
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.! V( a, q4 |' ^4 r$ K
  43.                                        This parameter can be a value of @ref CAN_filter_activation */
    ' v! s5 V8 `5 P" G$ c  [4 u
  44. # x- l1 k$ W% O0 p
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.( L6 f0 A. U0 A2 H, M
  46.                                        For single CAN instances, this parameter is meaningless.  B8 [- ]! s5 L' a/ T: [+ [% }
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master
    7 K* U/ {% o$ B
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave, N9 Q/ C( p8 N. n; Z6 h
  49.                                        CAN instance." @( M! q4 T3 g, n! [" Z7 j! e
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */( W3 k$ e& I2 C( m
  51. } CAN_FilterTypeDef;1 m9 R5 R. r+ t3 R2 S+ z/ Y
复制代码

! J# b% a) D& v+ s5 p/ p" ^: K* N7 [$ W( T% R! Z' |
2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

1个回答
yklstudent 回答时间:2020-9-29 08:29:13
不应该中断方式发送多包嘛
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版