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

STM32 PWM输出

[复制链接]
STMCU-管管 发布时间:2020-9-10 10:18
01 PWM介绍
PWM定义:脉冲宽度调制(PulseWidthModulation,PWM)简称脉宽调制。通俗讲,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。

" G) `- B% {: L+ w* t
电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
/ |3 k7 e$ X5 N- X+ i
占空比定义:占空比就是高电平所占整个周期的时间,如下图所示:

6 X5 I. t3 w1 b! B& S/ k
1.png

+ W- [- y6 V/ y& q& O( I$ G
第一个PWM波,周期为10ms,高电平的时间为4ms,所以占空比为40%,同理第二个PWM波为60%,第三个为80%。

( H6 O9 Y& A1 E' Q3 o; ]" _
PWM的频率: PWM的频率的整个周期的倒数,所以说上图PWM的周期为1/0.01,也就是100HZ。改变PWM的频率是通过改变整个的周期实现的。所以通过改变高低电平总共的时间、改变高电平占总周期的比例就可以实现任意频率、任意占空比的PWM波。
3 B5 \* E1 Q+ ~0 W& c, u
PWM的用途和优点:电机调速、功率调制、PID调节、通信等等,配置简单、抗干扰能力强,从处理器到被控系统信号都是数字形式的,无需进行数模转换。并且让信号保持为数字形式可将噪声影响降到最小,噪声只有在强到足以将逻辑1改变为逻辑0或将逻辑0改变为逻辑1时,也才能对数字信号产生影响,这是PWM用于通信的主要原因。
" f% `" u6 o( {! ~$ _+ j3 Q
02 STM32的管脚复用
STM32没有专门的PWM引脚,所以使用IO口的复用模式。首先确认PWM功能的输出管脚,使用定时器9。从下面的框图中得知,timer9只有两个输出通道,所以timer9只能输出两路PWM。
+ E9 u% g) N' _$ p$ `( n# ?$ W
2.png

. n3 i# M2 b& ^# Q3 G0 c- }, J' D
在STM32F207数据手册中的Alternatefunction mapping图片中,timer9的两个通道分别可以复用为PA2,PA3,PE5和PE6。
& [1 Q+ O. @4 O/ C
3.png
03 STM32输出PWM原理
1 Y1 H) J' N/ q/ P  \" R
下图中的①部分,在《[color=var(--weui-LINK)]STM32基础定时器详解》讲解过了,关于影子寄存器,也在《[color=var(--weui-LINK)]STM32影子寄存器》中讲述,下文不再赘述了。本文将重点在②部分,捕获/对比通道讲解,其中STM32的PWM就是利用对比通道实现的。
% ^% S4 o) a8 J/ ?5 [
4.png

0 V: m1 A( N) i0 G. G
Pulse Width Modulation mode allows you to generate a signal with afrequency determined by the value of the TIMx_ARR register and a dutycycle determined by the value of the TIMx_CCRx register。
节选自STM32F207 Reference manual手册
' Z! R4 t% d: P) j3 t! G

# K( Z, q1 H" [% ?# _" d
脉冲宽度调制模式可以生成一个信号,该信号频率由TIMx_ARR 寄存器值决定,其占空比则由TIMx_CCRx 寄存器值决定。9 e( G$ ?7 o  x3 R& R

1 N$ a* U8 x' C0 o8 }
从下图可以看出,当CCR寄存器和CNT计数器数值一样时,会产生动作(改变通道对应的GPIO电平)。由于CNT溢出时,重载值由TIMx_ARR寄存器值决定的。所以说TIMx_ARR寄存器值决定周期,而TIMx_CCRx寄存器值决定CNT溢出时,经过多久会产生动作(改变通道对应的GPIO电平),也就是决定了占空比。
7 T& \1 x  y/ Q3 x
5.png
" `) j5 l7 O7 A3 J0 N
以向上计数为例,重载值为ARR,比较值为CRRx

$ w/ b8 z: s/ |$ \. Y

; \% U" w8 Z6 I$ u' c. X
6.png

5 K* R; i( _7 m
上图可以看出:' o: _6 i1 \; }% i% w
7 F- M+ f( e; \. @8 O
  • 0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平。
  • t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平。

    3 s; U2 E% s+ t: A
    ) M+ @6 `) `6 X! g3 n
当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程至此一个PWM周期完成。

" \4 [- e/ l- V- s+ F) W
上图更加形象的说明了
  • 信号频率由 TIMx_ARR 寄存器值决定。
  • 占空比则由 TIMx_CCRx 寄存器值决定。
    + ~( h% L) C/ B; F! F: ]1 ~' T% U6 Z
    * L' L. F3 V* ?  o5 j+ g( H

0 @4 `5 F, a  h9 r* u
STM32输出PWM的过程:
1、首先配置GPIO,配置定时器,具体参考一下代码。定时器配置参考《STM32基础定时器详解》。
2、捕获/比较通道使能比较通道。
  ~9 ?8 Z* h9 A3 r7 h* Y) {
7.png
9 ]3 r4 N' U( R" i# w. M
上图看到,①寄存器名字为:Capture/Compare1register。可以选择从②处输入捕获,也可以选择从从③中输出,也就是我们需要的PWM输出功能。选择捕获通道,还是选择比较通道,在框图中没有找到具体的说明,但在TIMx_CCMR1寄存器CC1S[1:0]控制位使能。
$ m* w& Z- O8 V5 e  S1 D1 `# f
8.png
& h) L6 n2 n, }' b4 P& ?& Y
3、使能完输出,就要配置PWM输出了
; x; e4 ~0 I6 w
9.png
/ H1 o  L: c" Z0 ~
①TIMx_CCMR1寄存器的OC1M[2:0]位,设置输出模式控制器
! D7 t/ H  a! M. |' p
110:PWM模式1,111:PWM模式2。

/ V6 R* n/ Q: K

6 X4 w- r: @3 r/ Y
②计数器值TIMx_CNT与通道1捕获比较寄存器CCR1进行比较,通过比较结果输出有效电平和无效电平。
8 c! O  K" P5 l4 W4 i6 b, L

+ q$ V% `8 k" x/ x$ {& M
OC1REF=0 无效电平,OC1REF=1无效电平。
* M) }8 ?7 I. k9 p! ?  G( L
③通过输出模式控制器产生的信号。TIMx_CCER寄存器的CC1P位,设置输入/捕获通道1输出极性。
2 X* A  g7 d$ ?8 j+ ~. q
0:高电平有效,1:低电平有效。

) D; k3 V2 T& Y# ~
④TIMx_CCER:CC1E位控制输出使能电路,信号由此输出到对应引脚。

6 y' f( ?3 |' U
0:关闭,1:打开。
: }# q  K9 ~  F& X8 i: \' i- o- M5 ~" m
首先对PWM模式1和PWM模式2进行介绍:
01 模式1
, }/ `" E2 X' o. o% b. M% T  n/ `7 h  N
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;在向上计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效电平(OC1REF=1)。
02 模式2# n( k/ ~0 Q. J% \; c7 d7 I; i( g
在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

* `5 C9 A& e7 t9 Z) k  s
TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。% m, d8 h) m1 }* Q- T
7 `# k9 d1 l6 @: ^
PWM输出高低电平由TIMx_CCMR1:OC1M位和TIMx_CCER:CC1P位共同决定。
" G- E) [" k9 a# q5 g
总结下来:
% Z2 X8 E' }% |# v5 U' g
模式1:

0 Y7 ~& k+ F& L/ ]( h+ m
    CNT<CCR为有效电平//(OC1REF =1)
    CNT>CCR为无效电平//(OC1REF =0)
* _" ~, _) ~+ D/ m3 I6 l7 a
模式2:

* i  i! P( T7 Q4 i! O
    CNT<CCR为无效电平//(OC1REF =0)
    CNT>CCR为有效电平//(OC1REF =1)

" K2 E# m' G# G7 a
CC1P:
    0:高电平有效
    1:低电平有效

$ q5 k& q2 L0 P5 A% ?+ h0 h04 STM32输出PWM配置

6 m, m2 ~, E( w1 I/ ?
分析了原理,那么下面就分析STM32生成PWM的过程。

& @: n- t1 ~. {. ^7 S& e
1、首先要将GPIO设置为复用输出
0 ~1 F# f- |2 y3 ?
  1. , b( F8 T5 v! Y& N( _
  2. /* GPIOE clock enable */3 s$ d% }+ P# i- Z. z( K
  3. RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
    ) |! H( y. x4 b* L$ F

  4.   O1 K0 J( X4 ~, `$ g4 d* w2 ~, r
  5. /* GPIOE Configuration: TIM9 CH2(PE6)*/
      a8 l! V9 b+ n) b. Z% U
  6. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 |GPIO_Pin_6;
    & p* @: K  |" v
  7. GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF;% e6 d- H. `- P: ^" S
  8. GPIO_InitStructure.GPIO_Speed =GPIO_Speed_100MHz;
    7 G& H4 W; r" f% S7 L& x! z" J
  9. GPIO_InitStructure.GPIO_OType =GPIO_OType_PP;
    ; B# n* i5 S% j) r
  10. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    ! A0 j; f. C" C4 E% E) b& P' k4 o
  11. GPIO_Init(GPIOE, &GPIO_InitStructure);, k5 |3 h7 \4 y9 t5 G2 z' x
  12. 1 b, K+ [4 O2 u$ p) r; I! b
  13. /*Connect TIM9 pins to AF3 */  
    ! H, R2 q; N' A$ T, D  w( t3 l
  14. GPIO_PinAFConfig(GPIOE,GPIO_PinSource5, GPIO_AF_TIM9);) K3 @3 x3 X# L, T
  15. GPIO_PinAFConfig(GPIOE,GPIO_PinSource6, GPIO_AF_TIM9);
复制代码
0 T8 X- n1 T, U; ~* j! d
2、配置定时器向上计数,配置定时器频率

" F% w' m9 G7 V2 h/ W$ L9 B" I

/ W# l  K* I& y

  1. 9 `$ e5 k7 @/ y& K9 _
  2. /* TIM9 clock enable */* x: t% h. t6 ^, Q
  3. RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9,ENABLE);
    ; K( ]2 ]5 f$ ~
  4. / Y% H% q0 F( h, n# d
  5. /* Compute the prescaler value */1 z& {8 h6 k' _1 @
  6. PrescalerValue= (uint16_t) ((SystemCoreClock) / 2000000) - 1;# C! @' @- Z: q- l1 G3 x

  7. $ T- m% ^8 N8 }* k# u
  8. /* Timebase configuration */
      J* l" j' J5 C# e" U
  9. TIM_TimeBaseStructure.TIM_Period =1000-1;
    3 ~6 [, w/ r, _" H+ ?. V: B9 Y
  10. TIM_TimeBaseStructure.TIM_Prescaler =PrescalerValue;& Q2 x' ^8 q# v2 D: u. W3 j
  11. TIM_TimeBaseStructure.TIM_ClockDivision =0;. }, H: ]7 A& O
  12. TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;% l+ i9 w! b: _3 h
  13. : w& k& O2 X. v0 p9 `. n' S7 d
  14. TIM_TimeBaseInit(TIM9,&TIM_TimeBaseStructure);
复制代码
. e# B( t: f1 f! R5 v
/ h# t, T2 n+ L/ x( t
# ]0 ]; ~7 y$ B5 ?
1 E8 Y7 }0 v+ Z' N; i$ R

0 n5 ?! |5 e1 R# j/ c+ ~( H! \( I3、配置PWM输出上面分析过程较为麻烦,ST提供了标准外设库,我们只需要配置TIM_OCInitTypeDef结构体即可。
4 w  t+ D+ o+ {1 r/ ~  ^2 q

  1. ' _5 B& i; K7 f# j
  2. TIM_OCInitTypeDef  TIM_OCInitStructure;
    3 O7 y2 g% ?7 c  G4 U! y" w

  3. + n- }! c  [7 ~. Z2 N
  4. /* PWM Modeconfiguration: Channel1 */
    2 K, z# e& G7 l, y8 j; i8 j! ]
  5. TIM_OCInitStructure.TIM_OCMode =TIM_OCMode_PWM1;
    ( x$ Y: N% }& b. h7 K9 u
  6. TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Enable;! w# W0 i) I& r- a, X& q& L9 u
  7. TIM_OCInitStructure.TIM_Pulse =100-1;
    9 h+ s* m; o# o2 L3 @* V2 o
  8. TIM_OCInitStructure.TIM_OCPolarity =TIM_OCPolarity_High;
    1 b7 x6 Q8 ~" f- L

  9. % p* @5 X5 C% N0 [
  10. TIM_OC1Init(TIM9,&TIM_OCInitStructure);! d; Q9 U' _- f+ L
  11. TIM_OC1PreloadConfig(TIM9,TIM_OCPreload_Enable);
复制代码
9 K9 v% z* x, j. J7 l+ |
; N7 g7 B/ n/ q8 \  }
5 D$ @$ F! Y- w# U( i% n
TIM_OCInitTypeDef结构体解析

! a: T( Z- O7 L, }" @+ r9 ~

  1. $ L8 @' i4 w% _1 Q- b
  2. typedef struct
    # ?* p% L3 p$ O6 ~. G5 \/ d, ?% v
  3. {0 l  G  i, P! t9 `7 e1 S, ?
  4.   uint16_t TIM_OCMode;      //PWM模式1或者模式2
    * J; ?6 _7 o( W. ]: t
  5. uint16_t TIM_OutputState; // 输出使能OR失能
    8 I# Q$ }* u/ @- J: e# x
  6. uint16_t TIM_OutputNState;  // PWM输出不需要1 n. k/ Z7 K, [" D! {% T
  7. uint32_t TIM_Pulse; // 比较值
    & Q: N3 v2 u7 d
  8. uint16_t TIM_OCPolarity;// 比较输出极性: ^8 {; E' ^' m& W9 o9 ^
  9.   uint16_t TIM_OCNPolarity;   // PWM输出不需要$ K  A/ q) V, m$ E0 J
  10.   uint16_t TIM_OCIdleState;// PWM输出不需要$ }0 n% t, r6 ?& u* M5 z5 W; {
  11. uint16_t TIM_OCNIdleState; // PWM输出不需要
    ' i: p0 Y  w2 Y" X: z
  12. }TIM_OCInitTypeDef;
复制代码
/ @! `5 V' K7 o# t
其中TIM_Pulse可以在初始化时设置,设置完毕后,也可以通过以下接口再次更新。

( k3 t2 ~) U# H9 n) Y: |% |: Q
  1. : H4 R+ O' o4 x5 N; ?
  2. void TIM_SetCompare1(TIM_TypeDef* TIMx, uint32_t Compare1)
复制代码

. n% V  g9 D! P  G2 i& A! b/ ~

7 r( R$ O3 ]) B3 N
4、使能定时器

: I- m2 r& h. o$ y) G5 `6 f& y8 f
  1. + H9 N8 B3 H& t- q! Y0 C+ P
  2. TIM_ARRPreloadConfig(TIM9, ENABLE);
    ; h1 S9 Y/ K  y  A

  3. + N/ Y+ _* }5 v" s) I6 M
  4. /* TIM9 enable counter*/
    & Y+ N; |. o6 k
  5. TIM_Cmd(TIM9, ENABLE);
复制代码
: I% W2 [; U9 g6 O+ v' r4 M! x
使用timer9输出PWM的波形。
10.png
5 \, L: Z6 ^+ \/ w0 B; I
, j% B  N1 D  y% ]+ i. k# r* n
6 z+ V9 y2 K$ c/ Y) y1 q
1 收藏 2 评论0 发布时间:2020-9-10 10:18

举报

0个回答

所属标签

相似分享

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