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

STM32通过PWM控制电机速度

[复制链接]
STMCU-管管 发布时间:2020-12-7 10:50
STM32通过PWM控制电机速度
" e" W9 `9 n. k! I3 M' a

$ e' X, M, q$ {8 I2 B' x做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。
7 ]# S) K! Q5 r2 I" I/ U% q8 M  d6 [7 E  _' y

, O# G. Q5 y5 H" g2 c7 lPWM控制电机速度的基本原理
1 G6 L. F2 |/ W( y    PWM(Pulse Width Modulation),也就是脉冲宽度调制。3 G. {8 _9 A% L7 f4 w
    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。
4 d! e8 ~; r: T% L3 f6 |
" j% H; V6 _( b3 f5 r: C

3 O' b: ^  ~# v8 A8 E+ }6 |    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。
  q4 d2 i" v- K
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这两个寄存器的值了。
  {! X& [" U+ Y- h! k* U
( c4 d$ a+ D1 g( O* C
, q9 T8 i$ P9 w& E; P: N) i
STM32定时器中断
" e, e- y- Q1 A7 d    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。! d0 m' k$ p$ ~, Q9 u: ^2 o, C
3 c, h  C( g1 y! ~/ s; A8 Q( {; R
0 w- Y: D* N' L, i
    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。) `% ]$ J! J! d6 \1 G
原理简介
1 q# h' s' g7 N4 c2 z- }    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:/ A$ M  t7 N8 u5 \

  1.   W# W1 ?4 |2 T( u7 D) q
  2. void TIM3_Int_Init(u16 arr,u16 psc)3 q  U# M  S' }4 Y! w
  3. {( v1 |! }1 [1 w( h
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能    # \  e. T- \+ K( u' o9 v
  5.    TIM3->ARR=arr;    //设定计数器自动重装值 . h& V; d; ^$ a- I2 J
  6.   TIM3->PSC=psc;    //预分频器设置) |! W/ [  a- S
  7.   TIM3->DIER|=1<<0;   //允许更新中断        
    & C. F8 U  ]' F& M- s
  8.   TIM3->CR1|=0x01;    //使能定时器3
    * K5 l) q6 v  |( P! Z$ y% _
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                   ) U$ H8 G2 e, n* E
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
# a1 E5 k0 k& M# ?5 D7 l
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。
; M3 @0 r  f2 @, r4 T2 g( X
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。1 \4 z: ]5 O9 B3 |7 K
  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代表的是前两位给抢占优先级,后两位给响应优先级。' d# n4 \2 O: Y) X

8 b& k& y1 R" x# f4 U' l
# v, `7 ]" ]2 m8 c
PWM模式、有效电平2 Q$ R# j/ m, z$ D' ^- O

* l# r2 y6 I6 E6 Y, J

1 w- D1 R# F: a    前面介绍完中断,再说一下PWM工作原理。, H5 `' ^, X$ G3 v) @" _3 y; I
6 F# A9 b/ H, S4 D6 b$ L" m
9 K1 n0 O" G, K% D: y, t8 C
    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。
. }/ K8 d0 o2 m' o/ ?/ \  u1 P3 C+ `( a* H' h! m9 ~1 k$ C$ j/ D

* Y9 e: `( D6 Z- B) ]( `" \' w# o模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。3 B7 O2 j- r5 W) t
3 q. |8 ~  }& q
) F) T% T4 ?* |' U
模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。
  b: b* E! X2 k; Z9 `+ }: I1 s8 Q5 X0 |
- }! V# l, T4 [4 f

2 }, p; |% G* t" U  O    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。
. w- o  ^" Z7 a; m/ r: J& y6 F! y
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。8 K& h4 E4 S8 T. }8 @5 a

  1. 2 @: T8 ]6 c% {: v- E6 O" R+ c
  2. void TIM1_PWM_Init(u16 arr,u16 psc)
    1 s6 o# _: u) M5 P6 f4 \/ E7 q" w
  3. {                * d! M! H/ L6 ^8 y; r
  4.   //此部分需手动修改IO口设置
    % F$ L+ C* ]& ]4 p$ [5 `2 ?
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能    ( {$ J9 |( w* ~3 a0 u
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置( H( A# f* U- u( c* B) L5 O" i
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出   D$ Y: w+ j2 R* y
  8.   ) q; C# `4 m) k
  9.   TIM1->ARR=arr;      //设定计数器自动重装值 + f/ H, ^# s: J7 x+ S8 f- v8 w  [) a
  10.   TIM1->PSC=psc;      //预分频器设置) Z+ _7 }% f% w0 d& c
  11.   ( x, s3 Y) H$ n
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     ( s# V, W: U9 V" a4 V7 W
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    ( h2 H/ a3 n+ d5 M8 [9 Z( X
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     
    . o+ n: {% ~! x5 I! T2 D6 G' Q+ m
  15.   //TIM1->CCER|=1<<1;. ~! n  i6 R( C( m1 H/ Y$ u  P
  16.   
    7 q$ @" q) e$ o8 s8 o
  17.   
    5 c9 \! D2 q: v+ H7 `1 H9 I* A
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     
    ) `; g: t( S! G5 m) d" y, X1 z
  19. / I3 A5 T5 W* Z  R  L. Y$ U
  20.   TIM1->CR1=0x0080;     //ARPE使能
      C/ c9 s2 j0 i2 |+ y
  21.   TIM1->CR1|=0x01;      //使能定时器1                       
    - Q. V) z/ j- y0 X' z
  22. }
复制代码
下文具体分析上面的代码。$ `+ S3 O* d! g$ P; ~
前面4-6行是用来配置GPIO口的。# F6 f2 p! ], F; R8 C
  1. TIM1->ARR=arr; //设定计数器自动重装值
    3 R: y8 m4 U' G
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。
  I3 _6 w0 ?8 `
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式
    8 d; I! [! I% W# |7 E
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能
    # Q5 v/ p  D" I; P: w: m( f0 N
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。9 i# s2 R. A9 H* {' d1 z
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。
6 n* U# Q2 D8 K6 n. O
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。
- h* ?0 T* o) D5 w
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。& @: m0 |/ t7 J( D  \
( I4 ~, K' ]: E* y& a' G. d
" i9 s* g3 l$ v* T# b2 n* j
上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:7 u, e. }/ @0 e( z5 k5 s; ]

  1. 8 b; ^2 i& P4 X
  2. for(i=0;i<300;i++){( a, S( }, C/ J2 ^5 n3 w$ @
  3.   TIM1->CCR1=i;
    , m8 n3 m' x) O: m: O) H7 i
  4.   if(i==300){
    . E# _: @$ d7 L
  5.     i=0;% F- o7 c. E' k3 \: \. h
  6.   }
    - m- d: ]( @8 R4 X
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。2 i$ d6 o: R+ x8 k
2 W0 y* p% O' l6 h" r" Z* a2 B
* H8 i" Z7 ^$ y$ A9 j) E, h
    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。. Y# C' s4 T( F. E( J' s
. k. s$ h2 S' D

% G4 `0 w; m* O, t- l2 h% F* T5 `. W; Z( L2 R; ?4 J- i
8 u" h$ ?+ J, d3 K! K5 P
: ?0 Z2 L# K6 c' g5 }) x
5 ^9 Z1 M, o7 i8 J$ d% n0 a
; {. w1 U. O* ]! t; j
收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答

所属标签

相似分享

官网相关资源

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