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

STM32通过PWM控制电机速度

[复制链接]
STMCU-管管 发布时间:2020-12-7 10:50
STM32通过PWM控制电机速度
, e  X* M0 q) N3 I; t) w2 j
; F, t* R3 g2 y
做STM32智能小车的实验中会用到定时器PWM输出,来改变直流电机的转速。分享本文了解如何通过PWM实现对电机速度的控制。
% u) F" E5 w, e: D0 Z' O/ F+ ]' u3 z4 @0 W9 ?4 r2 W

  g3 k; [5 p  oPWM控制电机速度的基本原理, m$ ]/ v' O5 [
    PWM(Pulse Width Modulation),也就是脉冲宽度调制。
' l5 Z$ `7 @2 K! n    PWM中有一个比较重要的概念,占空比:是一个脉冲周期内有效电平在整个周期所占的比例。+ r/ @% y& g" o; c$ {2 R8 W! v( H
9 J  A' ]% X8 j
% n/ Y+ t% ^8 s+ b' v. ^* z# w3 Y
    为了实现IO口上电压的持续性变化,可以调节PWM的占空比。这也能够使外设的功率进行持续性变化,最终控制直流电机转速的快慢。如何调节PWM波形的输出就是重点。3 |5 X5 L4 g8 d2 b2 P, F
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这两个寄存器的值了。
& v, v% L/ u/ S* X5 U4 D# z$ d" G0 [8 F' ]

4 h& _  R' F: c" A1 X! O# MSTM32定时器中断
/ {5 f0 x& o+ r  ^  O- V( b    为了便于理解接下来关于PWM应用的内容,先插一段定时器中断的知识。
8 E3 F1 l+ G& T+ ~( Q. D* ]3 ?0 h

0 h3 T/ ?7 l! S4 p+ o    产生定时中断是定时器的用法之一,与定时器用来进行PWM输出和输入捕获相比,定时器中断更容易理解、掌握。
9 _+ r/ }/ e' u# ~原理简介
0 f8 z+ h9 D# E+ C* O1 G    使用通用定时器进行中断的原理,其实和开发板Systick定时器进行中断延时很相似(Stm32入门——Systick定时器),即:用psc(预分频系数)设置好定时器时钟后,arr(预装载值)在每个时钟周期内减1,当arr减为0时触发中断然后进入中断处理程序进行中断处理。以下代码为例:
9 Y5 Y; Y2 g+ J( h0 g0 Z

  1. 0 I% z% c9 J# _
  2. void TIM3_Int_Init(u16 arr,u16 psc)1 [$ B9 @6 n6 H
  3. {
    ' u9 M; k; w( y/ W; I+ t$ m/ n
  4.   RCC->APB1ENR|=1<<1;  //TIM3时钟使能   
    - B! a. x) C- m' G" X8 X& A  g
  5.    TIM3->ARR=arr;    //设定计数器自动重装值
    $ K) Z+ y. M7 ]4 j: q
  6.   TIM3->PSC=psc;    //预分频器设置
    3 o0 h9 I$ B. T
  7.   TIM3->DIER|=1<<0;   //允许更新中断        + D) T' V5 x3 @3 B. I' R# `
  8.   TIM3->CR1|=0x01;    //使能定时器35 u- t5 C; L  x
  9.     MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2                  
    / J! V# i; `# G& C; ?/ s0 n
  10. }
复制代码
  1. RCC->APB1ENR|=1<<1
复制代码
解释一下上面这行代码,由于定时器3(TIM3)是挂在APB1上的外设,所以要打开APB1,这里的预分频器值psc是来设置TIM3的时钟频率的,如果系统时钟(SYSTICK)频率为72MHz、psc为7199,则TIM3的时钟频率就为:
- Q8 X$ Q; L) n+ Y! A/ a5 A! G" W
  1. 72MHz/(7199+1)Hz = 10KHz    //这里的“+1”是手册中规定的。
复制代码
10KHz是什 么意思呢?就是一秒钟会产生10K个周期,那么一个周期的时间长度就是1/10KHz,如果你想将定时器中断的时间间隔设置为0.5秒,那么你将arr设置为5000即可,因为arr每减1就需要一个周期的时间,减5000次就经过了5000*(1/10KHz)=0.5秒。
8 V9 d8 ^# O" E, `1 ^' ?+ T
  1. TIM3->DIER|=1<<0
复制代码
再解释下上面这一行,设置允许更新中断,即arr减到0以后可以触发更新中断,还有其他类型的中断。
; C5 {' p/ H: L  a, V
  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代表的是前两位给抢占优先级,后两位给响应优先级。
: B" ~) @, b2 a4 `: ~
2 S  b! {' P( N
3 y6 S* H) ?) G
PWM模式、有效电平% P, V5 O! d3 w1 ]
0 e  X  O' A: W2 r6 p9 G0 ]7 q* e; A

6 r/ \* [7 y3 G; m# ~$ Z! Q# f    前面介绍完中断,再说一下PWM工作原理。
2 K7 I" G: m7 `3 `- \; Q2 B* M7 ]5 ]2 P$ E! c' c/ W

) j6 h( O4 m1 Z! J# y, I: e    假设上图中ARR大于CCRx时输出为高电平,ARR小于CCRx时输出为低电平,但在实际运用中可能并非如此,有可能是相反的情况——ARR大于CCRx时输出为低电平,ARR小于CCRx时输出为高电平,至于到底是哪种情况,还要看PWM是哪种模式、有效电平又设置的是何种极性了。' o! @" J! Y* C, m/ N0 o0 Z3 T
) p! \6 `5 a! Y6 E" v# J* h  u  \" f
8 d+ Z3 g0 E1 D; R) t
模式1:ARR小于CCRx时输出为“有效”电平,ARR大于CCRx时输出为“无效”电平。8 K% Z3 w( n, l) t
: b: d' |  e2 T& }) \) I9 B4 x* G; S
* e) I" u% o) {# i* B3 p
模式2:ARR小于CCRx时输出为“无效”电平,ARR大于CCRx时输出为“有效”电平。
: t0 t* v3 l3 w# e2 f0 V2 b9 n, |; N5 j- ?, O

* _, [! w: n& s3 H: `% p: J! f0 p# j    这里说的是“有效”和“无效”,而不是“高”和“低”,也就是说有效电平可高可低,并非一定就是高电平。PWM模式、效电平极性,需要程序员自己配置相关的寄存器来实现。通过下面的代码来讲解。0 X% g: B3 z0 U+ u1 r$ B" t1 c
  1. TIM1_PWM_Init(899,0);//不分频。PWM频率=72000/(899+1)=80Khz
复制代码
上一小节讲过关于定时器参数的设置。使用定时器1的通道1来输出一路PWM波,这里的899设置的就是ARR的值,至于那个0是用来设置TIM1的频率的,不分频就代表TIM1的时钟频率和系统时钟相同,这里假设为72MHz。
- E  Y6 L; X, \* m4 G  \9 t
  1. . f+ w; e1 J# y/ S, ?0 s' v
  2. void TIM1_PWM_Init(u16 arr,u16 psc)' i6 u; _. \) W1 \
  3. {                3 E: i1 a9 b* b
  4.   //此部分需手动修改IO口设置
    6 K9 D9 U. Z# I+ [- D
  5.   RCC->APB2ENR|=1<<11;   //TIM1时钟使能   
    ' J5 y% O" n$ }. z
  6.   GPIOA->CRH&=0XFFFFFFF0;  //PA8清除之前的设置. A/ M' S: O' k
  7.   GPIOA->CRH|=0X0000000B;  //复用功能输出
    4 ^" `4 N9 r& u0 ?) _8 M" ^
  8.   
    " l) Q7 \) t2 ~' f3 V. B7 ?. y
  9.   TIM1->ARR=arr;      //设定计数器自动重装值
    . ^$ n4 {% g5 o2 I+ w
  10.   TIM1->PSC=psc;      //预分频器设置
    ; b% s$ i! K* E% ]9 _4 D
  11.   ( v8 y( B3 N  h) Q! l
  12.   TIM1->CCMR1|=7<<4;    //CH1 PWM2模式     
    + _6 F2 ^- J) x& P, C
  13.   TIM1->CCMR1|=1<<3;     //CH1预装载使能   
    ) h& E9 [7 S1 S; V+ B* Q, r2 Y
  14.    TIM1->CCER|=0<<1;     //OC1 输出使能     
    . D6 o% S6 n6 y  ~- V- m
  15.   //TIM1->CCER|=1<<1;
    $ g! C. ]! @1 [2 S5 J( P1 p5 f
  16.   
    1 a0 K1 g9 F2 Z# K
  17.   
    " w8 b- V. A/ y  ^! L9 ]
  18.   TIM1->BDTR|=1<<15;     //MOE 主输出使能     + f; O/ g  e0 p: k

  19. 8 [. z. q5 k* A! R8 x
  20.   TIM1->CR1=0x0080;     //ARPE使能 * l& n1 D; u6 t- i& n* |( {
  21.   TIM1->CR1|=0x01;      //使能定时器1                       
    $ Y7 L5 o1 v& w
  22. }
复制代码
下文具体分析上面的代码。; K! I& a/ \1 u
前面4-6行是用来配置GPIO口的。
) i1 N. c# g2 y% q9 `2 u7 ]9 g
  1. TIM1->ARR=arr; //设定计数器自动重装值
    6 }- D) V9 U: }/ w
  2. TIM1->PSC=psc; //预分频器设置
复制代码
这两行就是我上门提到的设置定时器的频率和重装载值。) O9 s4 n' f% y
  1. TIM1->CCMR1|=7<<4; //CH1 PWM2模式
    5 V8 _1 W  l, b/ |. z6 ?7 x
  2. TIM1->CCMR1|=1<<3; //CH1预装载使能- H' F$ `9 s# z$ Y3 G
  3. TIM1->CCER|=0<<1; //OC1 输出使能
复制代码
这三行是用来设置PWM输出模式和设置通道的,通道是什么呢?简单地讲就是输出PWM波的GPIO口,代码一开始不是设置了PA8这个GPIO口嘛,这个PA8就是通道1。使用通道的话要先进行输入输出方向、通道使能的设置。
5 x8 O& m, v6 ^  F7 H+ o1 B* z
  1. TIM1->CCER|=1<<1;
复制代码
这行代码是用来设置“有效电平”极性的,根据手册,当TIM1->CCER[1]这位置1时,有效电平为低电平,置0时有效电平为高电平,而默认情况下置0。
& q- b% o# j$ V2 P2 @+ V
  1. TIM1->BDTR|=1<<15; //MOE 主输出使能
复制代码
这行代码只要对高级定时器进行设置,普通定时器无需设置。6 k9 N; G; p6 d& Z8 c7 \/ F1 ]+ p
  1. TIM1->CR1=0x0080; //ARPE使能
复制代码
这行代码是用来使能ARPE,ARPE是什么呢,就是当它被置1时,你自己设置的CCRx会立即生效,如果它被置为0,那么你自己设置的CCRx值不会立即生效(可能之前ARPE已经有值了),而是当之前设置的CCRx生效后才会使用你最新设置的CCRx值。
5 X" P1 ~( i8 E/ r2 g
- F7 W3 s% Z9 w1 t! D( B

8 e, V8 i6 Q4 Y6 ^8 x9 T上面的代码里没有对CCRx进行设置,这是因为CCRx常常是一个变化的值,你可以在主函数中用一个for循环+if判断语句对它进行++或–的操作,从而达到连续改变CCRx值得目的,例如:3 Q7 a8 G) |8 z( P* c, V* V$ U. u

  1. ! e9 [( X) I- b! X5 N
  2. for(i=0;i<300;i++){
    . i' r1 D" e* D  P
  3.   TIM1->CCR1=i;' b# c) J2 A+ z9 C) |3 N
  4.   if(i==300){; I0 l  l2 O# a( r. |
  5.     i=0;
    9 E# }; f7 v9 J& \1 N1 g
  6.   }
    ) K, K# @- Z, Y9 u: @! e, R& k6 x
  7. }
复制代码
PWM波的周期是由定时器时钟频率和预装载值两者决定的,预装载值就是ARR。# r; K3 z) T# K. a
3 S- B, a4 U: T/ I9 m, Q' C. O8 O) p

0 v8 x2 U1 a8 t& [8 @2 L' c    预装载值PSC设置为899,那么,当定时器的当前值val从0增加到899时,一共经过了900个时钟周期,这900个时钟周期会产生一个PWM波形,也就是说900个定时器时钟周期才相当于一个PWM周期,那么PWM的频率就为72MHz/900=80KHz,周期为1/80KHz。
3 f3 l7 f. G8 q: G# \. B! w8 m9 ^+ [

) R7 c; R1 z- u$ }$ }& v/ g& M8 [+ L5 q- J6 \# z) W
. ?6 [, _+ K! ?
# f7 T9 _, c; [, G$ z

: T+ V0 O8 o* ]. C' H/ a+ j9 R5 n7 v7 L
赞 收藏 1 评论0 发布时间:2020-12-7 10:50

举报

0个回答

所属标签

相似技术帖

官网相关资源

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