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

【经验分享】STM32-CubeMX-实现CAN通讯

[复制链接]
STMCU小助手 发布时间:2022-6-26 11:29
  首先要安装cubemx跟Keil5两个编程软件,然后打开cubemx软件,新建一个工程项目:

( e1 H; k( ~% _3 X, q/ J, h; ~
微信图片_20220626112734.jpg

: `9 J. G0 r/ h8 h- k
    输入CPU型号:
9 Q  \0 ]8 I4 x& B
微信图片_20220626112737.jpg
" |7 v; m' K9 Z' ^
    在右下角双击CPU具体型号:

/ F8 V9 M# Q/ I% A( n" G
微信图片_20220626112740.jpg
4 a! a5 k4 @( a' X( }- o# D
    稍等片刻会打开如下对话框:
' a! y! f5 Q7 e& ?1 N
微信图片_20220626112750.jpg

7 Y) N# ^5 I2 V
    首先要配置系统的调试方式:我们选择SW方式,

+ d! ^: }$ C/ v1 l; j( c
微信图片_20220626112755.jpg

' y, P% v. ?+ m8 I+ j/ h3 t
    然后配置晶振源,这里选择的是外部晶振,8M,

$ t% p! ^( d# K5 o9 k: |
微信图片_20220626112758.jpg
; S3 H: Y2 i9 f3 @+ D( d' `  ^) @
    使能看门狗,
8 q3 K4 S) E. B4 g
微信图片_20220626112805.jpg
  Q1 Q1 E4 y, G. A. ^& Z% [( e  ^
    使能CAN,
% L$ h2 e$ k, B- L# g% s
微信图片_20220626112810.jpg

$ d2 ^: T. k8 B  a5 e; v
    使能TIM2时钟源,采用内部时钟,
: @8 {8 f3 A( c6 ?" a$ W6 _
微信图片_20220626112817.jpg

' L7 H. u% M0 c% C6 }
    配置完成后可以看到单片机管脚已经做了配置。

- F+ }5 T; h- J, F
微信图片_20220626112826.png

% |6 |5 K( n3 y% z* B
    切换到Clock Configuration选项卡,配置时钟周期,这里配置为8M
" P3 A% Z& F' ^7 @

$ ^/ s; ^, p3 n+ o) E
微信图片_20220626112835.png

" W5 V7 X( f! ~5 R) h# ]6 A
    切换到Configuration选项卡,进入CAN配置选项配置波特率如下为500Kbps。( W/ n6 G& ^4 ]' b
/ K: s3 U" |- W0 L0 V- Y" _
微信图片_20220626112838.png
+ n& |' G: b- @. ^6 s
    配置接收中断。
' y. G5 W& b2 Q/ |7 @. M, i+ J
! ]7 Y( F) S$ p3 |5 r
微信图片_20220626112842.png
) `- O& T* M) a8 F
    配置定时器如下为1ms定时器。
0 b7 O1 o3 ~- K8 R/ d/ }
0 B% t( E& E5 w+ o" p
微信图片_20220626112845.png
% n6 E2 I2 p2 N' v
    配置定时器中断
$ ?# m8 @" |6 X# Q; i' I& ~6 n+ G/ b4 _- g

, R3 B- F7 Q1 b' @2 C
微信图片_20220626112847.png
2 e3 y. [1 Z4 u. z; X1 N5 L5 @6 r
    配置完成后点击保存,然后点击如下按钮,生成代码
$ ?8 G- I) L) h8 O) ^  H* T
+ t/ `$ b0 _. s! t; o
微信图片_20220626112850.png

0 U6 b1 N: `3 R, m2 Q
    填写工程名称,路径,编程软件等等5 k/ `) d; g# I% o; D* ^

' o5 }( s. E8 V% b
微信图片_20220626112853.png
; z/ I5 J! v. Z3 L" t, J" c$ t
    选择生成代码的方式4 g9 x, O- j8 @- X2 E* c

/ ]) u, B1 J- _+ [6 Q! K% L4 s
微信图片_20220626112857.png

2 B  N7 Q- t+ i! F9 S, d) |' [
    等待……
    之后点击打开项目。代码生成部分完成。

/ n1 R/ Q# n) s. X8 k6 [
微信图片_20220626112901.png
& a! r. \; x, W5 @  N5 y2 C
    添加一些特殊配置和逻辑代码,添加CAN的配置信息函数。
  1. void Can_Config(void)
    # W7 t  O% R8 o' a3 p
  2. {
    ) X9 X& ]8 z, t1 U6 }
  3.   hcan.pTxMsg = &TxMessage;* M8 A# K, T+ `$ Z# }$ k
  4.   hcan.pRxMsg = &RxMessage;# P3 w( `8 i0 y0 o# g
  5. : m1 y# _3 Z0 ?4 `1 X8 B6 n% ?
  6.   /*##-1- Configure CAN1 Transmission Massage #####################################*/* g9 G4 l. O" f9 D2 r+ z7 Y9 `
  7.   hcan.pTxMsg->StdId = 0x123;2 G' z# \7 F" P5 C8 [3 j3 g( d
  8.   hcan.pTxMsg->RTR = CAN_RTR_DATA;
    9 j8 x' x) @- L/ ?4 ]1 u
  9.   hcan.pTxMsg->IDE = CAN_ID_STD;6 i2 s+ V0 B7 X' n5 I' `. w
  10.   hcan.pTxMsg->DLC = 8;* e2 t# i% r& n1 L' Z1 y

  11. 6 X9 @, s  X# x) b0 p
  12.   /*##-2- Configure the CAN1 Filter ###########################################*/
    * j: c2 H, J: J8 X2 `) ^9 @
  13.   sFilterConfig.FilterNumber = 0;
    $ t/ ?$ b  j# Q
  14.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;! J% C0 r- O5 ]* ~4 h$ R
  15.   sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
    & s. ?+ b, K+ C( p; i  Q
  16.   sFilterConfig.FilterIdHigh = 0;8 ]  C  s9 P3 N/ [! `
  17.   sFilterConfig.FilterIdLow = 0;. x3 d7 _, ?! n1 K
  18.   sFilterConfig.FilterMaskIdHigh = 0;4 H. ~- R% H  Y, x  n4 X2 g
  19.   sFilterConfig.FilterMaskIdLow = 0;
    4 N  z. S; E! O6 V$ [
  20.   sFilterConfig.FilterFIFOAssignment = CAN_FIFO0;
    ( n9 ~# v( w% L4 H" K8 _$ |
  21.   sFilterConfig.FilterActivation = ENABLE;
    : h8 P0 P9 g2 Q' @! t
  22.   sFilterConfig.BankNumber = 14;$ Y1 _0 O2 e$ B7 z8 {
  23.   HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);# Y! j% s. m7 x; D- k
  24. }
复制代码

  s" R9 F+ N6 E& y) j
在Main函数中while(1)之前调用一下即可,添加定时器启动函数:
  1. HAL_TIM_Base_Start_IT(&htim2);
复制代码
* ^/ }& l5 m, x
    CAN接收中断启动函数:
  1. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);5 y/ d+ z  K3 G4 ^. [/ P+ @5 Y
  2. /* USER CODE BEGIN 2 */) D. F* f) N' r% z

  3. ; g/ g( ^( g- f% f
  4. Can_Config();                        //Can配置信息/ }9 I) j9 T9 r
  5. HAL_TIM_Base_Start_IT(&htim2);       //定时器启动
    ; C) v' O' S; _
  6. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//使能Can接收中断
    ; _9 ?" x0 M4 p& a4 L) H
  7. 0 ^1 @% J8 K2 L, J7 X' m, R% b
  8.   /* USER CODE END 2 */
复制代码

& k$ [9 r, r' V5 @2 O- x3 g
    打开stm32f1xx_it.c文件,找到如下函数,添加接收中断启动函数:
  1. HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);
复制代码
0 Y0 Q9 o' r5 i5 K) Z' |0 T
    注意:接收中断启动函数使能一次只进一次中断,所以中断退出前要再次使能。
  1. void USB_LP_CAN1_RX0_IRQHandler(void)7 x# c4 ]9 r  K3 i) m6 C/ \
  2. {' I" U- v* @4 S
  3.   /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 0 */( S  m2 H6 Y" {8 S0 Y% V+ i
  4. ( w* Y; P; Y- A: p
  5.   /* USER CODE END USB_LP_CAN1_RX0_IRQn 0 */
    0 x. x, Z, u1 ~# q, C: b/ p0 \
  6.   HAL_CAN_IRQHandler(&hcan);
    , u" V: i% Z: ~& |) v
  7.   /* USER CODE BEGIN USB_LP_CAN1_RX0_IRQn 1 */
    : v3 t" E0 V9 T
  8.   HAL_CAN_Receive_IT(&hcan, CAN_FIFO0);//ʹÄÜCAN½ÓÊÕ8 a' p$ E3 o$ s3 I! O" T
  9.   /* USER CODE END USB_LP_CAN1_RX0_IRQn 1 */" Y. E0 {+ x+ \7 g* s/ T
  10. }
复制代码

- F. J$ q1 D. }- B8 r* X% X
添加CAN接收服务函数:
  1. HAL_CAN_RxCpltCallback
复制代码

* i% l( S4 [$ K1 O$ A, X+ u) X; t
    说明:该函数在stm32f1xx_hal_can.c文件中已经有定义,它的定义方式如下:
  1. __weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
复制代码

; F- c9 ^$ s( b& N$ L8 w    函数前面的__weak关键字意思是如果有同样的定义,先执行没有__weak关键字的函数,所以当我们定义了HAL_CAN_RxCpltCallback函数后,编译器会先编译我们定义的函数,而忽略系统定义的该函数。当我们没有定义该函数时,系统会编译带有__weak关键字的函数。
  1. void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
    * _* I3 y- [& j0 e* d) D
  2. {
    ; b' H2 P2 y7 R) x  m$ @5 {
  3.     unsigned short int speed;1 `3 q) \% {$ g, U1 y
  4.     switch(hcan->pRxMsg->StdId)# j/ n/ X, w) V$ \1 a* U5 q- e
  5.     {//根据ID处理数据' x% J, U- w2 L
  6.         case 0x123://8 r( b! r9 b  }0 E* [) v5 ~
  7.         /*在此添加数据处理逻辑*/$ C( P! _* t/ v3 ?
  8.         break;
    . ^  S  y9 K' P* m$ C
  9.         default:
    8 ~+ Y& G' Y( C9 D
  10.         break;
    / V; j8 L0 l# _9 e
  11.      }- s6 G4 T+ Q0 s: l( r4 _
  12. }
复制代码

  X1 t( n3 D# `9 w9 K+ r
添加CAN发送函数:
  1. /* USER CODE BEGIN WHILE */
    $ S9 j* b3 W0 b) j/ g% k) {
  2.   while (1)3 c$ u3 p2 L, a! c% N
  3.   {
    $ K7 f  f$ q# i7 y  N3 ^
  4.         HAL_IWDG_Refresh(&hiwdg); //喂狗函数
    " b2 V! U2 n9 I/ t1 I- l$ \

  5. & o. a5 C7 q% {2 {
  6.         if(Can_Trans_Timer == 0)- j% Q7 K$ Z9 ]. Z
  7.         {//每100ms发送一次数据! V3 T7 |- |* X: m. Y+ f
  8.             Can_Trans_Timer = 100;
    1 A, @: X/ O5 W; r, L( Q1 c4 O
  9. ; s( N* O5 _  h6 j! b# c6 B
  10. 6 l, F1 c+ ^7 y8 A* ]' E, Y0 S9 S
  11.             hcan.pTxMsg->StdId = 0x123;& `: Q3 u5 T- l; \. ]- S' U5 r) B6 g
  12. 3 c5 H  ~+ W5 T5 {. Q3 k
  13.             hcan.pTxMsg->Data[0] = 'C';
    5 a& r( P+ V7 y4 `* W
  14.             hcan.pTxMsg->Data[1] = 'A';# c7 I! q* n$ R/ W" h7 q! N
  15.             hcan.pTxMsg->Data[2] = 'N';
    % x: J7 |7 ?; q
  16.             hcan.pTxMsg->Data[3] = ' ';
    + O- ?% A/ ]8 z3 r; Z  L/ w( E
  17.             hcan.pTxMsg->Data[4] = 'T';
    ! F) m% g7 @  I) O1 M" P" `# E
  18.             hcan.pTxMsg->Data[5] = 'E';
    " O5 C" P. i1 g4 ^2 K
  19.             hcan.pTxMsg->Data[6] = 'S';
    8 c% N' V9 ~, u) i
  20.             hcan.pTxMsg->Data[7] = 'T';
    6 N  g% C6 M0 \6 T# E2 ], |
  21. + F) c0 X' t: v+ ?2 \# Y
  22. 4 Y* c/ m2 O! T0 V' q# K5 b* v
  23.             HAL_CAN_Transmit(&hcan, 200);//发送一帧数据* H# e8 n* J' U" u
  24.         }  B. h& t2 p0 E1 W
  25.     }
    * |/ @3 `" v6 ~! R# q3 t5 F' u( a
  26.   /* USER CODE END WHILE */
复制代码

5 d+ S& q3 Y3 b, O% Z2 u; @2 h! M
在定时器函数中添加定时器代码:
  1. void TIM2_IRQHandler(void)
    ; P& W5 i6 _! v6 U
  2. {( q* z: `* ]) y+ m2 y
  3.   /* USER CODE BEGIN TIM2_IRQn 0 */4 u; _* ?( q1 H3 {% {
  4.   if(Can_Trans_Timer > 0)          Can_Trans_Timer--;5 G% g4 ]) ]0 }( B* ^/ A" X( r
  5.   /* USER CODE END TIM2_IRQn 0 */
    7 f8 q4 r% h0 k( H- y% {& y
  6.   HAL_TIM_IRQHandler(&htim2);
    ; m3 i- ~6 b) w: L
  7.   /* USER CODE BEGIN TIM2_IRQn 1 */" u- \" `# V8 j5 S( R

  8. 9 j, D# A( Q0 K1 e8 z" M1 }

  9. % G3 f2 B! f9 y+ x; N, q. a
  10.   /* USER CODE END TIM2_IRQn 1 */
    " t# I. b5 I. p( {2 C. i
  11. }
复制代码

5 D3 N# X0 J( P& d8 i2 Z5 T; y. F2 I
    说明:在往工程中添加代码时要注意,不要任意往里面添加代码,要在注释着USER CODE BEGIN的地方添加代码,这样在重新生成代码时才不至于将已经写好的代码覆盖掉,如下
  1. /* USER CODE BEGIN Includes */
复制代码

" f& K# I/ b9 ~* A. F
赞 收藏 评论0 发布时间:2022-6-26 11:29

举报

0个回答

所属标签

相似技术帖

官网相关资源

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