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

STM32通过PWM控制电机速度

[复制链接]
STMCU-管管 发布时间:2020-12-7 10:50
STM32通过PWM控制电机速度
7 {/ q1 i. O  a3 W6 ?8 c0 q; Q$ v

) i5 z$ [" n' `0 g6 S: ]做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。
. g4 C* X( U- p. l$ U8 \( j. e
; ]+ f2 k) T2 E% G' G
1 E7 y) k5 w4 \" D: h
PWM控制电机速度的基本原理
+ o: ], u. N8 ~- _% l9 D2 l! b- S6 W    PWM(Pulse Width Modulation),也就是脉冲宽度调制。+ S6 v( y6 u& h$ f/ O
    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。
8 ]) w! s! q/ s) C( N& P0 Z& {- x0 G) z2 G- |9 s
5 u0 @2 p7 {; L/ k- D  ?
    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。3 h4 {' J/ O, j: S
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这两个寄存器的值了。
! y8 H: L8 M8 R5 _( z# ]0 o) V5 y- g2 H$ |. W8 N3 [, a

8 e7 H) v. p3 g2 L+ RSTM32定时器中断6 c: l0 g3 }* u* l# c3 \- m
    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。* U6 }$ j3 D* r+ F* Z# y6 q
" Y9 P' A) R2 d) v% ?: i

# Q+ X7 C) C6 q: }& ]9 P    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。
/ v2 D/ l" X7 }, y原理简介
# W  B$ i3 q; V, q" o& v    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:
8 N1 S) \1 S- f; v
  1. 8 W# {7 B; c8 `4 d% E9 L
  2. void TIM3_Int_Init(u16 arr,u16 psc)
    0 H* M. c; ]' G9 P( B+ f9 q! g9 E* _
  3. {
    ) I0 f. T+ v( }7 U
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能   
    ) D& w& j$ ]& a/ D9 \( Y
  5.    TIM3->ARR=arr;    //设定计数器自动重装值 ) t" z$ a! @! B- T, r
  6.   TIM3->PSC=psc;    //预分频器设置
    " n% w# f5 a( @
  7.   TIM3->DIER|=1<<0;   //允许更新中断        
    * ^% |9 \8 l; \' P
  8.   TIM3->CR1|=0x01;    //使能定时器3# U: W  |0 {, T* p
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                   % I% b, E7 n; Y% J% d
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
$ g! J1 ?  r7 O8 l4 V9 q5 w
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。
0 l4 |1 e( v' V" @
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。0 G  }1 \. d3 G- J' y2 s6 r
  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代表的是前两位给抢占优先级,后两位给响应优先级。
" ?6 \0 i5 K, P7 {' U, D- P! n$ M8 g) u  g

, h3 k1 H& {+ W# nPWM模式、有效电平
; f& [; s6 w* E& x5 S7 v
- b" F7 R, X2 C! i9 H
4 @* e; u1 p( L/ q2 M5 g3 i
    前面介绍完中断,再说一下PWM工作原理。3 J( b& \- c4 l1 P' N# I6 B& \
. V' r6 h( y! o1 S% z

1 b% q8 y" b* A! `& H1 }' w    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。( ?- I+ O* V5 m+ k" b- s

2 W- ^5 \- e! X7 Q0 _2 X3 H
( N# A2 J  a4 A* p( P0 f$ Q
模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。, P4 \! U# ~% y' l
  b+ d. \1 s1 j+ f) y* Z

3 q% `; f2 S, [* @1 d, h模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。3 a5 w) u+ }) V% _# _5 T

/ [- c* g+ Z2 }: _+ v+ m1 H
. L9 U+ d" q; B! J
    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。4 r8 k, ]8 Q( ~+ ~5 E* C+ t
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。' j! z. F( X' K1 V+ [
  1. 0 o6 _/ j+ [. k: Y- T: g% |6 O
  2. void TIM1_PWM_Init(u16 arr,u16 psc)% @% z' X$ n7 p8 A7 c
  3. {               
    4 G$ G. m5 `' e2 H0 W# k" V/ d' R
  4.   //此部分需手动修改IO口设置
    5 W  {- w& ?$ |0 ^
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能    3 {9 q" ]% b8 k6 ^9 N
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置/ \4 Y' \( f. n  m3 N8 O
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出
    0 l/ N1 h. Q, _
  8.   $ q2 `* o8 u  P3 R2 d5 s
  9.   TIM1->ARR=arr;      //设定计数器自动重装值
    * ?# V) N# [: _
  10.   TIM1->PSC=psc;      //预分频器设置
    $ s3 @) o1 c- x2 l* g- b# x1 _. b" g
  11.   
    , t& o% z. ?% ]
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     + g5 c9 i/ i: d1 |3 J
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    % W, T, x& F' }( e
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     
    ( [9 C4 X% Y: ]" V0 K* i! L3 n
  15.   //TIM1->CCER|=1<<1;5 d4 h% D  ^4 P# i7 M- h  m# }/ M1 W
  16.   
    ' e) h! e- |% y% x  D; [
  17.   
    # C! D3 ]: T# S* C1 p- H* A- O
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     3 w. _$ q1 [; H: d4 O7 L' N
  19. ( G6 s* ?# \1 I+ g
  20.   TIM1->CR1=0x0080;     //ARPE使能 - _& O! n( u# n9 \6 E* Y. v  p0 G
  21.   TIM1->CR1|=0x01;      //使能定时器1                       $ Q  a# u% O+ E4 M3 r
  22. }
复制代码
下文具体分析上面的代码。
8 e+ m7 v3 j  @* _7 U  Q3 B* ~前面4-6行是用来配置GPIO口的。
. \7 m8 w* x, S7 M5 M! X# Y& G
  1. TIM1->ARR=arr; //设定计数器自动重装值
    3 Q+ v$ ?. R% c% L, R9 L0 z: w+ a
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。
) N$ a3 j+ S7 n! d
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式& N, o" i, u" L7 L9 r) S& ^1 d
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能: v' f- P8 r: A, v# Y
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。; S, R, A- b! i9 q+ I
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。& H- I. @3 {% A3 |$ c0 @: b
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。/ e' r8 b# v$ f
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。
! q( k# _9 N; S/ p7 M& X; p6 a. X3 E

  R# G' {9 X$ c$ O* d上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:# r6 I1 _$ l* t
  1. * l, X! d( w' v+ q
  2. for(i=0;i<300;i++){  d; A5 W. U" ^) m
  3.   TIM1->CCR1=i;, f# V8 I& v9 Z4 l5 V
  4.   if(i==300){
    7 V2 g$ |+ j; H& W' d
  5.     i=0;/ T! e5 X' m* A7 @1 ]! i: C
  6.   }
    - p( j4 `3 G' F; `' {5 Y
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。
" O1 K- B/ M2 X8 B" m
0 b* c" d# W' e0 L8 m# j: O7 C/ D8 i4 a

) @7 p7 _4 l2 A/ \2 o    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。  f# J2 k$ E; U! P& s" N# P: N3 l
: z. H2 q2 D7 F2 R7 {
* w0 }* A9 n. K1 A3 A( W- X

! U' e" S6 L# S8 m6 ?; z/ K) G* n

7 F" c9 \0 Z0 d6 M# C- N' ]2 k3 z+ p2 S9 J
5 \, W( L1 o- r, b* f

4 Y, ?$ g% D# o# \! ]$ M
收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答

所属标签

相似分享

官网相关资源

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