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

STM32-CubeMX-实现CAN通讯

[复制链接]
STMCU-管管 发布时间:2020-10-19 13:07
STM32-CubeMX-实现CAN通讯

/ c: d6 X  a0 d  K1 p
0 @/ ~' k6 P) }; h
首先要安装cubemx跟Keil5两个编程软件,然后打开cubemx软件,新建一个工程项目:5 U4 B- `) i" `4 Z2 X  l, S' T5 _
11.png
7 j" O+ V2 {6 i6 ~. M7 a    输入CPU型号:; Z5 p/ ~2 U% ~( L7 _; y+ G- f" z
12.png ' P- M0 }& k  a) Y3 {6 T- r9 M' s
    在右下角双击CPU具体型号:. U- S$ z- U/ Z/ B( ]# o' W2 R
13.png
( k; m" Y! Q1 k; D6 ?* ^- {& L    稍等片刻会打开如下对话框:
* F# _$ ]) M5 w: }& G4 k6 A; k 14.png 3 J! I# E2 x6 K5 o8 f% _# ~2 P
    首先要配置系统的调试方式:我们选择SW方式,' x( L! p# z$ d  m; G9 Q. L
15.png
, S( M) \  K9 D    然后配置晶振源,这里选择的是外部晶振,8M,
5 B) o- I. H4 u. n. f- u 16.png / ~# X1 M: U6 G" s
    使能看门狗,% @" R8 F1 ]6 I8 g3 y
17.png
) w4 l2 i) I! Y    使能CAN,) l8 ?/ ]$ G6 t* [
18.png
' l7 M1 q5 B1 t1 b0 Q, I7 N9 N' L    使能TIM2时钟源,采用内部时钟,
& @8 T1 g# R% W* }" R 19.png - D5 ^7 `1 ~+ u/ s& C' o; Q
    配置完成后可以看到单片机管脚已经做了配置。+ ?. q1 i6 u  [  R3 y( j
20.png
* s+ z1 |' A; j, y$ ~    切换到Clock Configuration选项卡,配置时钟周期,这里配置为8M+ h4 C) [4 N$ s
21.png
- O. H* s6 R4 r1 i- o" }    切换到Configuration选项卡,进入CAN配置选项配置波特率如下为500Kbps。+ `9 c+ F& G$ `6 \2 ?
22.png " v! C, n. h) J: C
    配置接收中断。2 }+ @7 f. D; D: p
23.png
3 [5 I4 i" q, ]1 Q9 c    配置定时器如下为1ms定时器。
* Z3 f% K9 t  y3 v, |" n) V 24.png
8 t6 z7 L) u$ @& l& c( A% X& y    配置定时器中断4 p3 s$ X% E1 B3 C! \" `. K3 Y
25.png
( O8 }, ]' R% K! s& @) |. g8 y" L4 A    配置完成后点击保存,然后点击如下按钮,生成代码9 T# W2 s4 V$ V3 g1 L  D: x
26.png 4 ]$ q8 z4 e3 ^) j# p9 |
    填写工程名称,路径,编程软件等等
9 N2 s) C* R' J6 l8 q 27.png
9 _# E; \1 t2 t+ d1 V    选择生成代码的方式0 d: M3 F  G5 Y6 V) t" l
28.png - [; s  M' N* O1 b# i/ a0 W0 V
    等待……
) I# z4 q8 R$ V+ ~4 s4 d    之后点击打开项目。代码生成部分完成。
/ y* F1 L$ V' S  L 29.png
, I8 {# k5 A/ K9 o* c    添加一些特殊配置和逻辑代码,添加CAN的配置信息函数。$ i' A; c7 h9 B: q1 e% X

0 N, `+ j0 }/ E6 [$ p' n* P0 k% Q
' f% ~5 D& r! X) c
  1. void Can_Config(void)
    * ^9 a7 o  n- z' C& f
  2. {
    & [$ y0 X# x9 H& ]$ M* u* G% f7 S
  3.   hcan.pTxMsg = &TxMessage;
    ! E% j% H" A5 V7 J: E
  4.   hcan.pRxMsg = &RxMessage;, O& }: N, g( C1 l
  5. 7 S. c, A$ q. w8 T/ A$ D9 u0 ^
  6.   /*##-1- Configure CAN1 Transmission Massage #####################################*/, b( K4 |9 ^7 j6 s
  7.   hcan.pTxMsg->StdId = 0x123;
    6 A0 l. [3 ~3 j. s' l* j
  8.   hcan.pTxMsg->RTR = CAN_RTR_DATA;
    ! J8 `- u- }4 e- A
  9.   hcan.pTxMsg->IDE = CAN_ID_STD;
    3 d1 F! U; Q. X! u2 J+ E% N
  10.   hcan.pTxMsg->DLC = 8;8 L6 n% o3 J. R6 f8 `
  11. , u2 f5 O2 M9 i5 x" w: [
  12.   /*##-2- Configure the CAN1 Filter ###########################################*/% {4 L2 R0 e( K3 G9 W2 e$ }% X
  13.   sFilterConfig.FilterNumber = 0;
    ( G. z0 x4 f1 d2 K* h) i1 O7 k3 V- n$ }
  14.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    1 ^" t! p" Q9 l  A7 G
  15.   sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;0 l/ I! t  {  w4 e) [) ?
  16.   sFilterConfig.FilterIdHigh = 0;
    0 ~' s$ i9 Z! q7 L. ?
  17.   sFilterConfig.FilterIdLow = 0;; d( i4 g" [/ Q  ]4 p! f& K
  18.   sFilterConfig.FilterMaskIdHigh = 0;1 _/ B: z; V; y& J/ ?
  19.   sFilterConfig.FilterMaskIdLow = 0;
    , o2 l9 u" I9 W" [
  20.   sFilterConfig.FilterFIFOAssignment = CAN_FIFO0;' ~" Z. b9 t. `9 }
  21.   sFilterConfig.FilterActivation = ENABLE;
    2 `! t3 |9 G( }
  22.   sFilterConfig.BankNumber = 14;! W7 M! J! ~8 Z' P
  23.   HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);9 Q6 J) v3 J6 `5 e% M1 ?* u$ E, e
  24. }
复制代码
2 ]# d- J! T9 [7 R9 ^, Z; f! q6 M

) G3 B( f5 I$ q8 g4 t
; N+ y/ p4 m% p$ @

- |& w7 }' g' O3 }, y在Main函数中while(1)之前调用一下即可,添加定时器启动函数:: X2 ]5 z8 d0 t7 @
0 R7 {* |" y1 s& D

2 y) Z* N* q1 l, G
  1. HAL_TIM_Base_Start_IT(&htim2);
复制代码

9 J' h/ [; }- u3 _. S1 i/ k
( f2 {0 t( e8 A- a- K+ C
CAN接收中断启动函数:
7 q- r, [2 B2 B
! {) o! x/ F/ {7 K/ T! _* W

, e% D" f5 N9 X" g+ u

  1. ( s5 ]" n- E  U
  2. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);% ?0 U, q- E- R. f
  3. /* USER CODE BEGIN 2 */
    : b  e5 G, a; X9 F4 i: H5 d
  4. / K4 o6 F& u9 k" e2 @% ]
  5. Can_Config();                        //Can配置信息
    % i- U3 a% d- O# H6 Z! s8 W
  6. HAL_TIM_Base_Start_IT(&htim2);       //定时器启动
    , d# ?" _0 [5 F/ [. c  z
  7. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//使能Can接收中断
    - k  _7 L9 r. n/ n5 O  A

  8. 8 \1 ~& e' c& {' x( J
  9.   /* USER CODE END 2 */
复制代码
; Z8 p5 S% w, H

: y3 a1 @9 U( x+ o# Z+ [ 打开stm32f1xx_it.c文件,找到如下函数,添加接收中断启动函数:
8 |6 F6 z, N& R, J8 ]
1 \1 X4 ^' a  ^9 R

. L% m2 b9 _4 n8 V: b: I
  1. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
复制代码

% X0 L. L6 W  M% A
7 f, Y' G  y) E; j6 ]8 [
注意:接收中断启动函数使能一次只进一次中断,所以中断退出前要再次使能。  T) c) @' ^5 d$ |+ S

/ n  \0 ]2 V0 \" I8 }5 h) f

! R) }( ~; G+ A$ E
  1. , c4 y" P$ P2 W0 r7 ~% p
  2. void USB_LP_CAN1_RX0_IRQHandler(void)
    5 J  {- w* ?* }/ k% q
  3. {, r& m" u. Z% m+ Z  [
  4.   /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */
    / P9 }0 y5 |- }5 l/ k

  5. # S% V6 V3 A' T7 }+ P
  6.   /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */
    ) ^9 M/ ^" u' d0 c' q
  7.   HAL_CAN_IRQHandler(&hcan);
    ) f9 I9 \" F+ |" M7 J. O* ]# N1 }
  8.   /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */7 s' K/ n2 G4 W+ B
  9.   HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//ʹÄÜCAN½ÓÊÕ( J  i% p3 ~% m3 m2 L' k
  10.   /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */- y, u# T9 M& ]
  11. }
复制代码
/ F" _/ c4 g& ~6 i# _
: `8 o+ n+ Q  z7 g; O4 R
添加CAN接收服务函数:
. U# G$ `) \& m. P* h. N
& m# E: \& O9 ?9 q2 C0 q7 a2 Y/ Q8 t3 \
4 K4 r( k$ R, T: f7 U& V* Y
  1. HAL_CAN_RxCpltCallback
复制代码

3 c6 H) N+ C1 \0 S& ]0 A% v

, h0 q$ q/ H; ?" A$ Q: U& C% |+ R  说明:该函数在stm32f1xx_hal_can.c文件中已经有定义,它的定义方式如下:) W" v, N( c3 h" R) p

" @+ {! K" o& M% B8 y

8 i! x$ F3 J) i
  1. __weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
复制代码

, [6 r' ^. p! M( b8 T
$ m! w% {- t+ c
函数前面的__weak关键字意思是如果有同样的定义,先执行没有__weak关键字的函数,所以当我们定义了HAL_CAN_RxCpltCallback函数后,编译器会先编译我们定义的函数,而忽略系统定义的该函数。当我们没有定义该函数时,系统会编译带有__weak关键字的函数。5 E( t" b& y8 `. d3 v+ ~, W
9 [5 Y" {% W6 J1 t( u* M
: e# }: |- H" i7 z( l3 M. N

  1. / J: b' q3 V* d8 ]7 w+ l! H
  2. void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)1 q, ]  u6 z2 D8 T, q
  3. {; {- `" j9 B& B) ~4 U; h9 e
  4.     unsigned short int speed;
    , A& _6 N8 e! u5 ?7 P
  5.     switch(hcan->pRxMsg->StdId). y2 \6 {, t$ D4 E  ]4 M. f! N
  6.     {//根据ID处理数据9 }: S7 w9 B% p
  7.         case 0x123://
    9 o# ^' f5 l- p7 r. ?! O
  8.         /*在此添加数据处理逻辑*/1 Z' q* Z  w. ]; v5 D) |8 u
  9.         break;8 h$ W1 \) }& d. R& }1 z9 n
  10.         default:
    * V0 r. Q% x; D+ {! k# ^% H
  11.         break;
    * T8 A: W$ a1 A2 g4 j" q9 ~
  12.      }7 B4 w2 c6 B' m8 A
  13. }
复制代码

# y9 ~# S+ o2 ]3 T- ?& k8 s6 |
3 b8 N3 \- W4 k# ]" h3 @
添加CAN发送函数:$ b; |5 y- y5 ^" d  V

+ s- Q/ ~$ O9 s( Q) _
0 [. v1 ~$ V, M4 [( i1 p6 c
  1. /* USER CODE BEGIN WHILE */- Y( `8 s8 G! F
  2.   while (1)
    , ^, D  }/ n7 ^2 p  \& h
  3.   {9 s6 ^$ i" f- |: ?- j
  4.         HAL_IWDG_Refresh(&hiwdg); //喂狗函数3 K, |2 y6 D: o4 n' t( O
  5. 5 h" H1 M; P  G$ H7 ~$ b1 b
  6.         if(Can_Trans_Timer == 0)5 m8 P& G, {& }9 v1 k: t% L
  7.         {//每100ms发送一次数据( E* P, P7 q7 ~/ P; N
  8.             Can_Trans_Timer = 100;) t- }' X/ u9 f4 ]

  9. , E. F; u: }# Z4 h. a! n6 {+ ~

  10. ! p  d+ T8 F+ Z5 |+ r+ x! r
  11.             hcan.pTxMsg->StdId = 0x123;  f& c5 _/ h$ S6 o. x: \# f! v! u# F
  12.   ~6 @2 ~5 ~+ h' ~
  13.             hcan.pTxMsg->Data[0] = 'C';4 _) C* a( g) R( k
  14.             hcan.pTxMsg->Data[1] = 'A';
    ) l; n  b+ d+ K; s8 [- A0 V
  15.             hcan.pTxMsg->Data[2] = 'N';
    ! L9 ]9 ?* k2 k3 {
  16.             hcan.pTxMsg->Data[3] = ' ';
    7 `8 E1 F6 B1 E
  17.             hcan.pTxMsg->Data[4] = 'T';2 j  K8 a+ O& v& O: C8 r
  18.             hcan.pTxMsg->Data[5] = 'E';
    ( h: ]# c3 O1 S+ Z9 {
  19.             hcan.pTxMsg->Data[6] = 'S';& p% o0 z5 v9 v$ i( w8 Z% @9 n
  20.             hcan.pTxMsg->Data[7] = 'T';  t- {' [7 U* G1 p/ A
  21. 3 N* _6 Z' e( L& Z) {& K

  22. 5 q# z; f4 w; W# D  i. S
  23.             HAL_CAN_Transmit(&hcan, 200);//发送一帧数据
    + F) v5 g8 |9 a$ h! H' u
  24.         }
    2 b, C- K! r6 v; x, S# ~$ u3 y# f
  25.     }6 D7 ~5 z3 C, D
  26.   /* USER CODE END WHILE */
复制代码

2 C6 P( f4 ^8 |
* x0 `6 i: ^3 P2 R
在定时器函数中添加定时器代码:4 J" A: \0 e. |7 i5 D
  G& A3 L* f2 d8 B( \9 Y% }
6 I4 W4 _  P$ O0 r" }

  1. 0 G1 z1 U0 s, }$ I  b# D9 |3 ~4 n
  2. void TIM2_IRQHandler(void)
    3 |* g* s4 Q8 ], Z  ]9 t3 J& k. k) b
  3. {
    7 l. `3 r# J- k
  4.   /* USER CODE BEGIN TIM2_IRQn 0 */
    , z# j8 x% H# i# s7 o; h
  5.   if(Can_Trans_Timer > 0)          Can_Trans_Timer--;" U; G; _1 I8 j
  6.   /* USER CODE END TIM2_IRQn 0 */9 v4 A: _" R! B3 X
  7.   HAL_TIM_IRQHandler(&htim2);
    8 l  @  U! f- `  K- {
  8.   /* USER CODE BEGIN TIM2_IRQn 1 */9 c' F. w( J/ x" v* d  U

  9. ' }% U% w. {' K9 Y
  10. , I; [; k) r( g% P3 s5 m% [+ \
  11.   /* USER CODE END TIM2_IRQn 1 */
    2 K& d2 j8 \$ E9 I( a
  12. }
复制代码
4 Z% Y( w" r% s, P  q5 e
" t8 u& d: h5 _& c- Z
说明:在往工程中添加代码时要注意,不要任意往里面添加代码,要在注释着USER CODE BEGIN的地方添加代码,这样在重新生成代码时才不至于将已经写好的代码覆盖掉,如下: c  K9 Z7 v/ m+ o2 ]! N
2 ?- O) C1 }5 a; [7 M

! `; }4 t- F$ M& {- [/ T4 Q4 E

  1. ' P9 D; w  k3 c8 j  W8 z% p6 T
  2. /* USER CODE BEGIN Includes */
复制代码

$ @8 j- Q/ u" l# G/ @/ a: @

: w- p* b8 W9 c: Y" O' @7 M: N% S: H
( W! Y1 Y. u" N% H
8 D6 ?, K# Y& X
7 a( K8 l- Y: v# W. x0 ^6 T/ r
1 F; i; A9 M/ |3 n$ C' C

$ R6 P% j7 f0 ?; T
: l# ?. x8 |% \
7 j7 F6 {9 D7 t$ @' R

2 g' q6 r/ X6 o& S5 Z4 c: h, |
! A- T& s# T! Q6 b- q, m; P
; Z! m; H( R9 b2 {9 |' T
! H& s, ~! _1 F

) {( v- Z6 g$ l2 h* G
收藏 3 评论1 发布时间:2020-10-19 13:07

举报

1个回答
g921002 回答时间:2020-10-20 22:50:40
新版的HAL已經不是這樣寫了。
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版