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

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

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

1、发送单包数据,我想都非常简答,例子一大堆包括,demo。但是发送多包数据怎么处理?
: b4 g; V0 ~5 W/ j% {/ |8 P2、发送多包数据,网上基本上就两种说发" d$ ?# s% [# _
*两个数据之间加延时. o2 H% _/ Q1 Y# d
*查询邮箱是否满了+ y# r5 k8 r( |; l; A% Z
HAL_CAN_GetTxMailboxesFreeLevel()
; K2 W4 t4 Y3 k6 s; j) @) E8 v对比上面两种方法,为了效率我们选择第二种


) v" p+ ]$ Y2 u9 f


3 Q  ?" P" C3 a9 @6 v" U

二、配置与代码5 G) U3 c. L* d  j( A
& ?/ Y9 ]& h# B( E% Y. O7 D

直接上cubemx配置

( S/ V, K& O. z8 l' Z


( ?+ N. ]$ T  F/ S3 g# p6 R

1_meitu_39.jpg
/ c$ R1 I8 L- U  P
2_meitu_40.jpg

' {- q5 y6 i  {. `$ z
. ^" Q7 w2 c0 M5 b* k3 M9 h8 Z3 s  L3 J4 [) S* L. g! t
直接生成后,cubemx没有设置过滤器,需要自己添加,结合网上各资料总结代码如下

2 _& g; z% S: d& b# R: I; `& f, `

  1. int main(void)# b( F- [! i. ?8 `7 x5 V7 A
  2. {* s: s0 C+ j% e
  3.   /* USER CODE BEGIN 1 */
    4 _3 ]  X, V% b$ U. B

  4. * z# a1 V) o+ G6 Y, o* f
  5.   /* USER CODE END 1 */
    ; Q8 I7 @% e. H5 B; G) J. v
  6. % N. c9 ~+ i3 e
  7.   /* MCU Configuration--------------------------------------------------------*/& B6 `: n, t$ e
  8. # C0 m; E4 a; s% S* u
  9.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */  B9 I9 D, Q( E( ?
  10.   HAL_Init();
    . T, h0 Z" N. e

  11. " Q( N8 Y& ^/ Y1 L/ X: D; Y
  12.   /* USER CODE BEGIN Init */
    $ p. S3 I* i5 t6 H5 t: e$ h8 |
  13. + A; T: o" {# P2 a
  14.   /* USER CODE END Init */3 z; c- [! y1 T% a5 q4 S+ Z
  15. ' u, x+ |$ ^$ p. }" f- M
  16.   /* Configure the system clock */
    2 F) Z9 q7 {9 J, |- K/ Q
  17.   SystemClock_Config();
    . L2 f8 I( l7 p6 E

  18. 4 j! G) C6 i! g1 I' d
  19.   /* USER CODE BEGIN SysInit */$ T% d$ i- _# C8 ?- ~

  20. 9 l: O: a0 P2 u/ E4 u6 C
  21.   /* USER CODE END SysInit */
    ) ]0 S9 Q6 d. W1 O

  22. & U+ ^( l- m1 R+ D; Y
  23.   /* Initialize all configured peripherals */4 }# N' g2 ?0 A8 B! u
  24.   MX_GPIO_Init();1 o) O* ]+ x/ l$ a+ r. S
  25.   MX_CAN1_Init();
    $ ?% Z8 E: j$ w
  26.   /* USER CODE BEGIN 2 */
    7 _9 O0 N. {7 a. Q4 L
  27.         CAN_Init();
    : q/ ~0 j; Y' W% m+ b! D
  28.   /* USER CODE END 2 */5 g0 S, ^$ L- T  f% o: l4 V
  29. ( ]& i% h$ K7 R3 y, _( U# d4 y
  30.   /* Infinite loop */
    ' m! B5 N$ Q* w8 e$ v
  31.   /* USER CODE BEGIN WHILE */
    ! x5 L; C* q; C! _* {! C/ H
  32.   while (1)
    ; y; T/ G1 o2 a* |/ R  @' {
  33.   {/ `+ O! W2 j6 A/ Y( t
  34.     /* USER CODE END WHILE */
    # s2 _2 `( Q/ d7 D1 a: z, S( K, ]
  35. ) y  q5 p1 R' L7 Z1 q0 S6 @
  36.     /* USER CODE BEGIN 3 */  r9 L2 B- ~$ q& F
  37.                 uint8_t TxData[100] ;
    + Y  y8 |+ F4 z' Z7 r0 c
  38.                 for(uint8_t i=0;i<100;i++)
    3 T; z( ~) o8 w; K9 M1 |5 N
  39.                         TxData[i]=i;
    5 i; \  b$ T7 D! u
  40.                 CAN_SendStdMsg(&hcan1,TxData,sizeof(TxData));
    % x8 p, p9 \/ t
  41.                 HAL_Delay(100);6 Q/ c- [8 T5 m! m
  42.   }
    $ }3 v* [7 a4 d4 z, l
  43.   /* USER CODE END 3 */
    " `* H& j& \* ?1 @  D; B% v
  44. }
复制代码
+ C- u- Z. f8 q7 g3 c

bsp_can.c


& {, P/ {! I3 v  X  i& c" o* S7 M
  1. #include "bsp_can.h"
    $ Q# s2 ]6 s+ W- }
  2. 3 h3 x, F9 w* g* E
  3. 7 p! v8 v( r% q
  4. /// CAN过滤器寄存器位宽类型定义
    $ l' P, \5 B- D7 i2 ]
  5. typedef union
    , u2 F# _9 T. u) c6 D5 x3 w
  6. {
    . F) C! V# V, Z  D
  7.     __IO uint32_t value;) V* u5 U7 k1 H# Z+ Y
  8.     struct$ H1 q0 q9 T: v" I( |) v1 P
  9.     {" A& F5 ?: y# Q' C/ N
  10.         uint8_t REV : 1;                        ///< [0]    :未使用7 Y3 W+ ?. x! H, q' D
  11.         uint8_t RTR : 1;                        ///< [1]    : RTR(数据帧或远程帧标志位)
    8 J$ {* h5 C+ n" B% W) A) s8 G
  12.         uint8_t IDE : 1;                        ///< [2]    : IDE(标准帧或扩展帧标志位)
    ! p8 f2 M1 K" ^* I" \, m. W
  13.         uint32_t EXID : 18;                        ///< [21:3] : 存放扩展帧ID, Z$ o" o% W$ ?% m
  14.         uint16_t STID : 11;                        ///< [31:22]: 存放标准帧ID" w; J! H9 Q- n1 S
  15.     } Sub;; D( ?+ I2 R7 W* l
  16. } CAN_FilterRegTypeDef;
    0 M3 R5 K! q2 [* U/ w& R& Y' a, n
  17. , i7 w2 R+ S$ V$ c; S
  18. 8 ?9 K4 B# v# k$ o
  19. #define CAN_BASE_ID 0                                                ///< CAN标准ID,最大11位,也就是0x7FF' V) q2 h9 |/ l7 a

  20. * d+ c7 o0 M7 X5 ^' l
  21. #define CAN_FILTER_MODE_MASK_ENABLE 1                ///< CAN过滤器模式选择:=0:列表模式  =1:屏蔽模式
    ) U1 i9 W6 q( o4 Q* \
  22. + a5 o* q2 R% g: [' `
  23. #define CAN_ID_TYPE_STD_ENABLE      1       ///< CAN过滤ID类型选择:=1:标准ID,=0:扩展ID& E1 r! \2 x, i% U0 W

  24. 1 Y$ c! ?! t4 L5 S9 x! b
  25. void CAN_Filter_Config(void)0 y& N+ N0 t: F) }. k
  26. {
    5 s' J4 T) E7 q1 E) D
  27.     CAN_FilterTypeDef sFilterConfig;
    . a7 `8 G' {. I' s
  28.     CAN_FilterRegTypeDef IDH = {0};. v$ Q/ b# D/ ~: [
  29.     CAN_FilterRegTypeDef IDL = {0};$ @0 q8 Z$ d3 j

  30. / u' Y5 g$ @7 [
  31. #if CAN_ID_TYPE_STD_ENABLE# g5 s! I1 N7 `8 U; ]+ |
  32.     IDH.Sub.STID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 标准ID高16位
    & f. R0 ~( S% Y
  33.     IDL.Sub.STID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 标准ID低16位* U, z" p( c# b$ n3 \" t* o
  34. #else: e$ k5 e7 q( I: I' K9 G$ E! ]5 d
  35.     IDH.Sub.EXID = (CAN_BASE_ID >> 16) & 0xFFFF;                                                                                        // 扩展ID高16位
    9 k, u# M. ?3 a3 [
  36.     IDL.Sub.EXID = (CAN_BASE_ID & 0xFFFF);                                                                                                                // 扩展ID低16位/ y% I, R: X. z+ x- Q  q* y. c
  37.     IDL.Sub.IDE  = 1;                                                                                                                                                                                                        // 扩展帧标志位置位
    0 t5 d" z* V' [
  38. #endif, h  S3 Y! B: o4 m
  39.     sFilterConfig.FilterBank           = 0;                                                                                                    // 设置过滤器组编号
    6 ^+ M: B/ B6 x+ e5 m
  40. #if CAN_FILTER_MODE_MASK_ENABLE) }1 x: G& h5 [/ k' K, j
  41.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDMASK;                                // 屏蔽位模式- Q. z. ^1 ^7 V0 @" p
  42. #else
    - j9 N& [% l" R
  43.     sFilterConfig.FilterMode           = CAN_FILTERMODE_IDLIST;                                // 列表模式
    ) A: L3 H9 T6 o8 ~# l
  44. #endif
    + |4 a  Y! f1 P9 H
  45.     sFilterConfig.FilterScale          = CAN_FILTERSCALE_32BIT;                                // 32位宽
    + N: z( L8 |' b  b& O/ W, ?
  46.     sFilterConfig.FilterIdHigh         = IDH.value;                                                                                // 标识符寄存器一ID高十六位,放入扩展帧位
      X* K1 g0 [6 J; v# k; \8 A
  47.     sFilterConfig.FilterIdLow          = IDL.value;                                                                                // 标识符寄存器一ID低十六位,放入扩展帧位
    # f" p0 {7 z2 _! G( `
  48.     sFilterConfig.FilterMaskIdHigh     = IDH.value;                                                                                // 标识符寄存器二ID高十六位,放入扩展帧位5 O' n+ N+ _1 @8 Z9 x
  49.     sFilterConfig.FilterMaskIdLow      = IDL.value;                                                                                // 标识符寄存器二ID低十六位,放入扩展帧位
    0 p2 \- s  o3 c9 `2 C, e2 g. g
  50.     sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;                                                                // 过滤器组关联到FIFO0
    0 V! w* u, f+ W* [0 B8 w& Z# U& b% A
  51.     sFilterConfig.FilterActivation     = ENABLE;                                                                                        // 激活过滤器+ j+ R. `  m/ F
  52.     sFilterConfig.SlaveStartFilterBank = 14;                                                                                                        // 设置从CAN的起始过滤器编号,本单片机只有一个CAN,顾此参数无效( n; [+ a0 {) U8 E9 v
  53.     if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)2 b+ b1 W9 A! z1 T! F" _
  54.     {
    , a) e1 t0 b2 y9 x
  55.         Error_Handler();' u- O/ F: k5 w: ^" ?
  56.     }
    : }# T# Q5 K# S0 X" M% e
  57. }. x4 X+ c* {/ r) h: w# a- \- S

  58. & N% Z& P3 A7 I6 M2 Z& s

  59. & G. x3 }7 a  A% [  O" h

  60. ' K' \6 ?* c  R1 E  }* j
  61. void CAN_Init(void)
    1 O4 \, n! P# l) ]! a/ _
  62. {% L" q$ d3 b) s$ L' k3 g1 \5 M1 w8 ?
  63.     CAN_Filter_Config();. S3 ?. Y1 A: B$ x
  64.     HAL_CAN_Start(&hcan1);
    ) b% ^. x) r9 e/ H6 G, B+ z
  65.     HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);                                        // 使能CAN接收中断: N( y. G. p  s: m% N
  66. }( d! @0 ?5 {$ F7 W7 K3 q4 {

  67. - U" x( _& k8 P6 G
  68. void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *canHandle)
      N9 m1 {  |3 y& Z+ ?6 v
  69. {+ ^0 V3 Z3 S- ?/ h4 p5 }% y+ @# [
  70.         static CAN_RxPacketTypeDef packet;! X7 T8 F% t- y* u3 X
  71.         5 I. {. C* V6 j) M
  72.     // CAN数据接收9 E7 g. ]+ C  o- Q8 L% @
  73.     if (canHandle->Instance == hcan1.Instance): I  {; v" E5 W. I
  74.     {( N/ [! M( B: t2 Y
  75.         if (HAL_CAN_GetRxMessage(canHandle, CAN_RX_FIFO0, &packet.hdr, packet.payload) == HAL_OK)                // 获得接收到的数据头和数据
    9 E7 {- H# b* ?% }, h+ M% H
  76.         {
    & L6 f2 I$ x* \  J9 f; ^9 D. q, R. R
  77. //                        printf("\r\n\r\n\r\n################### CAN RECV ###################\r\n");
    5 ?- y- F* S0 g( M; d& [, E
  78. //                        printf("STID:0x%X\r\n",packet.hdr.StdId);, {5 }" d3 X+ Q& z/ H
  79. //                        printf("EXID:0x%X\r\n",packet.hdr.ExtId);
    4 I2 u0 ]' k% W2 }6 g2 t8 ^+ C
  80. //                        printf("DLC :%d\r\n", packet.hdr.DLC);9 Q% D/ i/ \0 k% t' Y
  81. //                        printf("DATA:");
    . ~9 y7 O! x- y; k' g7 b% j# g  n
  82. //                        for(int i = 0; i < packet.hdr.DLC; i++)7 B/ y' X! x, z& x# s4 K
  83. //                        {
    ) {0 `: ?2 s) _; V8 n
  84. //                                printf("0x%02X ", packet.payload[i]);
    / a1 x0 M* o0 s$ A4 w- n
  85. //                        }
    * }. o( f7 J2 k) W' N
  86.            HAL_CAN_ActivateNotification(canHandle, CAN_IT_RX_FIFO0_MSG_PENDING);                                                // 再次使能FIFO0接收中断
    $ N! p$ X# }! U1 r2 V; G
  87.         }" s7 @4 k! j: Z- `' }# Z
  88.     }8 T3 W% G5 ?, |5 L, b
  89. }+ s' y; u5 Y9 p6 H6 B0 v
  90. ; Y4 \! u3 t/ K; T) z

  91. ! y* ]9 a3 T7 K) u, o3 d
  92. uint8_t CAN_Transmit(CAN_TxPacketTypeDef* packet)- P: [9 z5 P' Z- ?9 t6 S
  93. {
    5 f9 L: X3 u% L" r' }! N8 g8 ^. R
  94.         if(HAL_CAN_AddTxMessage(&hcan1, &packet->hdr, packet->payload, &packet->mailbox) != HAL_OK)
    8 C, g- e& Y- U/ V# z4 H
  95.                 return 1;$ h" N5 Z& F5 S& C# O
  96.         return 0;8 E  [3 g$ ~. u
  97. }* }! H1 F/ u& L1 T* o8 Z- a
  98. - z. l2 N+ ]" E% m: A: Q2 {
  99. 6 d2 l. x9 ?/ M) s+ A0 E+ d
  100. CAN_TxHeaderTypeDef TxMeg;
    & {- n3 ^. f5 f' |
  101. uint16_t TimsRepeat;# d3 w8 s1 l( u- c$ p6 m- |) c" }
  102. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len)  r+ V: A+ Q, W1 w$ w: Z
  103. {2 B8 [0 I+ T6 z. ~2 r7 J
  104.         uint16_t SendCNT=0;
    3 j5 a3 k+ T* C
  105.         uint32_t TxMailbox;
    ' t1 N7 ^' Q' j6 ^
  106.         HAL_StatusTypeDef        HAL_RetVal;
    0 C, K3 o+ x' t& \9 P* _
  107.         / v" {1 b# u; m( N" ]
  108.         TxMeg.StdId = 0x321; //标准ID/ w: B8 X2 t3 F7 P, n* I
  109. //        TxMeg.ExtId = 0x10F01234;+ c% @, x1 N9 Q8 l/ S4 A7 \
  110.         TxMeg.IDE = CAN_ID_STD;// 标准ID类型
    " F0 E; d# m; k& \  |2 w
  111. //TxMeg.IDE = CAN_ID_EXT;// 扩展ID类型+ f  |1 o9 M1 Q+ \! r& F) r
  112.         TxMeg.RTR = CAN_RTR_DATA;                // 数据帧
    0 O2 o, Z6 T6 T
  113. //TxMeg.RTR =  CAN_RTR_REMOTE;                // 远程帧0 B4 L* F3 O" @  L$ J. k+ ~% t6 \  a
  114.         TxMeg.TransmitGlobalTime = DISABLE;
    - d* _6 q* b. ]( m5 X' H) Y
  115.         6 m5 C4 @% k/ |
  116.         if(!__hcan || ! pData ||!Len) return 1;
    , _' {) p3 w' C" b4 u! p" R  N
  117. ( h& t- o0 w4 t/ z) U. c9 _& _
  118.         TimsRepeat =Len/8+(Len%8?1:0);9 A* f: V7 w5 L9 v+ c, m
  119.         while(TimsRepeat--)
    - V1 m+ F' ~2 k
  120.         {* \: `: K+ _- K8 I$ C2 w. d6 |( ^
  121.                 while(HAL_CAN_GetTxMailboxesFreeLevel(__hcan)==0);% W5 k1 x0 N* ^- R. V: C
  122.                 if(TimsRepeat>0)* A& f& r. {1 m% M$ D+ Y
  123.                 {       
    & n3 u8 I$ M' S1 k/ d$ j6 E. R
  124.                         TxMeg.DLC=8;4 d! q+ [2 f9 I7 c6 G& L
  125.                 }3 C- @* ]# |2 N2 i! m2 L/ ~
  126.                 else& {. @: J; _" z3 M7 H- y
  127.                 {
    3 h0 L% x- p9 V
  128.                         if(Len%8)7 Q; D7 e$ u6 x8 u) f
  129.                         TxMeg.DLC=Len%8;
    % a4 n4 l: Y6 C6 D) M
  130.                 }- o/ C4 v/ N- U0 h( H: N$ @2 k
  131.                 HAL_RetVal=HAL_CAN_AddTxMessage(__hcan,&TxMeg,(pData+SendCNT),&TxMailbox);  5 B+ y. X5 g( z) d- D% o
  132.                 if(HAL_RetVal!=HAL_OK)" ]6 @9 `$ ?( a
  133.                 {
    : }- g6 s' P8 s9 r* R9 L
  134.                         return 0;+ h1 s4 T* b) f2 k  s
  135.                 }" z$ }5 Y5 @2 U' L4 A6 N& _
  136.                 SendCNT+=8;) \) K( W: [4 x# Z4 G# }9 o
  137.         }% U% s2 l# \4 p# M
  138.         return 1;
复制代码

" d& Q# h9 [5 Q1 C% i$ l# \/ P" P9 l$ E; v

bsp_can.h

2 \+ ]  N$ p% @$ U# K* y  R" Q: H2 i* p

  1. #ifndef _BSP_CAN_H
    ! v) {6 ]" a& k+ w4 o3 v3 N
  2. #define _BSP_CAN_H
    4 a/ R+ X+ S0 w5 X' e' l
  3. #include "stm32f4xx_hal.h"4 J9 O+ T5 _+ `/ g
  4. #include "can.h"7 o8 R7 j+ E1 T- y' O# z
  5. + M/ _0 e) v. U; r6 u* {& c
  6. //typedef struct: u0 E/ S! i3 b% R8 o7 y: {8 r# U- ?
  7. //{
    ) P5 n% T) E9 r2 ?, C- a4 u
  8. //        uint32_t mailbox;
    " E6 H! g: Z5 y9 r: d# T
  9. //        CAN_TxHeaderTypeDef hdr;
    # a3 o# _! s( Y6 P+ F
  10. //        uint8_t payload[8];& t  {! p' [: u3 Y# ~
  11. //}CAN_TxPacketTypeDef;( l9 c6 Z" l% L2 T
  12. + {+ z2 o; v) p8 l3 i! D6 c
  13. typedef struct
    " `) F* u( @/ F+ D9 x. X
  14. {
    " a7 k1 z: g2 p! L
  15.         CAN_RxHeaderTypeDef hdr;
    & [. `! R% k. Q. {! v" n
  16.         uint8_t payload[8];
    2 F5 J3 l' H; _7 f' G5 s
  17. }CAN_RxPacketTypeDef;% H; ^& K+ ]- w4 ]( B

  18. 9 v; e+ C' C) T

  19. + [$ M' ~1 L) j$ ^# ^  U5 [
  20. void CAN_Init(void);
    9 v% U# N& u# y) n$ E# z
  21. uint8_t CAN_SendStdMsg(CAN_HandleTypeDef* __hcan,uint8_t *pData,uint16_t Len);
    8 V8 e2 z+ F' K( |5 |
  22. #endif
复制代码

2 r' C& R9 g3 _+ m2 T% c' _5 n

就可以工作了???非也
3 `- u6 [5 c) w( l( B其实我发现还是有问题


8 g* N  j2 D, f+ o

3_meitu_41.jpg
2 M% [: \  P8 ^: i/ U! A
2 s  Z: s% Q6 E

9 V8 B) t' H1 y2 q% t6 d
为什么第2 3包数据到最后去了?

  K. p; G' o; g; `0 j- n

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

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

: @4 d$ f* C* T2 a( x3 r; k: _; E

查看库函数2 T7 k+ \$ Z; R# Z3 o9 B, Y! l( M

2 Q7 c1 |. |$ \: c4 _7 p

  1. /**! D0 ?3 m0 Q; r: Y; W
  2.   * @brief  Return Tx Mailboxes free level: number of free Tx Mailboxes.
    : r$ v& z2 C3 o
  3.   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
    / B& R0 h+ Q& J5 `+ V. [
  4.   *         the configuration information for the specified CAN.; t/ ^2 Z4 I4 m$ y+ ?2 x; }
  5.   * @retval Number of free Tx Mailboxes./ d, |3 V9 T# m% H6 d8 p) y
  6.   */
    + L- ^% |" W, M; @7 z4 c  o
  7. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan), Q, g! e/ H3 b; O$ z3 Y* G  m
  8. {
    $ s7 Z' d. E  a, y0 f7 i
  9.   uint32_t freelevel = 0U;. p# u. ?3 j% g
  10.   HAL_CAN_StateTypeDef state = hcan->State;  n! O; U7 B8 N, z0 I
  11. - m& F% X6 M: ^# b6 Q! d
  12.   if ((state == HAL_CAN_STATE_READY) ||# \  y0 G, q. v, N& v/ x
  13.       (state == HAL_CAN_STATE_LISTENING)). T# Z0 k8 H8 I+ L0 s# a
  14.   {
    . V! J& w& A  [: ]- v0 |
  15.     /* Check Tx Mailbox 0 status */4 [9 n9 t. O# F9 V  x7 D. p( y
  16.     if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U): n/ r  E) G( g4 q: g
  17.     {
    4 P: X, Q2 V3 C
  18.       freelevel++;; _/ G: ~. J* e" s
  19.     }
    4 u. p- r6 ~6 p/ L8 v
  20. 1 V2 @( t! z( m0 e! g
  21.     /* Check Tx Mailbox 1 status */
    # S" T& B+ |. [
  22.     if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)4 |  C/ F/ X1 W7 ]  ]
  23.     {- {$ Z, g  ?! c$ J6 L. l
  24.       freelevel++;: c9 S. V* n( H+ M
  25.     }
    / _+ h  D: I; a& Y1 v! n
  26. ( D: k/ M" e: z2 P" Z
  27.     /* Check Tx Mailbox 2 status */
    8 C, I, c" j4 n
  28.     if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
    8 B% A; P, S0 p# N: b
  29.     {
    ! ]& E6 J' O; @6 b
  30.       freelevel++;1 q! n. k/ `1 f
  31.     }8 L6 n' k- \4 N* V% q3 G
  32.   }
    . J6 ], c( j7 `

  33. + V' `( n3 `" @3 T
  34.   /* Return Tx Mailboxes free level */; G. o) j' i2 Y7 [: l! D
  35.   return freelevel;
    & l' j) Z0 i8 D2 k1 l* _3 [
  36. }
复制代码
  f$ }$ I% b1 l) D4 O& \3 z0 l' D

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


4 t. b3 p8 U$ u. g1 E" o7 W

  1. uint32_t HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan)
    9 n: X6 X$ V4 b. l
  2. {  l: Q( i* o# p+ p6 |. g  [/ Q
  3.   uint32_t freelevel = 0U;1 i3 n# X; w* v& X6 V3 l
  4.   HAL_CAN_StateTypeDef state = hcan->State;, g* X  I1 A9 u* J% h5 ~1 O

  5. " ]5 j: _4 L3 d" l
  6.   if ((state == HAL_CAN_STATE_READY) ||0 z! d% z( |) m# X) ~4 M' k, R( ^
  7.       (state == HAL_CAN_STATE_LISTENING))) z5 E9 Z# i& Q0 b8 _. o! Q( I, l
  8.   {3 _5 [4 ?" a+ s7 z6 Z) E; A
  9.                
    0 }3 D6 v: N- L
  10.                 if (((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)&& \
    " s+ K2 x, {' T8 o' ~$ q
  11.                           ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)&& \
    * P8 I* G5 I) Q; L) J$ j
  12.                      (hcan->Instance->TSR & CAN_TSR_TME2) != 0U), s  P, c+ a, `7 f
  13.     {
    4 \0 |2 y3 q* V, `, O1 ?; {. X
  14.       freelevel++;5 B  Y+ K8 }- c/ o$ z  W
  15.     }
    6 c; r. Y+ |; \6 h

  16. ' [. D# ?* S" A* R! j$ C( L
  17.     /* Check Tx Mailbox 0 status */2 ^0 s. U1 L# q# W& c6 w! d9 h6 p
  18. //    if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
    ; x- F- m$ h' t8 G1 R8 Q9 ~
  19. //    {
    & k- {: ?! P) r4 \+ l% l
  20. //      freelevel++;/ X  W7 S3 G5 C* J8 s# M" z
  21. //    }$ J( n+ v" P0 [% v( K2 e! j1 F
  22. 8 O: E# `/ x7 W# @0 K3 J' Y" r
  23.     /* Check Tx Mailbox 1 status */& c  N9 _6 i7 g
  24. //    if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
    $ l0 [; o+ L, j1 H& h+ `
  25. //    {" N: o: T% \1 X. d( g
  26. //      freelevel++;1 I, F; X1 F0 P
  27. //    }1 K1 f9 P+ N; B* ?* U6 q6 z* z
  28.   O; L  R8 y) l9 w
  29. //    /* Check Tx Mailbox 2 status */+ P/ ~) {9 `) Z2 E! X
  30. //    if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
      ?. n. u9 m" b  M, K! j
  31. //    {" g* \. Y4 a3 H4 q4 s: _- w- q/ t3 Z
  32. //      freelevel++;
    " C3 |' c; I1 g
  33. //    }, Y/ X4 }. A$ @) O9 }- \
  34.   }
    $ b# n3 s) Z3 A9 X
  35. " h- u9 ^3 M: \5 W, f# |
  36.   /* Return Tx Mailboxes free level */
    , _. T, N) j5 l4 M" G4 @6 P- F
  37.   return freelevel;
    % R: D% E2 ], S' x$ Z1 D- s* O
  38. }
复制代码

- f* p, E/ a7 F7 t0 a, p/ L

4_meitu_42.jpg

) N  ]6 R5 G( `' K6 N
三 总结2 W1 E7 I4 E; c

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

: V  t3 K0 h* g+ ^% Q% [

% s& ?: }  j( a$ O

四、CAN以及库函数分析
" ?, v* p# u2 k, t- ]

CAN总线
9 G3 H. I" q" p1 Z- F& _1、根据标示符(也就是 ID)来决定优先级的。, O3 A3 p9 g, |7 Q1 w4 t
2、在同一网络中,所有单元必须设定成统一的通信速度,最高 1Mbps(距离小于40M),最远可达 10KM(速率低于 5Kbps)
& O( a) Y) [# q5 c9 P: `3、可通过发送“遥控帧” 请求其他单元发送数据。
# K( l( y. `* T' Q4、CAN Model:


; M$ g& Q$ ?  r9 f: n. ]( y' eNormal 正常模式/ Z' K, f$ U2 _+ R3 E0 B9 h
Silent 静默模式
8 L/ c' E: Z- T  J, F" lLoopback 环回模式 测试9 P. A; j5 ?5 O; ], W& q
Silent_loopback 静默换回模式 测试

9 r' d. l9 o1 b1 T# g* V
5、波特率


! y' g1 z+ z8 L1 i7 Y波特率(Kpbs) = fpclk / ((CAN_BS1 + CAN_BS2 + 1) * CAN_Prescaler)

/ @! f: |% t) L" |% J2 S1 r( p

6、发送数据结构体指针

  
  1. /**& \/ H2 v* c" n! B. I- o
  2.   * @brief  CAN Tx message header structure definition7 \, c& g, n; d6 d  v
  3.   */$ T8 a0 q# g7 m7 \9 @" M* B" m, }
  4. typedef struct7 O4 W+ S$ \+ v1 Q: ^
  5. {
    ! N7 ?* W& ]" S5 k! V
  6. //表示标准的ID0 E; r- ~7 p9 A1 @, k
  7.   uint32_t StdId;    /*!< Specifies the standard identifier.6 A4 N$ [7 @- w% n7 A: ]
  8.                                                   This parameter must be a number between Min_Data = 0 and Max_Data = 0x7FF. */
    " f' N8 U& C+ h1 w, Z2 h) m0 ^
  9. //表示扩展的ID
    6 \- U* q* Y& v
  10.   uint32_t ExtId;    /*!< Specifies the extended identifier.
    7 o7 K' {% g; T
  11.                           This parameter must be a number between Min_Data = 0 and Max_Data = 0x1FFFFFFF. */$ j" ~, ]" p$ I  @2 k
  12. //要发送的是扩展帧还是标准帧
    5 L$ G5 U% R/ B+ Y
  13.   uint32_t IDE;      /*!< Specifies the type of identifier for the message that will be transmitted.% b, L+ K! ]; G0 m; i$ u! h( Y' C2 Q7 f
  14.                           This parameter can be a value of @ref CAN_identifier_type */
    3 @: l* V& m# X# F
  15. //表示发送的帧类型。如:数据帧、远程帧等  r, n$ n) {' {) Y" w
  16.   uint32_t RTR;      /*!< Specifies the type of frame for the message that will be transmitted.
    2 |3 j# J+ S( i4 G8 {- e! d  r
  17.                           This parameter can be a value of @ref CAN_remote_transmission_request */+ J. D! k3 e5 t" r
  18. //表示发送的数据长度
    / h# O7 y5 S4 J8 l! h' R4 [
  19.   uint32_t DLC;      /*!< Specifies the length of the frame that will be transmitted.* a& @! s* r# B8 d8 v7 I. R1 e
  20.                           This parameter must be a number between Min_Data = 0 and Max_Data = 8. */2 q; d  b" l; n. I) X2 i9 N" K- i
  21. / ^, }1 J' E) C6 c- z
  22.   FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start1 s& A( E$ j$ ?" S7 o
  23.                           of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].9 ]% ^* @  w% n( t5 E# h& g
  24.                           @note: Time Triggered Communication Mode must be enabled.  ]5 g8 G$ n. \& I  w3 m/ A4 D5 P
  25.                           @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.% U) k2 E2 }: t+ |
  26.                           This parameter can be set to ENABLE or DISABLE. */5 O7 X; @+ Z8 o) |$ I" {. }, ^& t  J
  27. 4 ?! b$ \: C- N+ E  _
  28. } CAN_TxHeaderTypeDef;
复制代码

- C: |* j3 {  }6 t0 c

7、过滤器:为了方便接收想要的ID,过滤掉不想要的ID。28组或14组过滤器,每组2个32为寄存器: P; d* N% w( L* n
屏蔽模式
8 E4 J8 x% s) T) B. y  `: O7 Z5 v8 R屏蔽位模式: 标识符寄存器(设置想接收的ID)和屏蔽寄存器(设置关心的位)。又比如说,当你值接收一个固定的 ID 的时候,你 把屏蔽寄存器全部设置为 1(即必须比较),然后在标示符寄存器里面存放你3 v% N4 T. Z5 v( r
想要的接收的 ID,那么当 CAN 总线上面出现你想要的 ID 的时候,它就将它接收,其他的不接收。# N0 L4 ]& H1 i+ S( s- l1 t' J
屏蔽列表模式:每组过滤器 中的两个寄存器全部用来做标示符寄存器,也就是说当接收的 ID 必须跟表 示符寄存器中的 ID 相同的时候才接收。


5 |0 B/ |- A  D3 _


9 _/ ~/ a: H/ u7 J5 K

8、过滤器结构体

0 A( v" f) R! g. _$ q
& h* B2 T" n7 U2 t& Q" E( D6 o
  1. /**
    . i$ H9 w1 Q. T) ^, C' z: g4 k
  2.   * @brief  CAN filter configuration structure definition, K& O& I2 Y5 O( a
  3.   */- s9 |0 E( O. _" }, l9 t
  4. typedef struct
    6 }4 w/ i9 ?; _) w8 B6 D. N
  5. {
    ' m( V* r+ {" Z" n; J
  6.         //这个是标示符寄存器的高 16 位- k( v9 n( Y  L# g1 f9 r
  7.   uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit- X& d: O( l4 ?8 y& H
  8.                                        configuration, first one for a 16-bit configuration).  \* ?6 u( O) D/ e6 B* r% C( V, o; |1 [
  9.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */7 R8 X: G5 L( M
  10.         //这个是标示符寄存器的低 16 位2 M& y' \% l/ O$ Q
  11.   uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit- Y  H# T/ z) N" J
  12.                                        configuration, second one for a 16-bit configuration).. A: z3 d* [3 n& C! I3 I/ B
  13.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    , b/ s- X. B( H9 s
  14.         //这个是屏蔽寄存器高字节的设置6 d1 X1 N1 Q# P: x  H5 u
  15.   uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,& Z8 n: j, \7 Z# e. |  T
  16.                                        according to the mode (MSBs for a 32-bit configuration,
    : A+ v* R  o# M
  17.                                        first one for a 16-bit configuration).) S0 \) f- l+ |; K; y5 s
  18.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */; |  }" B: H1 d( {0 {* g2 _# [
  19.         //这个是屏蔽寄存器低字节的设置
    $ x& e7 b2 d3 z0 `  ]9 q
  20.   uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
    % s, q+ Q  Q0 p; s
  21.                                        according to the mode (LSBs for a 32-bit configuration," w4 M6 E6 s+ V2 L% u( j) `
  22.                                        second one for a 16-bit configuration).
    % c# Q: h; H* w& Z) [& r0 J5 e) X
  23.                                        This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
    & s1 e! @; |4 |2 j+ h) \# X
  24.         //选择你要使用的邮箱,它有 0 和 10 Z0 e3 C3 w  U0 F, B
  25.   uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
    . R1 V6 j* j5 Y+ f
  26.                                        This parameter can be a value of @ref CAN_filter_FIFO */
    0 V2 B( @, m3 M, E, N
  27.   //表示标示符寄存器的ID,)我们这里使用第一组寄存器设置为:1。 % j1 K$ z/ p5 W* b8 W( [# `: R$ T
  28.   uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.8 }7 \' T0 a: U7 C  R/ W
  29.                                        For single CAN instance(14 dedicated filter banks)," r  Y1 x5 i" u) f2 L5 O, s1 A6 J
  30.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 13.
    3 S, b1 C4 O* R/ H' y/ n
  31.                                        For dual CAN instances(28 filter banks shared),& |. M- [9 k( Y6 k
  32.                                        this parameter must be a number between Min_Data = 0 and Max_Data = 27. */6 g; q! i3 X( ^8 ~2 P# [+ b( J  [
  33. //表示过滤模式。我们上面讲到它有屏蔽位模式和7 J' B' d2 K/ s  A+ d4 V! t( P
  34. //标示符列表模式。我们使用屏蔽位模式,所以设置为 :' u5 j3 c! {! P8 M! W  [6 G
  35. //CAN_FilterMode_IdMask。
    2 H' O! q; y' m7 Y& D7 a
  36.   uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized., @  }/ e4 p" X& O; T3 b/ z
  37.                                        This parameter can be a value of @ref CAN_filter_mode */
      C$ m' Z- N. u
  38. //表示设置过滤器的长度。过滤器是可以设置为16位和32位两种模式的(即接收标准帧和拓展帧的区别)。
    1 B4 }5 U& D3 F; O  h
  39.   uint32_t FilterScale;           /*!< Specifies the filter scale.' g( \! g7 X1 l) P, U
  40.                                        This parameter can be a value of @ref CAN_filter_scale */( i, K; m( V+ S) e  R) r" V8 V
  41. //表示过滤器的使能
    # q$ |$ l# N5 g8 c
  42.   uint32_t FilterActivation;      /*!< Enable or disable the filter.6 r* Z; z2 w+ ^
  43.                                        This parameter can be a value of @ref CAN_filter_activation */* C* F; ]4 ]1 s  j" p* B

  44. * v$ ], @+ r' N1 \, u
  45.   uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.8 g) G% l+ K9 ]8 m
  46.                                        For single CAN instances, this parameter is meaningless.
    4 I7 n6 d, j3 ^6 B. B, T
  47.                                        For dual CAN instances, all filter banks with lower index are assigned to master
    + t: ]. i& z  }& l, v/ q' O& @7 i1 I7 S
  48.                                        CAN instance, whereas all filter banks with greater index are assigned to slave
    4 ~4 E" |" M( c0 x* }+ j8 a
  49.                                        CAN instance.; c1 B2 w' M7 ?* Q
  50.                                        This parameter must be a number between Min_Data = 0 and Max_Data = 27. */1 C' U5 {% b6 o1 v) z
  51. } CAN_FilterTypeDef;
    * l$ M+ F3 j" M8 S
复制代码
7 Q. J  }* i- L

4 e8 Y% v. J( h
赞 2 收藏 2 评论1 发布时间:2020-9-28 13:43

举报

1个回答
yklstudent 回答时间:2020-9-29 08:29:13
不应该中断方式发送多包嘛

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版