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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?
- J; U0 h0 A! v" @" x. O5 j: k6 ?2、发送多包数据,网上基本上就两种说发
# N% j+ j; A" o" }9 m- p*两个数据之间加延时% `/ O2 O3 L# p# V( }; r. N  K
*查询邮箱是否满了
9 a5 d8 b8 Z- J. G1 n! IHAL_CAN_GetTxMailboxesFreeLevel()) P, [7 ^: j' e' Y$ c' Z
对比上面两种方法,为了效率我们选择第二种

6 n$ B8 |  M6 w, q& m  N5 D, z

( ]. S% u4 N. f# _1 G) J; `: i& B9 k

二、配置与代码9 X( Q% |! J/ f3 N+ q- q$ A! w
# d5 l. C8 `+ i- J1 y. q

直接上cubemx配置


( Q4 L9 p& M% Y. z. F: H# o

5 `0 @8 B2 g8 C# u

1_meitu_39.jpg
0 V: T* f2 |; h0 ]' V( y( C# n
2_meitu_40.jpg
  n7 `$ C# _( o3 W' l

2 j4 T5 v# k1 M, B+ M2 X3 y. G9 j& \- b
直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下

0 V( l! h0 ~$ [

  1. int main(void), w  \7 Z2 U7 J. ?% l7 B; H% N
  2. {# T5 \5 g/ @/ v; Q& ]3 K$ `
  3.   /* USER CODE BEGIN 1 */- E, T5 h  j: u: v% z
  4. & m3 {9 h+ V# F0 F+ N
  5.   /* USER CODE END 1 */
    * ^* n5 j7 s0 \2 M
  6. 4 t' K- u, O/ y' t6 w% C( ?
  7.   /* MCU Configuration--------------------------------------------------------*/9 r& S0 N6 y* h) ~- A4 l
  8. : W: O% l  J. B2 g, F: _* F3 M: ]
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    $ O* T* }) w0 R+ R: t
  10.   HAL_Init();
    / `$ r- z% F& s9 J

  11. 0 z1 g& r# V+ l5 m2 f$ f' A! z
  12.   /* USER CODE BEGIN Init */( E5 ^3 C( c+ t$ E% G

  13. * r" b3 x( }9 d; H6 K& U
  14.   /* USER CODE END Init */
    % p8 p4 e- v- P" P6 I% L3 ~3 I5 U

  15. ; I# X2 M5 G( z" u0 e
  16.   /* Configure the system clock */
    ! s- F; @1 p. p- ~& [9 U3 D
  17.   SystemClock_Config();
    5 d6 m4 z; r5 k' |3 t* w7 {

  18. 3 W8 f; _& s3 W: Z7 t% f
  19.   /* USER CODE BEGIN SysInit */
    ! [/ ]- T2 n) W( H$ y6 |
  20. , G; |/ L' H( o$ Q+ s& o5 G* n
  21.   /* USER CODE END SysInit *// \# t  Y9 g1 g& {# ~

  22. & N* [1 ^" X9 c/ f# ^9 W3 A: T
  23.   /* Initialize all configured peripherals */
    : F* \0 e' @1 G' [/ w
  24.   MX_GPIO_Init();
    ) m- [" R) r! v8 m
  25.   MX_CAN1_Init();; V0 A+ e1 |6 h- u- F& O3 E+ b
  26.   /* USER CODE BEGIN 2 */$ T; U& _) O( q+ ]! `! Y7 }/ i
  27.         CAN_Init();# \# H- M+ v. t; u4 T: {$ }
  28.   /* USER CODE END 2 */
    # E! d" W0 J- o+ [2 c6 M4 B+ a

  29. & P* Q1 k8 {8 `
  30.   /* Infinite loop */
    7 y) o" p$ B0 Q# s* i) ?
  31.   /* USER CODE BEGIN WHILE */2 u+ C5 X% e1 X4 _; n
  32.   while (1)9 w0 u/ F: A/ Z# N( d8 h) j- j
  33.   {
    $ j4 ]+ K$ d3 I: l
  34.     /* USER CODE END WHILE */
    7 U$ _0 C8 D  M! T% X

  35. 1 A8 ?+ G6 M4 W+ N
  36.     /* USER CODE BEGIN 3 */
    ! W( X, ]; ^3 Y
  37.                 uint8_t TxData[100] ;6 }+ C: \$ m6 @1 ^
  38.                 for(uint8_t i=0;i<100;i++)3 V2 n; @% Z& e. E& f0 M
  39.                         TxData[i]=i;% [1 I9 Y% J$ B% V3 a
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));
    " [* r' `1 i3 O
  41.                 HAL_Delay(100);- t; C" K" a8 Q: F8 v
  42.   }- P4 s4 p! Q, O* T7 J1 t: l
  43.   /* USER CODE END 3 */
    7 {2 D7 C7 Y" k5 f  Q
  44. }
复制代码

8 _) m9 u4 v) r

bsp_can.c

$ t, ^; Z6 p' C2 I
  1. #include "bsp_can.h", J1 N: u/ j/ g, ^8 z

  2. 8 v) N& q" }; q* d5 z
  3. 8 Z3 q, ^1 A5 y/ n
  4. /// CAN过滤器寄存器位宽类型定义
    8 q1 n6 B8 ]; E9 T: T
  5. typedef union' r! s, S5 p2 R8 W0 G2 [6 B5 ?
  6. {0 O' b( H* ], s) H/ N/ H
  7.     __IO uint32_t value;
    8 `6 Y; t2 i1 m/ o) D
  8.     struct0 V& F  F. `4 |0 H
  9.     {+ |; H7 D; p/ o# k8 e4 j
  10.         uint8_t REV : 1;                        ///< [0]    :未使用
    4 [( P' J9 @* L
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)' F6 E* [9 @0 J* f3 }. R2 _, W
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)2 X* B7 K) Y3 a' H$ U2 a" R, \
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID; V+ _4 x8 |/ Y! X
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID; B: L3 d: w. P2 w1 c
  15.     } Sub;
    9 x: v' b5 b  X4 s: j2 ]
  16. } CAN_FilterRegTypeDef;
    " r: L# z5 e  @

  17. + W0 J5 v' ]: [5 ]8 x, A. }
  18. ( f1 l  Q6 k5 T6 v  o' |
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF
    , C% T+ e* N: M3 R- u# x
  20. 9 }% w# }+ I9 \5 D6 S9 _2 n+ t
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式
    * r" n9 F% d1 O) q/ A6 i/ P: v
  22. 8 E& H/ H3 A7 i1 a  b3 Q
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID
    . R# l4 ~8 p% m% ?! T2 z. F- v8 j

  24. ! O( T1 ^" Z4 V4 R9 i0 |# S' w& E
  25. void CAN_Filter_Config(void)
    ; Z/ t$ `( r8 g  p
  26. {* a' X, z) y4 n5 {' Z1 l
  27.     CAN_FilterTypeDef sFilterConfig;' u3 z. C4 Y; ^! [
  28.     CAN_FilterRegTypeDef IDH = {0};
    & Z* x1 I, u  L' _, [' F$ Q
  29.     CAN_FilterRegTypeDef IDL = {0};1 S1 B- m* a% T% r3 _" p

  30. $ r; G$ H& m, C# |9 L8 d
  31. #if CAN_ID_TYPE_STD_ENABLE# S" c+ W. @; [5 l- `) L
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
    * A- Y8 D! \& [$ t# H7 f  s
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位# w. o, X, I9 w5 }
  34. #else3 ]' S; [; _2 }. j; m
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位2 o5 R1 k( `: X: ?" ?* F& R
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位
    4 S: \( P5 q* {
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位" W5 ]4 J+ z$ ^; v2 A
  38. #endif. d4 S4 i. L8 c3 ?6 Z* S4 D" R" O
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号
    6 [- q$ U! x4 B6 M& _; v# c: y/ @
  40. #if CAN_FILTER_MODE_MASK_ENABLE
    1 y6 k: G4 t/ r' E
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式% z  c& b6 b, @% ^+ R( x
  42. #else5 s9 i$ S: l$ J2 o# I# f3 R) S
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式5 c6 L0 }- m+ G& p2 s/ }1 s- @
  44. #endif- ~. j; P- Y& x7 ~0 A; f1 ]  k
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽
    ; K4 d+ s% W0 t7 n3 X3 `$ j
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
    * W# U( [3 R  ~1 h" {+ ]7 [
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位
    : z4 m# l1 s9 v4 m6 D% A4 [7 S, c4 k
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位
    . f6 ^; l$ l0 {/ k
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位2 k5 u0 t  V0 ~" y+ {: h5 g% u
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0
    2 l$ B& d& }$ v9 J& b: P' I
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器
    & f6 K+ ?! o5 I7 V1 t
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效
    6 T$ F; D% t1 Z0 ?7 i
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)7 V) H: R( B- U/ T: O
  54.     {
    ! Z8 b" m! n' J/ x# H3 s* j
  55.         Error_Handler();
    % }' r# P1 }* s
  56.     }# d" k6 @3 T# W6 \4 l( |( S/ H# }
  57. }
    7 G/ g# w, C  Q, i$ \6 [
  58. $ H; S5 I$ m1 F  Z% W( k! z+ |+ {
  59. ! B4 [6 D7 T4 c% r
  60. : f# g4 w! K5 Q; a/ b) h
  61. void CAN_Init(void)3 @# N* ?9 r4 q
  62. {' h- n2 N0 B5 i' N, F$ h
  63.     CAN_Filter_Config();
    7 y; g  n* p4 S7 L" U
  64.     HAL_CAN_Start(&hcan1);
    2 |7 y0 X) Z. }3 L
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断. u( Q$ D, h5 S4 X# R7 S- G/ u, q
  66. }
    , I) n3 O- n7 F% a
  67. * G4 @& `$ H3 k# G! a: g1 e5 s
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)! Y) T9 x2 C* B2 b9 `, L) P- g
  69. {
    # ^4 K, |1 {+ W( g" h' D: m, i
  70.         static CAN_RxPacketTypeDef packet;
    " d& k: C+ P6 j7 Q- r. v
  71.        
    + C+ Y% v" F. V6 v
  72.     // CAN数据接收
    3 t; J- b6 [( L  v4 W
  73.     if (canHandle->Instance == hcan1.Instance)6 B, v2 h* M3 \/ \, U/ L8 q
  74.     {
    / H9 a$ i2 D2 k2 Z# D4 L5 p
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    ' _# d' Z8 s2 J( s$ Y7 C4 n
  76.         {' M5 G7 V- u8 f- F; W/ a/ x
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");' ]" m( A: e( X: m, W7 L3 y8 |
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);
    " g6 e9 Z  k- j
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    % _1 k6 K+ ^$ T. D
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);
    % e8 y- s; `3 t7 p+ g/ a' y  c
  81. //                        printf("DATA:");
    ! O+ y' m, Y* `$ E$ Q9 z, ?% H+ X
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++): W3 M6 F- X5 h- P, c1 @! U( ?. n  n
  83. //                        {
    * ~& ?! N  w+ @4 H
  84. //                                printf("0x%02X ", packet.payload[i]);2 {+ C" \0 m3 z& j# E# g
  85. //                        }: V' J: I" N: d# j# z2 F1 M) }
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断; S. w9 E% E( T5 J
  87.         }8 B0 X5 L2 W5 R) Y6 C: P! }/ \
  88.     }: ?: B" ~+ I7 [) p+ u, r; M# d
  89. }  w, M5 ~/ V, ]7 B" w3 j/ h$ `

  90. " D8 j+ z7 t" d! F( |4 R

  91. 9 x& H1 `4 t. y$ Q8 w# h  G3 y
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)
    & W/ V* j3 }  Y7 ^
  93. {% y8 r" a9 ]6 q# I8 @. h
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
    . r: F1 y8 A0 g% b7 W' c
  95.                 return 1;( X/ T+ ]; h( |3 O" d: z8 V
  96.         return 0;
    : u& D; ]. B5 e& l
  97. }+ h9 o) j: z$ f% P

  98. : S( x' x  Q6 q3 c
  99. 7 [. Z$ V2 _- z9 |
  100. CAN_TxHeaderTypeDef TxMeg;- x9 a* t  p; [% u) W
  101. uint16_t TimsRepeat;
    & B6 m0 }6 X" x$ P2 }( |
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)0 j3 N) Z3 l0 k" i7 F; U
  103. {
    & d7 \0 l; N2 t" X
  104.         uint16_t SendCNT=0;5 e  u6 m+ a. r+ D- y
  105.         uint32_t TxMailbox;( S+ t6 _/ |/ b8 J
  106.         HAL_StatusTypeDef        HAL_RetVal;
    / Q- W( f) N4 S5 l( M' A
  107.         / g/ d: x  N5 u& \
  108.         TxMeg.StdId = 0x321; //标准ID
    & y# e8 d  a  M/ H! S, I3 I
  109. //        TxMeg.ExtId = 0x10F01234;
    6 H0 ^# R) O  I2 ?7 d
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型
    1 k. |$ O7 ^, Y2 F( m; ~" ]
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型
    4 B  h8 T+ t) P8 r9 W7 Q; r, c
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧9 M9 ]6 U& m* Q+ u% {5 n! }
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧% z8 N8 b- V- d8 ~7 N
  114.         TxMeg.TransmitGlobalTime = DISABLE;
    " n9 N1 z% ~# g& k9 N
  115.        
    # Z8 y9 Y% L+ P9 M) {
  116.         if(!__hcan || ! pData ||!Len) return 1;
    , n, m. ~( b2 M

  117. ! k3 W4 {8 T( Z, m
  118.         TimsRepeat =Len/8+(Len%8?1:0);% ]$ e9 w7 {/ b
  119.         while(TimsRepeat--)% E1 o- c' F+ z! G0 j
  120.         {, n; U0 [6 |/ f- }6 I7 @# K
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);
    ' s/ B9 `# s% K% G6 V
  122.                 if(TimsRepeat>0)8 T! f4 H, V3 I' h/ c, [* ?
  123.                 {       
    * `( E1 Q6 k; g4 I: p+ e
  124.                         TxMeg.DLC=8;
    2 q; {2 }- p6 d4 F% m, t
  125.                 }. d" G" `4 X, w  V: H& F' [$ O
  126.                 else3 n; _  J: a+ e9 i! C4 y
  127.                 {  U( R# f, r/ N# e2 L, _. Y- E5 A3 W
  128.                         if(Len%8)  X4 w! s' X' J
  129.                         TxMeg.DLC=Len%8;
    ! o( R4 l/ g- G! x
  130.                 }
    + @! D( S4 L' m0 C
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  $ z  G. C+ o# C# i
  132.                 if(HAL_RetVal!=HAL_OK)( ^: i. W* d, X. P) _
  133.                 {6 n, Y/ t/ R9 f! Z/ X* b9 ~4 L
  134.                         return 0;
    9 l+ a. Q1 h1 c, ~- u4 A2 Q2 L
  135.                 }5 J/ j7 B4 ^* f4 z9 K
  136.                 SendCNT+=8;
      n4 O8 d) B  y7 s% U$ X
  137.         }
    : v! t6 }! Y' c5 E4 V
  138.         return 1;
复制代码
5 M8 x  m. c6 \/ `- A0 n. r# _

6 y3 B7 l' W- ~5 L) ~. t

bsp_can.h

: s/ ?% e, H& g

  1. #ifndef _BSP_CAN_H: y6 h7 d3 u" ]. n6 b3 Q( q& Z
  2. #define _BSP_CAN_H
      z' m. u' G$ ?3 j6 N8 }
  3. #include "stm32f4xx_hal.h"$ x0 w+ \" M) f
  4. #include "can.h"
    1 [) T& X$ y7 L+ b% T% o

  5. 9 E8 i; K" N6 L  S, \& S" ]' _3 s
  6. //typedef struct
    ; p' Q! b6 x9 m) z  F* S6 Y
  7. //{; r) ~) k4 `/ f) P
  8. //        uint32_t mailbox;
    / b# j4 W7 ~. H% e" d0 ^
  9. //        CAN_TxHeaderTypeDef hdr;
    ) {) Y; u6 N# C+ P! g2 Q
  10. //        uint8_t payload[8];
    : C/ y; @0 S, V8 |
  11. //}CAN_TxPacketTypeDef;: i7 Y3 e  j  r3 V/ i" |. P4 G

  12. 1 U0 K" L& |8 }7 I3 [
  13. typedef struct
    5 \9 ~$ T. N: u- m* F
  14. {
    4 h. e* M: R2 I* F
  15.         CAN_RxHeaderTypeDef hdr;
    6 n$ o9 A8 `; R) C( Q
  16.         uint8_t payload[8];& u, t- M, ?: `! F7 f; C
  17. }CAN_RxPacketTypeDef;! J5 F. w+ o$ z$ ^3 c* v+ E

  18. 8 n! w+ m% y( y9 C* Z

  19. & X: a, H% V3 o% H- c8 J; d- x
  20. void CAN_Init(void);
    ! z9 C! V0 s3 I" w6 C; _
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);
    7 M' i$ R; L& X! J
  22. #endif
复制代码

) T  c8 Y4 f) T" L" c& w

就可以工作了???非也6 w6 K' Y' k/ E
其实我发现还是有问题


6 q# @; i% Y" ^5 U0 b* U( J, {

3_meitu_41.jpg

# |" f5 M; h! m9 }5 T" U# a% x, t. g! ]  p* j# U, j. V# q. T
( H  t( f( {# D' q# L7 u( ~2 y
为什么第2 3包数据到最后去了?


% S, K& d7 b3 W* l

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

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

( d9 `/ a7 N$ j2 r) H9 |

查看库函数
* C% ~% r9 g4 ]* A

3 f0 j2 M" s  S& e

  1. /**
    - u: [7 v5 G' u; u" ^" r
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    ! m9 D6 X; S/ \
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
    # k4 u7 b" G! k3 }; j) ^* o; g
  4.   *         the configuration information for the specified CAN.
    8 k  _+ G8 d. {) Z5 }4 v- q
  5.   * @retval Number of free Tx Mailboxes.
    / d# x: M) ?, W' W1 a* w) G( M# `
  6.   */5 [9 A  ]; j" G2 P# `
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    6 K3 N" Y& b7 |3 L8 V
  8. {
    7 @$ o) u  {5 X/ x: V  {  C
  9.   uint32_t freelevel = 0U;+ `# D' I9 r! D" X. C6 f
  10.   HAL_CAN_StateTypeDef state = hcan->State;9 ~9 [9 ?/ M% r( I, l9 J
  11. $ m2 O$ r! t! m$ w9 U: }! @& a
  12.   if ((state == HAL_CAN_STATE_READY) ||  B& ^( v7 T8 O9 C% C
  13.       (state == HAL_CAN_STATE_LISTENING))& ~. A7 r+ l: {, J) v7 `
  14.   {
    7 S. ?9 g. y$ W7 ?8 {
  15.     /* Check Tx Mailbox 0 status */
    9 O1 b; t  C( k8 h* a
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    9 D6 ?; v- L: Z6 _  `  O
  17.     {9 e7 t; o, P# k+ f
  18.       freelevel++;
    8 [' a) X  U+ E3 H2 r6 I* D2 }) [
  19.     }$ l% t& m2 j# L: a$ R
  20. 8 X7 r# h! @# [; L' L) l9 C
  21.     /* Check Tx Mailbox 1 status */
    , [5 {+ U# P8 O/ v  Q5 y
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)5 D+ |, T7 j, F5 Q+ o; O
  23.     {, @9 L, B$ _/ {5 G/ I! l) T5 ?6 \
  24.       freelevel++;/ V9 q1 k0 b  {3 I6 n
  25.     }# g# ]7 l' G& c: P/ t

  26. ' I# H$ j7 u( s" I7 q0 J+ F  `
  27.     /* Check Tx Mailbox 2 status */7 x$ o$ Z3 V6 s* z2 Y/ \. `( Y
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    ! F9 Z8 p0 J, m" M- l# w# p
  29.     {: Q3 j# p6 p8 ]( c
  30.       freelevel++;
    0 e& H3 @! r' {7 B4 g# C
  31.     }
    2 d9 h* P( u6 h/ G# |
  32.   }
    ( l: y" ^; X! x" J, R1 [
  33. : a; t' r) g1 t  J- F2 M8 W# J+ @' E8 D
  34.   /* Return Tx Mailboxes free level */7 H; a' N/ z8 i8 B0 S, f( D
  35.   return freelevel;
      ^' c( d; z) M! t% F
  36. }
复制代码

* C- c1 v. Z' t: ?/ K  J! h

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

! I' \5 }3 a5 i

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)/ S/ c) ~( O# }& _- u5 m: U
  2. {0 N( D6 y2 q6 {+ T3 O6 u
  3.   uint32_t freelevel = 0U;
    2 c9 M0 y' _" ]8 ~! `7 o
  4.   HAL_CAN_StateTypeDef state = hcan->State;
    5 `( q+ |4 r7 x% x# r/ V) u

  5. 3 n3 j1 ?2 @. b6 h
  6.   if ((state == HAL_CAN_STATE_READY) ||/ z' Q8 k; N) c4 n" A
  7.       (state == HAL_CAN_STATE_LISTENING))
    ( P3 X1 ?9 g3 c4 O8 }# s* A
  8.   {
    ' f1 X5 O$ \: ]* W
  9.                
    5 f$ v3 j6 C/ `8 W( P0 _# N
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \! ^/ P: G" s0 _+ q( x6 f
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \
    " Q: }" T- V' `' E% V/ \! Q
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    : b  N; a1 U, _8 z8 ^, r2 I9 U
  13.     {
    7 ?% |! V# _5 y1 }; K
  14.       freelevel++;
    * _% s; y* v. y6 b, _; S. p
  15.     }0 U- ^' i+ A" [7 g: ~1 A- z9 r

  16. * f5 ^$ P& _- {' a" ~4 D
  17.     /* Check Tx Mailbox 0 status */- A; `  j3 b1 O5 `
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    5 p; g! j- a$ g) W
  19. //    {3 ]" g# [% W& Q1 R1 c6 V
  20. //      freelevel++;
    8 ~# M: S$ o" B; A
  21. //    }
    ; I' R5 C& z4 x% e6 l

  22. / f# c6 T$ `* {' k
  23.     /* Check Tx Mailbox 1 status */' x1 Y1 ^/ e8 `* F( g0 R
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    ! L; o; D0 j# y8 l: y# V7 w. V9 V
  25. //    {* w, e1 N/ x2 g! M
  26. //      freelevel++;
    ' \- g5 \( l& G0 M' I/ i- h
  27. //    }& F$ w9 ^! H. @) k/ U4 }' _; F

  28. 5 ~+ B9 _( }- b6 l3 i2 {
  29. //    /* Check Tx Mailbox 2 status */- R% Q4 B$ v9 R
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)3 j% g" U+ Y2 L$ B' t( A
  31. //    {
    $ `: R, U0 q- m: n4 o
  32. //      freelevel++;
    ! g. U2 C: B/ [/ J( o5 I
  33. //    }7 G% d9 B+ G7 ?: q4 v! Q9 t
  34.   }0 x1 y: K, j( z. O! Y' M8 R
  35. # ?7 O$ m7 S& R/ _5 _( q
  36.   /* Return Tx Mailboxes free level */: s! ?* R! q! ^0 t7 Q
  37.   return freelevel;
    9 n$ \- V4 C9 \1 ?! M
  38. }
复制代码
0 O" [: s$ x* J' v5 w2 H9 Z# j  K

4_meitu_42.jpg

5 c+ Z3 @& ^$ L! a( n4 W. p
三 总结
1 W/ `$ @3 O0 J% J3 \+ n( a7 j0 E

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

2 P% D- E. B" n+ H) G$ \/ D

3 x% Z% i8 K, h! b2 n! s* {

四、CAN以及库函数分析' s$ [. R5 j' p- \0 p" z, H  l* e7 @

CAN总线% t: H" J2 M; X
1、根据标示符(也就是 ID)来决定优先级的。; k+ o6 P& k6 G; B! i
2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)
1 h) N* L& z7 w1 p, \7 T6 Z3、可通过发送“遥控帧” 请求其他单元发送数据。& P6 i$ T+ Z' y
4、CAN Model:

6 t, M; n6 p, ?; Z- e3 L  w
Normal 正常模式
% Q1 M2 ?  b7 b& zSilent 静默模式$ A  ]6 Z0 u( f2 h
Loopback 环回模式 测试
( c" I% E# t7 B) e! s# B0 ?Silent_loopback 静默换回模式 测试


, Z+ k" B2 e+ V2 p% h' t5、波特率


# l, h: E  W% C波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)


8 H3 b3 a5 f, e: m. ~) u$ t! I

6、发送数据结构体指针

  
  1. /**
    0 i6 J+ H9 |' \+ p1 C7 k
  2.   * @brief  CAN Tx message header structure definition
    , |: i! }) x0 l: i
  3.   */
    9 c7 T: y' h: n7 u
  4. typedef struct
    . k2 L+ H1 A# S2 m+ _' t% H
  5. {
    9 y. H; b+ l4 b% K3 N  h" e  d: I( z
  6. //表示标准的ID
    " x0 F* D9 u5 q; v
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.
    : f5 E1 M. q. M4 \, B
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */& J1 F! A7 M# z3 k. S
  9. //表示扩展的ID
    / X, P* s: U. X4 A
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.$ o( @( O: D3 p3 }* C0 }" k
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */
    0 z3 }9 [6 X7 W  e
  12. //要发送的是扩展帧还是标准帧
    ) p( \1 g8 u/ Y: e$ |7 \8 a/ B+ C
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.6 g9 G7 O9 v& Q" b; D. `8 {
  14.                           This parameter can be a value of @ref CAN_identifier_type */
    8 u5 L  [$ V3 r2 Y+ D" [
  15. //表示发送的帧类型。如:数据帧、远程帧等
    2 L& l6 F3 ~/ ]- M0 I
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
    % S" ^+ j: i5 |
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */1 K0 X, @0 p, F
  18. //表示发送的数据长度  P) x- r2 ~, O
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.
      `0 t" }# E& y. A
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */
    - L! \3 ~+ c2 n4 F3 n, o( }
  21. 3 {& {' q0 O9 E) K7 `  O
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start2 |- G; }4 x, l" y! Q" S
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].' }8 r( V7 B/ \7 _
  24.                           @note: Time Triggered Communication Mode must be enabled.7 t5 M, h2 t) J3 t, ]! f
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.$ p2 i- |9 I; [3 U" z/ ^- \' b3 M
  26.                           This parameter can be set to ENABLE or DISABLE. */
    2 I) T1 V2 S/ L- G# V! z

  27. 5 F0 b# d# |* ^
  28. } CAN_TxHeaderTypeDef;
复制代码
+ V0 k. O3 |( z, }! D

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器
+ _) L, g0 D/ z/ C9 D- A屏蔽模式" g: T: q" l3 Q3 I
屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你2 M' m" P5 b5 V( `6 Q, s4 N
想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。
# X4 B; Y8 }1 n: b. Q) U+ A& r屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。

/ [/ a/ }9 x+ q$ @* _


$ {* k7 j4 N3 h% v

8、过滤器结构体

+ r; e* F! w4 ^& i- }: c1 a
$ m/ V# }0 F% {6 }. A
  1. /**/ b6 b% G( j( W9 M' K
  2.   * @brief  CAN filter configuration structure definition
    / m& g3 n; z! O6 ^; d5 X% M
  3.   */- [- g5 }3 u7 O3 A
  4. typedef struct* _( f) j  o+ c
  5. {
    " u, m1 \! Z0 m) x/ U& V4 U1 w/ Y
  6.         //这个是标示符寄存器的高 16 位  ?4 X  O- ^/ W8 @
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit
    0 ?: i8 J( |8 Z. Q- F, p
  8.                                        configuration, first one for a 16-bit configuration).
    3 t+ t! {- u- j5 q
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */+ l2 n; j% `: M
  10.         //这个是标示符寄存器的低 16 位
    8 {/ Y4 V0 f+ X" D/ p+ D: A) D* b
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit5 }- b5 q' y' {5 w  s
  12.                                        configuration, second one for a 16-bit configuration).0 o! O' M; m* ~! u# Q
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    2 L: i3 i: m% D& v+ |* y/ M& c5 _) L
  14.         //这个是屏蔽寄存器高字节的设置
    3 k' d9 g  L9 Z$ A9 g
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,. @" F( m& _4 d! Q. L6 R: D. K
  16.                                        according to the mode (MSBs for a 32-bit configuration,
    0 M1 n6 O+ n7 w) V' O- M
  17.                                        first one for a 16-bit configuration).
    8 U: Y% T  f% K3 |0 I  ^/ T
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    8 h( g* y( c9 h9 c2 H
  19.         //这个是屏蔽寄存器低字节的设置
    : D) P$ T- i, ^# ]2 Y
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    ' r& s& j* _9 c; P, N* v- r
  21.                                        according to the mode (LSBs for a 32-bit configuration,
    2 s! @) W  V( B, B  m
  22.                                        second one for a 16-bit configuration).
    + d: G& l4 C+ D
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */' `. \# e+ k) z. m
  24.         //选择你要使用的邮箱,它有 0 和 1
    & W5 c% f2 M( Z+ j+ c, q' R5 U
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.8 [; m) \/ d* ]( k
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */$ L9 C* p6 ]+ r8 \$ Z6 G; Q2 r# P
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。 : @9 e8 C2 E. }4 g; p, j8 F* H
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.& g7 P% v% P1 d* V5 [: e
  29.                                        For single CAN instance(14 dedicated filter banks),+ X' Q  Z. Z3 M+ n  J8 x$ i. `
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.
      K  I9 m. i/ v) u
  31.                                        For dual CAN instances(28 filter banks shared),
    ' E& S4 H2 P9 i5 f8 g
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */; a7 X# C% a& V/ b2 M
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和
    3 ?9 @5 O0 j7 u) E. H8 F; r
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :
    " c% [$ @/ [6 ~) L. [
  35. //CAN_FilterMode_IdMask。
    % z6 ^+ Z# ]0 o$ d* j# b; E; h9 ^
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.
    ! u' w& U: H3 t# \0 ]) o% i
  37.                                        This parameter can be a value of @ref CAN_filter_mode */% s. t: j% s6 K
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。* E  @. Q, ~7 R4 A# H. O
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.
    9 H3 a0 k8 n8 X& D2 H3 q0 o' f9 g3 h- I
  40.                                        This parameter can be a value of @ref CAN_filter_scale */. L; {& f; N" C; k& y0 J
  41. //表示过滤器的使能$ I8 L7 X) L( [6 B' o; f4 J
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.
      s) B* s2 f. O0 I- q2 e
  43.                                        This parameter can be a value of @ref CAN_filter_activation */  G3 j/ k6 n) R2 r: k; }, A0 O
  44. 2 P" W+ R5 o  c- f' \
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.0 t  {) _0 z+ ~8 F/ @& j8 s& F, U
  46.                                        For single CAN instances, this parameter is meaningless.
    2 e" [/ j9 Z8 E$ q' g
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master$ h. p1 V4 J: G* |6 Q$ `" P
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave7 q! a" l2 i% I- z
  49.                                        CAN instance.
    ! `( L# j' a; w: |, I) O
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
    / R- t& C% Z- a! F" n4 J8 ~6 i/ ~$ h
  51. } CAN_FilterTypeDef;
    ! p$ q9 r' R0 _0 W. a! C
复制代码
: y' S8 g/ v- P* f6 F

0 p0 r$ X6 p) w, c. M, d5 w) u
2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

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