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

【经验分享】STM32 HAL库 PWM控制电机转速与编码器读取(超详解)

[复制链接]
STMCU小助手 发布时间:2022-5-24 11:05
本篇文章我将针对PWM控制电机与编码器读取电机转速的STM32CubeMX配置过程进行详细的讲解,让准备学习HAL库的小伙伴能够更好的理解STM32CubeMX如何配置。$ j6 Y& r4 E5 U1 }9 ~6 m2 y

/ o! p( i% _# S) f3 Y1、硬件准备
1 \: p/ l3 J9 m2 M(1)所需硬件- P. x4 j0 ^, M! A
; R* m, p; ^) U/ m; U7 d
芯片:STM32F103RCT6
  ?0 S/ Q" u0 s7 W. Q# X* v' E驱动:电机驱动板或TB6612(电机驱动芯片)
. ]8 L+ x6 t# |( P电池:12V Libo电池1 o: _2 L0 m) _7 `& q, U( {; v
电机:带编码器电机8 ~$ V" P9 C5 W; L- M! K
轮子:我用的是麦克纳姆轮
& t# |/ e( K; w; F' z( S: @(2)硬件连接:+ i; a. t6 m( C$ _/ u

& C) a6 v$ v! @* `$ _0 Z+ e4 zPA8 —— 电机驱动板PWM1
) Y  Q: G1 d! F; F. e9 r# aGND —— 电机驱动板PWM2
3 K! y$ l9 U3 ]- w(这里若要反转则PWM1接地,PWM2接PA8;如果在小车中两者都需接PWM引脚,正转:PWM1给一定占空比,PWM2占空比为0)7 [4 {' z$ T/ K5 h
PA9(USART1_RX) —— 接串口TX
# ?/ A6 U* c6 QPA10(USART1_TX) —— 接串口RX
9 \: w/ `+ ^2 o$ N6 ]PB6 —— 编码器A3 r  T4 H; a( a- P& v& m2 H4 R
PB7 —— 编码器B7 x* J; h7 Q6 O& {1 S$ I+ `- R0 n6 G
2、STM32CubeMX配置:- N7 U- ?6 F" n
1.1 所用工具:- X$ h% v; m" [, V) t7 j
! n( I! D1 |# k5 O3 a1 Z; I! x
芯片:STM32F103RCT6
; y7 Q. L5 }. M4 g% H. E  Z3 T3 ~IDE:MDK-Keil软件9 ^6 L! R1 Y& ~6 a
STM32F1xxHAL库
6 `: d3 n" W; c% R
' ?0 `" W3 p/ V! x* d; L' w/ B1.2 知识概括:
& x5 ?! }# T6 I# Y$ f6 v6 X% h6 Q/ ~, w! `% M
STM32CubeMX创建TIMx、USART例程7 e. E2 b2 a; h1 \
Keil软件程序编写2 l4 l9 r; Z5 d
+ i1 s$ s( q1 d2 z2 f  D, }; c
1.3 工程创建
* k4 B" I: b) O* r1、芯片选择
& B- K$ T1 W( c% v7 Z  芯片:STM32F103RCT6(根据自己的板子来进行选择)
# ]9 M  t/ |4 m
. ?  [6 q8 }+ d. u6 N6 c 23D0~9`L~7GL07(I_[N{KE2.png
8 x& ]2 \4 U0 g7 r1 T+ Q( c, I# @/ a9 B: d" L  T
2、设置RCC
6 t. d" `) O: m7 F6 V8 G  设置高速外部时钟HSE 选择外部时钟源2 j- \  D2 e0 y7 I

& s; K1 B% m% G' A PW`{J8OBH2[{M@N[5PNQZ79.png ; f; J  e3 i* P4 e4 f2 R3 {: T/ u
6 ~- Y% c' y. x: |/ I! I: ~+ }
3、LED1配置
' S, D' r8 @9 q, M( K  我使用的板子LED1引脚为PD2,初始电平为高电平,目的是通过观察小灯的亮灭判断是否进入定时器中断
8 E: D6 g+ w6 G4 d5 W1 T% ~. H& t5 ]5 [6 k3 J. J$ D, e
$({RM4FPK)]`4S%9ST`Y2IV.png 0 @7 I) `5 ~% k# Z* K
, s6 t5 K. l  Y% l# k) O; q
4、USART1配置: o; t) j- W' e
  异步收发,波特率默认:115200 Bit/s
4 h8 W: a7 p; ]5 J7 u7 ^5 @! T/ Z+ e- a9 E1 q5 c
H)P`$@T]OH)A_H[{)H(6@YF.png 5 t  X8 [7 }6 Y& o. ~$ f; _
  g' l# \7 d. }
5、PWM配置7 D$ g1 ]" {' F" U# O
  使用定时器1通道1和通道4(TIM1_CH1和TIM1_CH4),频率10KHz2 _, P% N2 T, ^, W) N1 }
* O+ Z9 f* s" Q' M! p0 C& r/ k, W
SOU4}_(_UV`NP()~L2RAZ%6.png # s+ {6 p2 G+ ?0 q3 W7 [+ D  T) m
2 L3 n# p  R5 p: f% V
6、定时器中断配置, I6 T+ ?) M. {
  使用定时器2(TIM2),周期设为10ms,即10ms进一次定时器中断6 Y, m! D; N& w% {
5 q& q9 {$ x7 c! ]7 q1 R  [* `
[6DJT48_KSPB0OWES)C%C.png : z( H$ ?; X0 k! ~( L
# {! B9 H! {; E# X% A8 M: W. I7 U7 ]
  打开更新定时器中断
$ a0 [' z( D" O1 c: R- ?+ [8 Z7 h: j) G1 ]$ x1 l
YOU~W`VS981(97ETMJ_GWQ4.png ( h9 c% T! X) }% C- }! }6 j$ E

/ d2 \+ m6 O4 ?7、编码器配置
' c; W. S6 {+ q' W  STM32自带编码器配置,使用定时器4(TIM4_CH1和TIM4_CH2),打开更新定时器中断
4 N( W* _- ]+ F. {" U8 L* i2 C& y3 q2 Z# o8 A. F
WWM7WN6[4QEZV49ZC(5FD_V.png
9 h' a- c) I2 @
% h  v% o. y4 `/ Y# @  p: R8、中断优先级配置* t! _- [; z* O( u: \" U
  因为编码器中断要发生在定时10ms中断内,故编码器中断的抢占优先级要大于定时10ms* y/ L# Z! V) K  O

! D- |6 |# r. Q, X3 R: [* L }_DSEQOI[MC]KJKD5}(][4V.png
. n, k8 `  J* |! V' e% s4 X& d( Z, f/ j0 S. }7 E3 a6 A
9、配置时钟- Q9 J9 W, s! ^; `
  F1系列芯片系统时钟为72MHzs* M' P5 J9 ~: b% q; M% z5 L$ ?: ]
5 g" I" N/ \+ y! z; P7 B( y" Z( Y
4NX{AV$J28BT0`HN2LHC%GC.png / P2 J% y# D0 b* U
/ Z. Q: B% M) F! v9 u6 o3 \" M
10、项目创建最后步骤
5 d: G: }/ t' ?: D- J0 B- y, {
1 _1 K$ B* v% F0 n  Z7 x8 ]设置项目名称2 B0 m# b' y% `! ^) J* y
选择所用IDE
: k" G4 u8 j  h6 ?
. k/ X- `. ?0 ~1 J4 j3 ^' I$ S _WFXTK(}2ZE8I8EMBL1)[YC.png : ^: s" H. S" Q# A
. S3 ^8 P( x! {" W& W- e
11、输出文件
7 C9 b; A8 |) B  t6 M2 {+ N  e" R) b5 p) g3 w
②处:复制所用文件的.c和.h4 I- l# `3 K% |/ p8 l8 I
③处:每个功能生产独立的.c和.h文件
; ?+ o. D( ]9 S& x7 ^
9 @5 y9 y3 n% m  J5 t WQR2U9C_7V691HYV7Q$VL96.png ) _% R+ W6 }) a; h4 b6 {
; X  [5 `( k' p! F( ]
12、创建工程文件
' j0 t$ @! a3 {' O, m, `% G$ E$ S# {  点击GENERATE CODE 创建工程
! {6 R3 `5 \/ j9 P! e; }; N6 L$ @+ O
13、配置下载工具
2 d7 ~) L. B2 U; e# V  这里我们需要勾选上下载后直接运行,然后进行一次编译
* {) J! c# {! X4 o; c! B2 y
6 ^1 J7 z+ n* G5 J0 J) R. X 6F5%O4Y~9Y2M[QO1[68RUXP.png # S0 {8 \, X. P( N) a" s+ @' s
" e$ f  E( Q8 l7 v+ B
3、STM32源代码:' o3 `5 L; }! r4 L- |* I+ N. H7 t
(1)下面的代码之前有用过hal库的小伙伴应该都很容易理解,小政就不过多解释,有不懂的地方欢迎在评论区下方提问。在main.c加上:
9 y1 R) D% c' N7 t4 B- U! y* L" f' Y$ \. H) e7 B
  1. /* USER CODE BEGIN Includes */
    ( w" a# V: Z% n4 P, Z8 V4 {
  2. #include "stdio.h"
    ) e: a2 [- p# A& ~
  3. #include "math.h"
    , g8 ~5 t& N( x/ ]9 T  o5 l
  4. /* USER CODE END Includes */
复制代码
  1. /* USER CODE BEGIN PV */3 s1 T' ~1 p$ u) r
  2. unsigned int MotorSpeed;  // 电机当前速度数值,从编码器中获取
    & X3 n$ j( k2 X9 H9 |- U0 h: X+ g
  3. int MotorOutput;                  // 电机输出. l7 f2 x; T1 f" Q# p; u
  4. /* USER CODE END PV */
复制代码
  1. /* USER CODE BEGIN 0 */
    # i( x( h, p1 p' I
  2. int fputc(int ch, FILE *p)
    6 a1 a' O! M2 ~$ [3 l3 Q% B! v
  3. {
      r& J# s7 t: v1 p1 R+ t8 d
  4.         while(!(USART1->SR & (1<<7)));, e+ g* F% }) ]; V4 S. Y6 A
  5.         USART1->DR = ch;1 Q. S1 _% `% Y( M: _
  6.         
    0 @0 W2 a: p$ T
  7.         return ch;
      N8 p$ V& ]3 x$ r. [
  8. }
      S; _( U0 p& R9 p& _
  9. /* USER CODE END 0 */
复制代码
  1.   /* USER CODE BEGIN 2 */) |: p8 x* g) q' {, I
  2.   HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);            // TIM1_CH1(pwm)3 I  X$ ]% p/ q  y9 ?
  3.   HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_1); // 开启编码器A/ u4 G2 B3 N$ D0 p! K
  4.   HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_2); // 开启编码器B        
      E% Y5 ^4 L' C% t) j
  5.   HAL_TIM_Base_Start_IT(&htim2);                // 使能定时器2中断+ Q/ [2 N* @9 \% r; i+ ]. m
  6.   /* USER CODE END 2 */
复制代码
  1. /* USER CODE BEGIN 4 */
    : b/ p0 M. L' x/ {
  2. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    9 v  D# Y5 |. }7 z$ K% F" e
  3. {% j% ~& W7 G4 I" Q( z
  4.     static unsigned char i = 0;$ P$ C7 _& K" g0 S; X5 n/ [, g& P
  5.     if (htim == (&htim2))8 |4 D) s! T# r- F5 J( a
  6.     {3 {$ x; N) |6 |
  7.         //1.获取电机速度
    ! `. F+ T8 p4 s1 Q* k' V
  8.         MotorSpeed = (short)(__HAL_TIM_GET_COUNTER(&htim4)/18);   1 D- {, J' Z( _  H" W: t& P
  9.         // TIM4计数器获得电机脉冲,该电机在10ms采样的脉冲/18则为实际转速的rpm6 y/ l6 y' T4 f( D5 O' d, {
  10.         __HAL_TIM_SET_COUNTER(&htim4,0);  // 计数器清零+ n5 s+ k2 v4 p* I" t
  11. 6 W' I% A+ h; O  X

  12. 7 N  w" u; m+ \! K
  13.         //2.将占空比导入至电机控制函数- U# F4 k# e4 G# a- w$ a& t' B
  14.         MotorOutput=3600; // 3600即为50%的占空比) n! |8 V( s0 t( Q
  15.         __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, MotorOutput);8 r$ G* a$ A4 _' |2 Z
  16.         MotorOutput=MotorOutput*100/7200; 4 c6 _( ]5 e! i) Q& b- t
  17.         // 占空比(按最高100%计算,串口打印)
    ! s: ^6 r3 l% J/ [7 M
  18.         i++;
    1 h# ]  M  A4 P6 S% J
  19.         if(i>100)
    ; Q- J. o& g2 g( d
  20.         {9 ~9 F! O, \5 D, m0 l+ Q* p% ?2 g
  21.           // 通过观察小灯亮灭来判断是否正确进入定时器中断, u& ]  u: f* c
  22.           HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_2);
    5 J" V0 `  _7 Y  Z- {5 O4 ]
  23.           // 打印定时器4的计数值,short(-32768——32767). ]8 A9 x& `4 M3 j" d( }
  24.           printf("Encoder = %d moto = %d \r\n",MotorSpeed,MotorOutput);        + {1 ~4 A3 x; ?$ Z/ g* f
  25.           i=0;4 f0 E9 N" _* Y* @$ g. `
  26.         }3 v5 G; T! U! V4 c2 i* |
  27.     }/ _% j* n1 ]2 D8 a0 @& X" K
  28. }
    , G1 j+ e6 E( @( u% p- i% B7 ^
  29. /* USER CODE END 4 */" J; R* b5 g, |8 L( t7 O
复制代码
( B. q- G- w) X3 i( K- p
(2)烧入STM32中,串口展示:/ K) a) r4 _1 V4 D( ~

& B. G" e: i4 [, s O`T47Y5J`LF6UMHK{DLRM]G.png
& Z$ X% e2 O. D2 D8 z" p' z# O
; D) r$ z3 ~$ s' S(3)实物展示:
# I2 z* r- T4 A! ~, n% o6 u9 Y' M4 F$ C9 ~. {% z* c
WO8L63G[V)3I$BYDF]A`T`A.png
8 n6 G( C* b# F' }8 m/ r; s$ q' k$ b  I& m+ M" \

# l3 a, z8 V6 }" D7 q4、总结0 r2 A7 E6 O; S
  以上就PWM控制电机转速与编码器读取电机速度的HAL库配置与keil编程,后续会推出利用PID算法闭环控制电机转速(HAL库)9 S# R  `7 J& P+ A7 b
, j7 ?4 M4 J% o" X* ~
4 q0 d7 Y: s) L8 H
收藏 1 评论0 发布时间:2022-5-24 11:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版