请选择 进入手机版 | 继续访问电脑版

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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?5 x1 U- Z  u  Y4 s) M. f- P
2、发送多包数据,网上基本上就两种说发
, Y9 X6 W! {6 q9 }& [7 w*两个数据之间加延时
) G' E! @: r! M7 |) p* ^" |! F' H*查询邮箱是否满了
3 |7 |3 E6 M; K& d* ]5 L: BHAL_CAN_GetTxMailboxesFreeLevel()% q& G7 A' |+ M2 `+ S
对比上面两种方法,为了效率我们选择第二种

7 l0 O! E9 S* P" @% K8 J


) C' f/ H& [4 L- e1 g. c4 g

二、配置与代码# q& q; u* X, r5 K# U
( k8 h1 s+ U) g7 w4 k4 v

直接上cubemx配置


0 Z% I  ~! R; F% o* W1 s. C


: ], r2 s8 `( r$ c

1_meitu_39.jpg
- @4 b, ~2 C5 {! y
2_meitu_40.jpg
" w% S+ }. \  e

0 r0 f3 B( {2 D: U$ p5 E' a
% R) S6 O- Y. w直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下

& M6 t2 x3 ?' ~* Z$ Z7 U+ v) d

  1. int main(void)
    ( a$ i, O5 b; T6 e! F/ R- p9 K
  2. {5 R; c) k7 R1 A: ~' {+ k
  3.   /* USER CODE BEGIN 1 */
    $ |& B& a+ u6 c: w: U. ?) m
  4. + n, b4 j0 g/ ?
  5.   /* USER CODE END 1 */4 a/ j& V$ |2 y% H* R4 r
  6. ) h2 e7 x! g% t/ w4 K
  7.   /* MCU Configuration--------------------------------------------------------*/) `$ V7 j. J" ]; b, U

  8. 7 Y  E0 u2 V  i" t3 X2 P
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */& m4 z1 Y6 g0 G' x
  10.   HAL_Init();! a. k5 a' `5 K$ g2 Z
  11. 7 P# u% q9 d7 V' }+ \8 G
  12.   /* USER CODE BEGIN Init */* y3 J1 @( A- N$ T6 _* }

  13. 1 _% i7 D! H$ ]  M9 d& Q- f: t
  14.   /* USER CODE END Init */9 ]4 M& Y* P- Z6 p
  15. ' O! |* c9 Y1 l& j) G4 Y
  16.   /* Configure the system clock */
    ) }0 j6 j. k; ~+ _- U  x
  17.   SystemClock_Config();
    / G. x$ e" |: x' c. x+ s
  18.   v* E2 w% h7 T4 M' l
  19.   /* USER CODE BEGIN SysInit */" Y( o* d5 A7 }, E1 n# b

  20. / w$ }* x9 v1 e- O0 n! {
  21.   /* USER CODE END SysInit */
    " W" X. u; r8 q3 t' X  J
  22. " ?" q8 z# `9 D: J# ^% @, Z1 K
  23.   /* Initialize all configured peripherals */$ {0 S; j% ?" Y6 ^7 ]# _
  24.   MX_GPIO_Init();. ?& H7 ~, _/ |  O+ h) Z3 _
  25.   MX_CAN1_Init();5 c* {1 K2 G- Y- ~3 d9 g
  26.   /* USER CODE BEGIN 2 */' m6 U  ?  W% ?/ C8 l9 }' u/ S* a1 A
  27.         CAN_Init();4 ], N# G( U: j' Y& o( h
  28.   /* USER CODE END 2 */
    3 F& I8 Y3 e* v; I  S/ M6 O2 X

  29. 1 y/ l) @- |# L% M" _& r
  30.   /* Infinite loop */
    + |2 Y/ b5 k: E$ h. {; d5 [. |8 E
  31.   /* USER CODE BEGIN WHILE */* D, }) B, x! j% ~3 Y' W+ Y7 h( g  E
  32.   while (1)6 p1 Q* ~3 P, p
  33.   {9 w$ b- ~. h0 h( s+ h) b3 v
  34.     /* USER CODE END WHILE */& X. q9 P( U& H( t3 B# H0 ?
  35. , B" \7 W) g" I* y% I" i
  36.     /* USER CODE BEGIN 3 */
    % B( t5 c5 m6 z; Y* s- _' F
  37.                 uint8_t TxData[100] ;8 I. {+ Q/ u; w* y! L- r! n# O% ^
  38.                 for(uint8_t i=0;i<100;i++)! H8 D. i9 w4 w( i6 E& {
  39.                         TxData[i]=i;
    - H5 V: W/ r* g& p1 m* T
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));
    " A3 M) _) x& f& M
  41.                 HAL_Delay(100);
    ) `$ V! c: W, a; E$ v0 F! f
  42.   }8 M# C9 k% Z4 _( }- f* Z
  43.   /* USER CODE END 3 */
    : v  p1 I0 p, J
  44. }
复制代码
* ~; [5 X1 p+ u% q

bsp_can.c

' G6 W! R' p' |7 H4 h4 D
  1. #include "bsp_can.h"- i3 Y6 `+ ^# V' }. ^

  2. ) n* n3 ^6 r6 u4 u

  3. 1 P; j8 F  M" W$ t- q
  4. /// CAN过滤器寄存器位宽类型定义$ [, p8 D, h- P0 y( ?5 _: n
  5. typedef union0 J4 f8 N$ `% f7 y' ]1 X
  6. {! l7 e! k0 @7 F3 R7 I
  7.     __IO uint32_t value;( _. Z9 ]7 `! y& n8 A0 ]
  8.     struct( E0 l* _! M: `1 Q, m" S
  9.     {
    8 k* [0 s4 W( v/ Y/ `- J/ i3 j. W8 b
  10.         uint8_t REV : 1;                        ///< [0]    :未使用
    8 f, g. W$ X( t% J
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)- ~" l, z% e- E) z
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    + ?; k7 l+ K/ @* J
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID
      F4 o. {! K& {
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID6 e6 F! e2 Q6 s
  15.     } Sub;
    & c  u# g! e! R
  16. } CAN_FilterRegTypeDef;
    + m1 t  }$ E$ ^4 N/ c
  17. 8 c" q+ t3 I* T' p) |' d4 H& [

  18. 2 F$ U9 b; A5 a6 l; ]
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF& W7 P7 h  H7 b& u
  20. % Y* j: t  g& M6 I# G3 j( F
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式6 z7 J$ k' K# ]% |

  22. " C- H3 J" w1 P, w
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID
    - j8 |' i$ V# ?

  24. ) x% f. s9 h1 J8 x' L9 u  g
  25. void CAN_Filter_Config(void)( E8 n' i8 h- r- {* T3 x+ p3 Y
  26. {
    ; d' Q" I2 H) R
  27.     CAN_FilterTypeDef sFilterConfig;
    . I0 k2 o1 n) K4 u% t( R
  28.     CAN_FilterRegTypeDef IDH = {0};
    & c( g. V# k! a& B0 h
  29.     CAN_FilterRegTypeDef IDL = {0};+ U0 h6 L* ^  G. r) a0 u$ k

  30. * W3 o& ?1 `. {$ h2 ^1 t# T$ }
  31. #if CAN_ID_TYPE_STD_ENABLE
    0 O: j* C# \% i8 w/ I
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
    / t5 a! Z7 O; {- e: ?( o( Q( L
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位# Q# V+ f9 d" Y7 ~, ~. k* U
  34. #else: R! e8 L) T- s( U0 j4 \2 L
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位8 h# I. s( i2 a6 s+ I( L% z% v
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位
    . A. N) \9 i+ O, Q2 M
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
    $ U: m" \2 U4 s; S" I5 }- W9 o
  38. #endif
    . \8 i0 l4 W7 Y  p
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号0 j) t. O- Q- _( V( O4 N; M
  40. #if CAN_FILTER_MODE_MASK_ENABLE- A% H3 Z' u: I, J2 N! d5 g
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式0 U- |2 m$ u& X& h2 I" t. e
  42. #else
    / F6 S. T5 \% J4 o9 L
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    8 ?& [' @+ h% w4 Q2 R. S8 C" Y# V
  44. #endif
    " H# s, ~4 X) H* k4 r
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽
    9 o: }# g' ?7 P; F6 E3 m
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    * A: [6 x1 ^) X0 y( u( y" \
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位/ d3 H" F# l4 P& S
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    + J$ P7 [3 i7 _* N
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位+ X# ^3 I& I3 U: L8 F; \% R
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0
    . K( ~' D6 ^" E8 L& \1 T
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器1 ~. ]- N: N0 Y# U: R, E
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效
    ' \8 J! r" s- C! @
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK). I$ N8 ~' C2 |* [, }' b. u9 N
  54.     {
    " M% z) I' A9 c  Q% _% y6 o
  55.         Error_Handler();9 c  S* Q8 o; u. W4 S: B
  56.     }
    ' q3 `& {7 u8 f; Z0 B
  57. }0 l" Z" _. w! C' S9 Z# A' M

  58. , G: X$ C) P/ V0 j& Z, `! y" n
  59. , r; J, e* b# f7 o0 w  D$ d

  60. 5 l- n9 P2 |' R4 h: h# {8 V; Z
  61. void CAN_Init(void)/ I. r8 S& r- B. M
  62. {
    9 \8 O0 e2 u/ O, C* T
  63.     CAN_Filter_Config();2 F; b8 H, b) y# x) [
  64.     HAL_CAN_Start(&hcan1);# X! Z! \7 K: i
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断* l5 v3 |& k) W
  66. }( ]# L* n) f4 `% y3 c
  67. ; g6 W2 i0 b3 D  f2 ~
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)
    ) N' k9 i* u1 ^8 l) J% I
  69. {
    ' D* |# C' L) H. F
  70.         static CAN_RxPacketTypeDef packet;' X! G* c% I2 s; F  q" {" x4 w
  71.         7 ^- I" a- y4 O2 I4 V
  72.     // CAN数据接收8 ~6 L+ r9 ?6 B( N0 Z! @4 ^4 g: V' s8 h
  73.     if (canHandle->Instance == hcan1.Instance)
    * z$ v( w) c% x9 F8 x0 c
  74.     {
    # F/ X  c& e. t8 ]
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    8 y0 ^, U) J8 i- L
  76.         {/ l7 ]1 M# B' h: w4 m7 u. w
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");
    1 ?+ G+ \7 A, N) Q; A
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);
    1 U, ^' b( \6 z, @( `: S
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    / A5 o9 F% j) _
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);
    % b1 V! }# w* w
  81. //                        printf("DATA:");
    . s( M+ p; o" P( U0 F8 ?
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)3 V6 K* J: h/ u, J3 ~! \
  83. //                        {/ @, y/ @; a3 {& K7 d  ^2 Y
  84. //                                printf("0x%02X ", packet.payload[i]);
    $ w% G  J0 x2 |, D. s# a
  85. //                        }( a/ z3 Y# M* T7 \2 O9 x  k
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断5 ^, y3 X( Y0 v
  87.         }
    $ c* V$ Y" c6 x3 R: z) {  {4 ]+ s
  88.     }8 y/ J! p& `! `5 W2 `
  89. }
    2 j" d& A$ Z8 G  P. z; q5 f6 G8 L1 w+ v' ]
  90. , k# _. c# [2 r9 H% C  D
  91. 8 n$ e8 @1 r7 z( \3 S, `. i! t4 k; F
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    1 O7 D* d7 E9 i# g, t
  93. {
    ( e& `$ E1 X# }- n' D
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
    6 w' g, A6 y) @" D
  95.                 return 1;
    : t4 V4 c6 U, _
  96.         return 0;1 m( @# P  \8 m
  97. }
      a' j& U1 v7 x! Q( z

  98. & Q  ~( r' ]1 f$ S7 Y
  99. / v( O3 z$ o& w; y5 f" T4 |% W
  100. CAN_TxHeaderTypeDef TxMeg;
    , Q. `& r, k3 x
  101. uint16_t TimsRepeat;; |& D* E2 x; N: \. z1 u8 c
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)
    $ ]) U. V5 a, u# K- _: D0 S
  103. {: {0 C* A+ z+ j6 f1 |$ g: q
  104.         uint16_t SendCNT=0;+ T5 L* ^) c1 K( _
  105.         uint32_t TxMailbox;
    7 P- V/ L$ N2 J# Z8 q5 [0 n
  106.         HAL_StatusTypeDef        HAL_RetVal;
    ; W: n8 g2 T( [) w& v
  107.         5 t  \! h! x! v) O, K5 J
  108.         TxMeg.StdId = 0x321; //标准ID( |% H- W. M3 K7 H3 k! d
  109. //        TxMeg.ExtId = 0x10F01234;
    % m: H. e7 ~2 I0 D0 l6 {1 k- P
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型) Y* ?: g: g9 h
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型+ `# w( q& ?2 V# t+ @  M
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧
    5 P& v4 v: @; `/ _' A
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧
    ; }& G" s; |+ f9 [+ Q
  114.         TxMeg.TransmitGlobalTime = DISABLE;9 b- K% G8 I3 `
  115.         ; k, E- `5 ], R
  116.         if(!__hcan || ! pData ||!Len) return 1;& f5 Q$ w% {1 g9 S  p

  117. ) e" `" u" V6 r! L6 U9 y
  118.         TimsRepeat =Len/8+(Len%8?1:0);2 x# D2 Y! T5 B6 {5 _4 U
  119.         while(TimsRepeat--)
    , Q+ u1 g) @" O9 L
  120.         {4 _* b+ O5 u, \4 D  K5 W: a
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);6 f! e2 R( j' w
  122.                 if(TimsRepeat>0)
    ( ?, ^" F% Z! u# |3 j$ n2 T
  123.                 {        5 J. J& m: b& e* S
  124.                         TxMeg.DLC=8;% p- a& B& v1 W$ D( o0 D' z
  125.                 }2 D1 O/ b3 W1 e* [& R+ b
  126.                 else" L% y$ B6 @, j
  127.                 {' |( e2 u& h% Y/ r6 [5 }+ M
  128.                         if(Len%8)! P0 J9 ]3 [0 |7 Y
  129.                         TxMeg.DLC=Len%8;  i" W9 N0 s- }! D! x: T2 e% l
  130.                 }
    ! B" H2 o# ^+ t8 h
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  6 a+ b- Z) d7 q- F7 a% S% z
  132.                 if(HAL_RetVal!=HAL_OK)
    0 R. k# T& Z3 F- R# [5 K
  133.                 {
    1 W9 G- h# F. r; e3 D6 n
  134.                         return 0;
    - r- p8 t& e& f2 X. E6 |5 [" l
  135.                 }
    1 h3 ^/ q- [0 `, J$ p2 F
  136.                 SendCNT+=8;, e& Z. j( l9 ?* q
  137.         }
    2 q/ _, w3 b! ~
  138.         return 1;
复制代码
0 w; j5 @; c+ l5 }% Z

5 H6 g) s3 R; R! w8 J1 z% K3 G

bsp_can.h

8 V1 N) I; Q% p# x8 i4 ^  ?

  1. #ifndef _BSP_CAN_H
    ) Z7 P0 N8 {& p* F) a6 |$ {
  2. #define _BSP_CAN_H' \7 c' [: l. T% d$ Q' U
  3. #include "stm32f4xx_hal.h", C4 @% b2 L. ]
  4. #include "can.h"% H  z3 I7 n1 ?% y9 V, ^
  5. 9 I' T5 f! E2 S  ]$ N  a, W
  6. //typedef struct
    * T. h0 }( O* L: j3 k
  7. //{
    ; K4 N% h1 Y1 V3 _. ]; ^" O: H
  8. //        uint32_t mailbox;4 |, v% A: y( ^# c& y! E
  9. //        CAN_TxHeaderTypeDef hdr;
    ; T8 ~4 K+ n+ X& N; }
  10. //        uint8_t payload[8];4 f" R% n7 L8 Y/ E8 @8 `8 L
  11. //}CAN_TxPacketTypeDef;
    ) D# X% Z3 ~) \6 Y7 J2 I
  12. 8 ~5 @( a, d- Q4 Z, R# |- M/ e, h
  13. typedef struct
    ) V: q  F( s8 P, S. A2 b
  14. {
    ; a1 t* W. j' m5 a8 u9 t6 p
  15.         CAN_RxHeaderTypeDef hdr;
      z. h3 h: C, Y5 R0 F- M+ \, n
  16.         uint8_t payload[8];
    , d) M7 W7 y& i( B
  17. }CAN_RxPacketTypeDef;8 k; ^6 Y$ `# l. w0 y8 Z/ d
  18. 0 t& {1 e. V( y; M: E0 e
  19. , ?# I9 g, q& Z
  20. void CAN_Init(void);( {% V/ c2 K0 P  t% k8 M
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);0 c& W" |4 p9 s( [# v+ p
  22. #endif
复制代码
* u) o9 ^2 p$ g3 l

就可以工作了???非也& ]1 ]) _5 F+ ?! g' k
其实我发现还是有问题

7 G1 T! Q' L( j7 x

3_meitu_41.jpg

4 K' l2 E+ H) [/ W
; B1 @+ X- f) c1 I! P- J7 h! d  H) S. w( I0 @( ?( R
为什么第2 3包数据到最后去了?


( R+ \, x* E) j+ a# d

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

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

# u+ y/ g' b$ ]

查看库函数
; I1 d: o3 P% ~0 T" r8 V4 P

0 c1 S4 L3 X" J: i1 w: n4 E1 w$ {

  1. /**
    / X& W! Q( A" m/ [
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    1 c% J7 L2 n& O
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains; ?* z; J. d1 n7 }  u) v$ f" N# q
  4.   *         the configuration information for the specified CAN.
    # |$ Y! n# L3 n" k# h1 z2 X) r# T
  5.   * @retval Number of free Tx Mailboxes.
    4 D: p1 C2 Q$ N9 q, [/ y
  6.   */: e8 D( q4 ?0 G% d
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    3 }$ y7 H& b' \  y
  8. {: }* d. j6 k" `: K7 ?. U
  9.   uint32_t freelevel = 0U;" l/ ]7 L/ r* w7 Q+ @. k0 i+ D
  10.   HAL_CAN_StateTypeDef state = hcan->State;
    7 n2 o3 f) Q" J: B0 S0 x8 ^
  11. 0 i) v" M8 D  W1 a2 a% H4 h
  12.   if ((state == HAL_CAN_STATE_READY) ||
    0 @+ @4 @% w  }  R
  13.       (state == HAL_CAN_STATE_LISTENING))
    0 F4 I6 k% }' _' `  y
  14.   {% N: {' `; S- A0 f6 P( D" b
  15.     /* Check Tx Mailbox 0 status */
    ( ^( i. }4 ^  r3 }3 e
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)/ \' t3 G6 V: w, E9 a. l# G
  17.     {
    # i* v' e+ Q2 \: A4 q
  18.       freelevel++;& {: I0 B1 R! c8 m1 _2 Z4 N6 ]. A9 l0 b
  19.     }
    % a; Y. P. \- i6 L
  20. 3 C( x* v  y0 T5 u" r! O
  21.     /* Check Tx Mailbox 1 status */  G7 W- {2 _: F
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    $ Y- b; N3 d1 u" _4 `% }
  23.     {% h" K( W* H6 f, B2 X0 V1 M
  24.       freelevel++;
    6 X! N4 y9 Y# Q
  25.     }
    ( Q9 }, O. p' W. Y' L4 \0 u
  26. + W) t1 z- f/ o+ \
  27.     /* Check Tx Mailbox 2 status */
    / f6 T7 D$ o9 x. |! Z  V7 }% D! W
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)! |" C5 S% c- w0 Y
  29.     {' p0 y1 q2 n& D) I4 H7 P; f
  30.       freelevel++;
    ! A# F0 Q, r% |  M0 y* p6 z" b8 M2 k
  31.     }
    3 Z: B# [3 s5 S3 A7 B  A& y
  32.   }
    : m/ Z" g( a: r0 ?' V
  33. . q+ }7 e& {0 S5 ^' o
  34.   /* Return Tx Mailboxes free level */2 p# Z% J; v# B) G) j
  35.   return freelevel;6 l$ |. c( G, G7 \
  36. }
复制代码
4 i- _4 w  {$ _( f" L

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

: d3 C% q* C$ l

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    4 l; G, W7 l3 D- P3 C
  2. {' w! s1 G2 ^! e, l
  3.   uint32_t freelevel = 0U;6 q; ~7 n+ E$ f" y" f" K( u
  4.   HAL_CAN_StateTypeDef state = hcan->State;+ ?& B3 J/ s5 S  ~$ {7 m
  5. / A5 n5 q, l0 c) L) A5 n
  6.   if ((state == HAL_CAN_STATE_READY) ||
      F" x9 w2 V" V, N0 U: z  x7 X
  7.       (state == HAL_CAN_STATE_LISTENING))6 `+ ^. i9 K( Z1 U0 Q6 p) Y% r" U
  8.   {" o/ E! \! N4 i% [4 w3 o
  9.                
    , n. t! |2 v1 U; |
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \
    + p1 @2 }# r/ O' k" x1 ]) C/ V8 p
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \
    0 r: a& I6 g7 y% Y% m, S3 H) w
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)1 g  _7 c* z: u2 E- I& o2 d
  13.     {
    - n# c; r3 L) C9 a5 _$ m
  14.       freelevel++;) s0 L4 ], Z, W9 y# ?1 D' t
  15.     }! [7 L3 T- ]6 n& s' z

  16. 2 R% X. l: Z( N3 r" e4 \6 e
  17.     /* Check Tx Mailbox 0 status */- v; r5 a9 w* _
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    5 W9 ?! u7 v4 A, \) O3 n
  19. //    {( U% g6 K6 k- w3 u. s0 d4 V
  20. //      freelevel++;
    9 T7 U, I1 P9 {0 A6 _) \; g
  21. //    }
    3 v0 ^0 `- O- H' V" @

  22. ( c- K/ V6 u  T- X) p1 c
  23.     /* Check Tx Mailbox 1 status */# z) |* X! N7 }! h, _8 ^
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)2 L$ q$ g8 B/ \, z% |
  25. //    {+ A  K" d# T- u  x6 }8 @8 M4 @$ c( `
  26. //      freelevel++;
    % I) {% \$ }1 `, j8 B0 _7 E; ]# g/ Z# k
  27. //    }3 c/ k5 M6 K8 N% l
  28. # v: y) `: o  E4 W
  29. //    /* Check Tx Mailbox 2 status */6 W! M" K8 W+ o
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)1 ]1 t/ |+ A/ L% p4 C  v( E
  31. //    {4 O4 v) u# Y, T/ j, |2 s/ _
  32. //      freelevel++;- X. y5 i/ `9 o4 D8 z8 ~! P' t/ F
  33. //    }
    9 s5 B1 h( R# Q* l3 l2 r6 e
  34.   }3 e8 I2 E/ `) E2 T" O/ D- d2 I
  35. 0 M% M1 _! F& M/ _; o+ Z6 L: c* a6 y
  36.   /* Return Tx Mailboxes free level */: \" U+ r: C9 N3 \! a) v! `
  37.   return freelevel;% O, N1 F7 p2 r3 X7 c6 ?; M
  38. }
复制代码

) n# i+ @: h$ ?

4_meitu_42.jpg

" _% c9 [9 T: M3 j) p- I7 |
三 总结' Z" [' q1 j0 ~( S9 K

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


1 Q; `! N0 T0 k1 z


+ m! {3 u) o# T: X+ @

四、CAN以及库函数分析
6 g+ S' R& _$ _8 @

CAN总线
/ t* K- J0 A: \$ B. f( y1、根据标示符(也就是 ID)来决定优先级的。
0 u2 O3 u8 V' z: \) m2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)5 D9 y9 {8 @/ Y1 \) K; V8 l% J  o
3、可通过发送“遥控帧” 请求其他单元发送数据。
" x4 g) _& S/ u8 M6 T4、CAN Model:


* f/ ~3 r, z" s( e2 kNormal 正常模式
1 G' N, x3 X# H: j7 {* JSilent 静默模式
0 j% `3 \! n4 z6 @Loopback 环回模式 测试
( C* j7 Y# |4 S" O. qSilent_loopback 静默换回模式 测试


3 ]/ h* c- {+ G' X+ y: H" G; I5、波特率


2 x) y6 p, q5 z4 M& A& q波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)

  _, D9 J; h# N$ z

6、发送数据结构体指针

  
  1. /**
    . T1 x& E8 ?6 Z) Y
  2.   * @brief  CAN Tx message header structure definition" Y) m, q/ k- f5 w, t
  3.   */
    5 {+ V) w6 v" h8 T6 g' Q
  4. typedef struct
    / E9 S* J/ z; Y: B. I/ C2 s
  5. {- [! j; T- X9 {9 b% U. h1 h, N
  6. //表示标准的ID4 f! ?: X7 w' e
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.
    $ N/ H1 X* K" |
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
    % t* @5 ~, N$ B5 m& S! D1 V5 D
  9. //表示扩展的ID1 s4 D7 @% s9 o6 J* H
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.3 q0 i! ^7 _- F7 s" v
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */. {5 J$ y9 d! N# u
  12. //要发送的是扩展帧还是标准帧* s7 ^" l/ s$ c2 ^8 |7 d
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.! n- X% Z2 K- n
  14.                           This parameter can be a value of @ref CAN_identifier_type */
      P3 C( g# X/ A% k6 S! l5 J3 p- ], v
  15. //表示发送的帧类型。如:数据帧、远程帧等; {; b' d, v# b
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
    ( C3 c: y# b$ @3 s3 T
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */3 p" o0 p0 n. k3 _8 I
  18. //表示发送的数据长度
    , m& \; f( [+ L. m1 A
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
    5 U; @$ l1 z/ G% S& P
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
    4 r3 O  N- J% G4 q

  21. 4 A4 e) W- j7 k+ O
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
    * M( M8 g+ {) O* F
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].! Q: y% S  ]* P; G( `! C
  24.                           @note: Time Triggered Communication Mode must be enabled.
    8 ?, ]& L! v! \9 _' {  b* S! t0 _
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.: ^4 s- M/ _* i
  26.                           This parameter can be set to ENABLE or DISABLE. */
    0 P: a4 ]  Q9 A6 A  A1 f
  27.   L# F3 b. C7 A
  28. } CAN_TxHeaderTypeDef;
复制代码

: R0 {# q: E! {6 {* p! U: k

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器
4 a- y6 Z5 i. C, y屏蔽模式# M4 M3 G' `5 h% n+ i
屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你
* _2 W+ X& S% f6 w+ _, w想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。
1 W% n2 v6 |* |# z6 g, }/ N4 f屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。

. n8 C5 p8 h! p* e$ p/ V4 H, Y

9 M% ?; W5 P0 b  M2 O

8、过滤器结构体

. A3 B$ c& u- I" o
1 d7 j/ V# e2 S  m6 {( C$ I  ?# v
  1. /**( ?$ T- m% z0 a' H
  2.   * @brief  CAN filter configuration structure definition
    / I  ?: }: ]" u( j6 V% \! L1 N! V
  3.   */( G4 t# Q6 t1 \3 `; P! @  ?. o
  4. typedef struct
    ; R3 d; r/ O: V7 }- D  c5 i; \: a
  5. {4 l" Y  r6 T. W! W: H  P# s
  6.         //这个是标示符寄存器的高 16 位2 n" R9 x# j; r. Q/ U' Y+ ?
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit
    & N+ i4 z. F/ o  f, ?
  8.                                        configuration, first one for a 16-bit configuration).: H) k; H9 j& m
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    " E- @- E( E) |5 F  b
  10.         //这个是标示符寄存器的低 16 位
    # w$ G/ E9 E7 j1 N9 _
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit7 t. B6 o; W1 m& t$ n
  12.                                        configuration, second one for a 16-bit configuration).
    - c- r- {& W5 m. q
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. *// a8 \# S1 y' @, N. f( L: K5 G$ t: k
  14.         //这个是屏蔽寄存器高字节的设置1 o* T& e" s" Z0 ?) [
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,
    * T& u' b: S) R
  16.                                        according to the mode (MSBs for a 32-bit configuration,
    : [7 U- P1 n+ d" N* S9 }; \
  17.                                        first one for a 16-bit configuration).5 d/ M/ v( _3 P1 o, e
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */1 |1 \& O+ q$ I: @* s% [! ]: {- K+ J
  19.         //这个是屏蔽寄存器低字节的设置+ J  h. R% m9 Z) k# A# G
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    2 w+ s0 _. Q& V3 \
  21.                                        according to the mode (LSBs for a 32-bit configuration,
    ; m" a# k! U1 r  z$ U( L
  22.                                        second one for a 16-bit configuration).
    . E) T9 r7 N6 K  v% f* Q* a! C
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */2 F0 @$ i+ X( k5 n7 q' s
  24.         //选择你要使用的邮箱,它有 0 和 1
    3 Q8 z5 K: v4 U, e- |+ q- l
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
    ! J7 t+ W! C9 G1 H( q1 k' v3 I
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */8 F7 `' k7 x3 O$ Q$ O1 i6 \& J9 B
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。
    / l( @- F7 W# N& c% n' \
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.
    4 ^( S8 x6 ^# [* n7 g
  29.                                        For single CAN instance(14 dedicated filter banks),
    # J, R  }: j  P! x
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.# ~! i/ P8 T; J
  31.                                        For dual CAN instances(28 filter banks shared),
    6 D' Z/ H5 B0 i3 ~
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */& Y3 }6 g' w; O) H5 }$ u' O: U- k( [
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和
    ; T3 X* z8 N1 Q( a& A0 K
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :# o0 E, `% m, S/ t
  35. //CAN_FilterMode_IdMask。
    & {$ R* _# T; h3 k: x7 C
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.0 [; _; h* L" g' C+ D+ R7 ^
  37.                                        This parameter can be a value of @ref CAN_filter_mode */" |( I2 F6 L, ^4 v' k- Q. P
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。
    + B0 @' [" q- f% c, F) m
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.8 d- D0 p3 K5 ^  X
  40.                                        This parameter can be a value of @ref CAN_filter_scale */
    , \! Y! P* x$ o9 z6 o* g
  41. //表示过滤器的使能1 b  |* Z6 ?3 ^. B/ {" J& O& U
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.
    + Q( J! M0 L5 ^$ D& J
  43.                                        This parameter can be a value of @ref CAN_filter_activation */
    : a" M9 @: T0 l6 _0 c0 G: r

  44. 8 L% U+ a$ G: @6 _
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
    - P: d0 K7 {1 k/ M) u. j1 |5 w
  46.                                        For single CAN instances, this parameter is meaningless.; B( v9 @0 [* A
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master7 Y( D" o6 s7 x' f3 B5 ?/ \
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave
    $ G- c$ m# r" \9 _, s) w
  49.                                        CAN instance.
    # X: r( D6 P2 v/ F
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */6 r9 A1 d: M  N' K( l9 D7 K
  51. } CAN_FilterTypeDef;# z5 R8 _7 t' e. [) B- f" @2 c
复制代码
) p! z% L8 q( c- B

0 D: z% ~6 n6 ^. P
2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

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