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

STM32通过PWM控制电机速度

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

- S6 j9 j6 e' M# F% b
% |+ \1 N$ [; G
做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。( O, i( j& M% H1 l8 C, D* p

" \4 |' y# B5 f# e
- d2 Y/ _( u" L3 U, H: A+ j7 n7 O
PWM控制电机速度的基本原理# w+ `" \9 E8 @( `* t2 Z
    PWM(Pulse Width Modulation),也就是脉冲宽度调制。
5 O! I4 ^( V% e1 n  I0 r    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。
3 j3 L: p  N! i8 ~. @6 Q) k. B5 Y
+ O( X6 e& G0 d# K1 I, O

+ m" n7 S, x9 j; I/ [) s5 h2 W  ?    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。' V8 q/ V+ B# ^2 J/ k# 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这两个寄存器的值了。3 Y( ?; ]+ i, l& D* ^5 |6 U3 f

) g8 \( f2 p; F# L5 \; `

1 r8 W4 T* [' y2 zSTM32定时器中断  v( s  H1 F0 `  x9 p6 R, z: F7 R) t
    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。* M) r( H2 a  `& ~) ?
8 x* J$ ^/ y- C. B$ ~
( j% D0 s9 }7 f+ V9 v2 h, H
    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。# k5 i* ]1 z; O! v5 Z5 j; Q+ Q
原理简介
$ Y: f7 H) |$ m  I: Z4 G8 D4 d( s' J    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:6 c6 W% w( x0 u9 W
  1. 7 D0 F0 U. j# c4 ^
  2. void TIM3_Int_Init(u16 arr,u16 psc)6 \% {2 @% O7 C" ^! U
  3. {
    3 \( B3 g4 W8 c* ?
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能   
    % K5 P5 C( K6 P: G
  5.    TIM3->ARR=arr;    //设定计数器自动重装值
    ' N9 a  [8 G8 T8 S& T
  6.   TIM3->PSC=psc;    //预分频器设置( x: H2 s- k  w8 k( Y- `
  7.   TIM3->DIER|=1<<0;   //允许更新中断        
    % Y0 t4 ]4 A7 _, n
  8.   TIM3->CR1|=0x01;    //使能定时器3
    , d8 O; e) g7 y6 W1 ]/ \- o* m
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                  
    4 E! ^9 ~+ N' l% r$ l; x6 v* n
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
) |' g( R* @4 b8 U; S6 }, }" \
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。! I/ M' y8 E6 U* Q& q
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。0 s2 ~: `, g2 ^
  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代表的是前两位给抢占优先级,后两位给响应优先级。
4 J& _+ q# y# U% @5 C; }: Q
" R8 _7 Y! R6 p' T# b

2 u  l" H8 ^3 n( v, H* mPWM模式、有效电平
! `( b% P5 x; K3 i) |# W# A* w6 h& b9 _5 G( D

! ~- V  v; @1 k5 d% o    前面介绍完中断,再说一下PWM工作原理。5 F8 o, W+ o( H; H* Y! f  p

! v2 x: l; y2 F0 Q! z9 S
" h4 i# V, S% n4 c
    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。! B% u7 w" f; M

/ G# P3 h0 g0 H1 N9 _, B, ]5 W) ^4 j

, M- a; D7 D4 ~& ?+ d  d模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。9 n, G" r9 n# [0 p7 O) ]. S
' K9 ~; Y( ?" \) J* X, u
( i# o% I" R! P* l9 X
模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。
; C. D, l, r, n6 u8 ]  C* [( O$ t5 _$ ^: ^8 d* N" D
. C: J# n' U6 j/ |# O$ A, y
    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。
% [, h# R0 {! u0 c) Z) m$ p  N' b9 s
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。9 h6 ^+ K$ O/ e5 d; Z
  1. 4 z/ @% U8 t$ X; v# e. i
  2. void TIM1_PWM_Init(u16 arr,u16 psc)
    / j) ]# ]4 l5 W, e6 T
  3. {               
    1 y+ N; E) N. A7 |. K9 p4 c
  4.   //此部分需手动修改IO口设置
    4 m! I3 I$ L( y1 R
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能    / u1 }% _* Y, [- n3 V
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置
    2 {# \/ Q% B$ ?' x7 X: q
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出
    " E  W# U8 p) Q7 j+ T+ S3 k+ M
  8.   , s6 K9 ^) G( ~& y% c6 r$ p7 `+ I
  9.   TIM1->ARR=arr;      //设定计数器自动重装值
    - e4 y% U7 ]3 Y. S3 [
  10.   TIM1->PSC=psc;      //预分频器设置
    9 F( j# e& d; e$ j) A
  11.   
      n' G' C6 z( \7 H4 `' o7 Q! K3 B
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     
    2 q" t; y; i$ l2 y0 g: K; @" B
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    , B$ j, b, i8 p9 |- W
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     
    1 ^  ?8 V0 R' [
  15.   //TIM1->CCER|=1<<1;* z0 \4 d* z: W- n9 `" U- w( I8 T
  16.   
    / F4 C1 O* z0 o1 o0 n
  17.   " U, Z  z  H; `
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     9 B5 F$ M( l4 Z0 i( f5 j

  19. 5 C! u1 [  O  N7 A6 @
  20.   TIM1->CR1=0x0080;     //ARPE使能
    " o/ t& }/ _2 H- I# `$ p8 d. m2 j8 e
  21.   TIM1->CR1|=0x01;      //使能定时器1                       
    / o- I* B5 r  K
  22. }
复制代码
下文具体分析上面的代码。& @$ n6 g% ^3 c: j
前面4-6行是用来配置GPIO口的。3 I7 f& @) @+ R
  1. TIM1->ARR=arr; //设定计数器自动重装值: \' [6 {+ d. k" {- F% _' v
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。" l3 n- v( q# h9 N& w2 N  _  o" h
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式
    * d' F1 W) d% [* r, W1 J5 e
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能
    0 K  S  J6 t5 ?% \& f3 ?1 V
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。) R3 g* O4 h1 o- b  L7 s4 S) M
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。
( B# U( o, x5 Z3 ]8 w( k  n; ]
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。' u8 @& m- E& k( Z4 T( w
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。
5 K  W. ~4 x# A3 c# s+ G: z. g
7 e. A) g6 ]; G# d

3 T4 h. K  B4 C8 y# r$ R8 o, a7 F上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:- F: T& ~4 H! C0 u1 N* p% t

  1. & ?2 l9 y( ~# T: V2 I/ ?
  2. for(i=0;i<300;i++){6 V" U% E1 I  Z# T3 c
  3.   TIM1->CCR1=i;
    3 _3 o! o+ w/ q% @+ `
  4.   if(i==300){" m  |8 F& z$ V
  5.     i=0;! H( `' k" W4 d1 b
  6.   }
    . d4 p. H' y6 G! K  q3 f4 w
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。3 k# h$ ^* d& U( d3 d

, g) \; N5 T* z: O) A8 V

5 U' L% p+ w7 [4 P7 A" V    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。
: \* `) E- _7 |! k! c- C+ H
) t5 h& D6 o5 i* b8 r
7 T" t  D# A" o% J1 Z4 {. j5 s4 `
: n4 t- |3 X+ L7 v

: V+ ~* L9 E4 f$ T: {2 H8 L. r. @- n2 @# u; \

6 k5 b4 ^4 B# V% U' n0 r+ c+ b2 h. q: v3 z, R' L8 W  C+ v; F
收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版