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

STM32通过PWM控制电机速度

[复制链接]
STMCU-管管 发布时间:2020-12-7 10:50
STM32通过PWM控制电机速度

. @* |/ ?: C& ]+ |. P
( \, p$ V; a% C6 p' Y: e+ L
做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。" u$ ]8 i  Z5 m3 a3 @, J( i

: D7 Q0 ~3 }% h) o; L
+ W& M" |7 |# O0 J! E
PWM控制电机速度的基本原理$ U; |. P; @2 D* ]
    PWM(Pulse Width Modulation),也就是脉冲宽度调制。1 ]3 `1 I+ z5 K: F
    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。1 i9 m- L6 t; B* n; y+ A& l3 g
2 |9 }4 n  @5 ^( |0 M' c& H

) {2 U6 [, p2 {    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。$ [! Y# @+ V( i
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这两个寄存器的值了。
2 {2 [( d  |* V  Z% ~2 k# m* A* V
8 V! m5 `7 p5 {3 n" v
STM32定时器中断
) G- Y4 f1 E8 ]% G    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。
. E8 h. \% N+ K+ R5 ]5 I
$ ~1 x5 m" u; z" o6 A$ E
2 X5 L4 r0 e' o8 R4 q3 x
    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。
# d/ l' L- L# o5 j2 P原理简介) C7 M! s/ {; P3 a* O( O% w
    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:/ c+ Z  W8 \' h  z% `: y" Z7 f0 K
  1. ( F+ F5 G- G3 H5 e. l  L: w2 m
  2. void TIM3_Int_Init(u16 arr,u16 psc)
    " I) Y( ^7 m0 k# O6 d
  3. {1 U6 {% c9 O# p! }9 D
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能   
    ) j1 i: O9 ~7 C8 j- ~
  5.    TIM3->ARR=arr;    //设定计数器自动重装值
    # B5 q; h; x$ T5 z$ q! h
  6.   TIM3->PSC=psc;    //预分频器设置
    8 B3 A, F; X1 E" o$ \5 s& h1 C  Q/ y
  7.   TIM3->DIER|=1<<0;   //允许更新中断        / M& A- M# A  `) t* ]
  8.   TIM3->CR1|=0x01;    //使能定时器3
    2 ?, G, Q# ^+ y8 j$ T
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                   0 c; v' M4 m  Z% n2 ~5 X0 P; ~" _
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
) T0 H0 q% P2 R6 W) p
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。
1 t- D- [3 @  q) ?
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。
2 @# T. h+ e. m" B
  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代表的是前两位给抢占优先级,后两位给响应优先级。/ M2 R9 m+ D. Y! b  y2 |) Q+ K
  p5 x' ]8 ^( U& W" j* k& X
+ j& c4 g4 c$ S  \
PWM模式、有效电平+ i7 s9 u% B8 N) V2 p9 @, f* X
& d8 |9 i: }7 K" V  \( Q+ g& L8 n

4 c4 k( d; ~* {! r9 h    前面介绍完中断,再说一下PWM工作原理。7 x* w; Q7 P* ^

! X, M% Z( l4 I5 E( l" K$ V- C
1 f* g4 }5 J2 F/ w3 {5 n( u% }
    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。
% J' p. Y' f6 @8 s1 @1 a: L$ r/ f4 [; ^* X: X) K/ Z

0 w+ Z1 r' \% z- `6 O模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。
# h6 |  L: p; z5 c8 C" f4 E# j* V% r3 |: z
" E5 D$ O/ U0 R$ f& M* [8 {
模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。* n* k' L. Z+ u9 X$ w

0 Y) p! T" g7 L% q: u9 p

9 D! Z* w2 S7 ~8 r8 [    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。
" M7 I4 o3 ~8 G1 `# c. V
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。
8 l; I9 H  A3 f2 L( H

  1. ! O6 `0 a, i. p7 S
  2. void TIM1_PWM_Init(u16 arr,u16 psc)$ R/ q& P. |& I6 E0 P% [
  3. {               
    / _- l+ R' }5 Z/ {; ]  e, A9 r1 s
  4.   //此部分需手动修改IO口设置9 K& e4 Q  b. W- S
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能   
    & [4 f- M% ^& m/ e7 }
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置+ j7 b" r5 `1 s7 q
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出
    1 w7 ^* D% Q) G
  8.   
    9 B8 M8 L0 z  a1 J" o
  9.   TIM1->ARR=arr;      //设定计数器自动重装值
    ( J( W5 N' a( I  G6 c4 S3 m
  10.   TIM1->PSC=psc;      //预分频器设置
    ' l/ b1 f! ^. J  ~
  11.   0 Y5 |# J# w2 f9 U1 R
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     
    . m' i& l/ M2 R! v& f& H3 Y3 _
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    # [6 e) B( g- }  `: w; u, e
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     
    / |3 q1 ~3 r5 v) P4 l
  15.   //TIM1->CCER|=1<<1;
    : ^7 f8 }. z( d% t' ?& L/ Y+ k: q
  16.   
    3 F( H! u; j5 `) j7 Z" p5 x
  17.   8 g1 f5 {3 h+ Y6 G9 U
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     . |. ~+ i# M6 I
  19. 5 x7 J0 R! B' g) {6 a0 z
  20.   TIM1->CR1=0x0080;     //ARPE使能 / Z/ b! |( U: {  A+ }0 [" `; A) h7 a
  21.   TIM1->CR1|=0x01;      //使能定时器1                       
    1 @4 T6 n) t4 j- e
  22. }
复制代码
下文具体分析上面的代码。
, b; w1 ?5 a6 U! ~前面4-6行是用来配置GPIO口的。3 H/ L. z8 C" _9 ^6 T4 ]8 R( z6 z: g
  1. TIM1->ARR=arr; //设定计数器自动重装值
    ! l! I5 t# z7 G* \
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。
5 d; x+ E4 t8 N2 \0 |1 ?
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式" C, A3 g5 L2 |( E
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能  s  i" s7 ~( i2 B! W  t# p
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。
! z0 e# r& d* D. z1 \
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。
! ^+ k& |5 L% Q) O7 R' ]# Z6 J, p
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。$ F" \$ \7 n, F( d2 H
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。% _2 u9 w( x4 x0 R" V, Y6 G
& ^5 `0 K8 c1 v$ h  _" s) f
. y( r; Z0 r  \& I: z9 T+ n' p
上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:
( {- O) P% _$ b! i

  1. 1 F# x+ Y! e: C( _9 r& y3 Q2 W
  2. for(i=0;i<300;i++){. l2 d6 h& D  x, u. }- W7 T
  3.   TIM1->CCR1=i;) \# i" Z& o" ^2 @5 t( @) Y1 [
  4.   if(i==300){
    * z2 `7 Z/ n) R1 a
  5.     i=0;1 v) x* h$ V1 L1 Y' K) o: ?, s8 }
  6.   }  N! _, C4 {' \; }
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。  {8 @3 R' ^0 [: e7 [, d% y; B

9 L* P- ]/ s0 J) B

9 L* K! N: N! U6 A+ [$ X    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。
& ^2 ^: K9 ]! E* }/ H$ x; [( s! b
; p: f% _  f6 S9 Z; J" }" o, w
8 f6 O4 K& {0 Y) d) `1 G5 _  S' D

- q2 A( O1 z' w+ L! w5 W  M
7 D) F; p- T* Y  U9 n; B

" S- S$ e8 V, y4 O
/ m3 p3 s6 G: \/ K* K
收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版