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

STM32通过PWM控制电机速度

[复制链接]
STMCU-管管 发布时间:2020-12-7 10:50
STM32通过PWM控制电机速度
8 a) d& M# Y- i' q

+ P) e* k3 N4 X6 U做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。
. v1 C7 H6 l5 Y( V! {& @% {( A% N% ~0 S8 X$ a% y1 G! ~- W& H8 g

# D- c1 ?9 n# r% U+ @2 D+ C/ F, HPWM控制电机速度的基本原理; h' ^9 m, V0 n
    PWM(Pulse Width Modulation),也就是脉冲宽度调制。
2 j* V+ ?$ r2 H) M    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。' X* A& N- N7 W6 J* W! L8 Z$ q0 @
' E0 k* [0 z% u7 v6 K9 x( r
- c% F4 w+ y$ Q( w0 E  |! O. N
    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。
+ B1 l  d( ]* y8 l  D/ D! \% N- c5 N
11.png
    上图中的ARR是我们给定时器的一个预装载值,CCRx的上下变化是产生PWM波的关键。我们假设ARR大于CCRx的部分输出为高电平(即t1-t2、t3-t4、t5-t6),ARR小于CCRx的部分输出为低电平(即0-t1、t2-t3、t4-t5),则改变CCRx的值就能改变输出PWM的占空比。因此,想要控制PWM的输出波形,重要的就是如何设置ARR与CCRx这两个寄存器的值了。
; G9 N) n( Y! L) p2 F& m+ H7 X* L" F( l$ s8 z. W

; @+ z: g: p) j$ ?1 I7 a* {STM32定时器中断
" ]5 V. m0 h+ ^& f    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。
' A/ E! ^9 \5 P6 w+ W; y
6 h9 u/ m, O2 t- t, e0 F" a1 B4 v

6 K; b8 o' \& |; W3 s0 V; x7 u    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。
0 p! d$ ~; w1 J# A3 |+ C; O' m2 J$ y原理简介' [8 _! S/ d- s: R2 w% {
    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:& e- E( x1 i' ^6 ]" B6 J# x

  1. ) k2 [& D. P! x  Y: M
  2. void TIM3_Int_Init(u16 arr,u16 psc)
    5 K5 A# @+ O  I% a5 h7 {
  3. {
    : f# D9 O9 c- A8 _' @, T' P0 ?2 H
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能      m* T# S2 z( W8 g5 N
  5.    TIM3->ARR=arr;    //设定计数器自动重装值 , T, s( L1 K- F$ n4 Z" C7 h
  6.   TIM3->PSC=psc;    //预分频器设置
    - f1 v' w' j5 j' F  H& G
  7.   TIM3->DIER|=1<<0;   //允许更新中断        & F( w4 L" N7 l( u# e/ n
  8.   TIM3->CR1|=0x01;    //使能定时器3
    4 ]: }1 T2 p# i1 b: H
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                  
    & [8 |3 B6 M$ B/ s$ O9 Y8 P5 N
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
5 x% J8 k: k& C$ z; t1 m
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。# b6 e$ b, h& Q
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。! e  `( f: ]. d! N$ \
  1. MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2
复制代码
看上面这行代码,中断优先级有抢占优先级和响应(即子优先级)优先级两种,抢占优先级即:若程序1正在使用CPU,这时如果程序2要求使用CPU,并且程序2的抢占优先级高,则CPU被程序2抢占;若两者抢占优先级相同,则就算程序2的响应优先级高于程序1,CPU也不能被抢占;若程序1正在使用CPU,程序2和程序3的抢占优先级等于或低于程序1,且程序2的响应优先级高于程序三,则待CPU空出后,程序2先运行,程序3最后运行。TIM3_IRQn是指定将要运行的中断处理程序号。“组2”是设置中断优先级分组的,这是因为寄存器提供了四位来设置优先级,组2代表的是前两位给抢占优先级,后两位给响应优先级。* [! P$ X4 u; O2 ?: g

7 z8 A6 l) ~/ N: \( u
! g1 O. I  L5 {  L
PWM模式、有效电平- E& t* j7 v% O  b) Y+ T
1 y, a% P( @% K

) Q. o& p* L+ E; N) H    前面介绍完中断,再说一下PWM工作原理。
8 u4 X9 Z4 `, y& i$ b' Z7 d
# C6 x& q1 i0 C+ Z4 A! l( j

: Q5 i: n, O) W8 l1 t    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。; S% k  P$ }. [7 x0 r

6 u8 Y) V7 K/ W+ J! w* }/ R# B

' u0 p/ @5 w( p模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。# W+ x5 n/ c9 b, r
. `9 V4 o, |" n$ p) s# `' s. e1 c

. \# T5 j  D' q) X1 A* e% c模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。- B; |  Y+ z) [2 e
! n2 p6 O" d( i2 h
4 k/ i* R. Y6 _% _7 W
    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。1 ?$ q( {+ }& e# Q  h5 K
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。
, n% d+ W7 l% [: P$ k/ b2 F$ B' W7 T
  1. - H6 X* [! W! w' O: i
  2. void TIM1_PWM_Init(u16 arr,u16 psc)1 `5 }! f2 i, L/ h2 }# u
  3. {               
    3 A# {" n. h- ]5 p( ?
  4.   //此部分需手动修改IO口设置; y) V2 W3 r$ ?; d: l5 b
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能   
    # \  p2 C' }% `1 X6 ~
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置
    + h% _7 _- B; o) l) F- t( n
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出
    5 i! Z  k5 q9 ~6 y" e
  8.   
    $ b) |1 a, S) E% A
  9.   TIM1->ARR=arr;      //设定计数器自动重装值 0 E6 [' l; D: Y( }' l* _+ N
  10.   TIM1->PSC=psc;      //预分频器设置. o0 O7 r  H: d1 I+ B" t0 X
  11.   " }& H. a. {. a
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     
    & Y" }* F, M6 u2 [2 |' E
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    8 o0 g% ~, z! M5 Q# Q
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     8 V7 ^) T% }; \* {! j
  15.   //TIM1->CCER|=1<<1;) x9 {9 z" S/ t) P! q4 G0 b
  16.   # J5 W( ?% \3 ?) u
  17.   0 L5 V0 c0 C+ ~7 g
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     6 I4 B: r$ b3 t  S  O7 c
  19. " ~- c& c! B. D! o) G/ o% w) V, W
  20.   TIM1->CR1=0x0080;     //ARPE使能
    ; M: N4 |5 W4 l% n0 O$ x# \% H/ @
  21.   TIM1->CR1|=0x01;      //使能定时器1                       5 x5 u# j2 R6 O$ u+ q
  22. }
复制代码
下文具体分析上面的代码。  J$ P7 i$ N" c5 }7 {; B. V; z& x5 O
前面4-6行是用来配置GPIO口的。' b; [$ B, x, F( X6 j: f
  1. TIM1->ARR=arr; //设定计数器自动重装值
      d  L2 q; g' E3 u+ L( q) e
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。' P4 w# j1 T) J& J% f9 ~
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式8 N) K! N/ a0 b; b$ T
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能+ u3 K# K) J: |0 k8 r4 z* s
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。
+ _8 W0 m, c. ~' P" B
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。
1 h0 ]: Z( F2 H- D0 `! m
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。' P: {! h& m" z8 S' a) [1 ?. U
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。- K6 ]2 {+ J4 O

( B0 `6 T% N6 p* i7 y/ V+ i/ k

' `3 I; L- U- ^- a上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:
6 \) B6 D; x9 Z$ ?. L) r
  1. # T3 P% T! `% D# n/ z
  2. for(i=0;i<300;i++){9 L- K; n) `1 ]# K
  3.   TIM1->CCR1=i;6 K  M+ \  c) g* k
  4.   if(i==300){9 M6 O8 u4 G" Q' @6 r$ [
  5.     i=0;
    5 Q1 C4 @/ K) e" s, f2 E0 H4 s
  6.   }3 a. h7 A' c( y: ?
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。, q/ H' E  G# X3 b! b7 Q

3 W4 U2 @6 J' U  W1 Y4 R4 L. p. j
# ^; b1 j$ z! L8 Z7 x' \1 u
    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。6 S# A1 T; j5 g- `  ?2 v& V) D1 }+ p9 a

  m# }) \6 ?5 A  W+ [
7 m" P7 f5 A) @+ ~2 m1 r
8 y  M& A8 Y% X0 z& U4 Y9 w

# S2 ~7 U+ P4 g7 M4 u) ~; I( D
8 C3 D/ I9 T1 f8 _

2 j- \8 P- X% x  q8 I
, O0 i+ O) N! {0 u! w1 d
赞 收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答

所属标签

相似技术帖

官网相关资源

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