1、PWM是什么?
! C; O+ Z, b6 ]2 {* t; ^% l |9 _1 D( ]. m3 S0 u5 p y2 J
是脉冲宽度调制,简称脉宽调制。利用微处理器数字输出对模拟电路进行控制的一种有效的技术,就是对脉冲宽度的控制。
( {, m# A% |6 R% L" z0 {. r& }$ o$ o8 \, e! ]; a& F
这里说的脉冲,就是我们产生的方波。方波就是N个这样的周期连续的产生。
3 p4 w; r9 P! h( t. X3 j1 H; {* F- G, p% j' K3 W' P
( R# S4 Q$ B2 d( {( Z
; D, M9 u, V' U一个周期内高电平持续的时间就是脉冲宽度(脉宽),而PWM(脉冲宽度调制)就是控制一个周期内的高电平的持续时间。
( b( w( r& m" p' T7 d% A5 S2 y+ N( m5 w5 K" t0 \
2、简单的PWM的原理示意图
$ `% }! v( O( z) |/ G- M: S" @% W/ a! `7 A, D) J# _! S
/ Y. d {! n0 j/ @
2 Z: t% ^: ]& t% pCNT:是当前值寄存器,计数寄存器。
6 d# D! L/ p* w# P9 l& ~8 F$ {, e% b' Y2 V S) J) ?/ e
ARR:是自动重载寄存器(初始化设定)。
P8 Q s2 d, F) _) t( {2 z8 e* A, K, d* p" N' t1 l# \' j Q
CCRx:比较值寄存器(TIM_SetCompare1()设定修改占空比)。
0 a1 m4 x; q* I) q$ W* S- \1 F- v" P! P2 |' J* ~5 u
( v4 c: i7 { H' x假定定时器工作在向上计数PWM模式下:& E8 e6 N1 n2 \: A) Q3 M6 e
9 U( h* K, ^2 s) @5 u6 X; I
当CNT<CCRx时,引脚输出0,当CNT>=CCRx时,引脚输出1。2 K* q6 H+ h) q2 _0 w9 y
) r2 o- _* v* G" l当CNT的值小于CCRx的时候,IO输出低电平(0),# e# R% r' D$ c W
5 D* c5 q* e7 C. w7 V
当CNT值大于或等于CCRx的时候,IO输出高电平(1),
# q9 G% W. c# |- z7 ?. }, I; @/ l
9 o# p) `- m9 l0 U9 n" s当CNT的值达到ARR的时候,就会重新归零,然后重新向上计数,依次循环。4 }2 t7 e& w2 g+ F" X6 n5 \
; s0 [ O" l1 C* i. r0 S2 F7 k/ z: S( m
改变CCRx的值就可以改变PWM的输出的占空比。改变ARR的值,就可以改变PWM的输出的频率,这就是PWM的输出原理。1 x- {* Z) g6 \2 [4 u$ m% a
7 Z6 p5 n2 S" I' l3 v6 c
3、寄存器工作流程:) q) U& l# Q) f: e
7 w6 Z# D$ u( Q% R; [6 B: f
* V: p; ^* c, \ z4 p# f: v7 T ~ N/ X2 R- t' k" j: ~5 C" h
PWM 模式0 U% o8 r. h) B6 ~0 p0 s
/ A. L6 ~& X: \5 o U脉冲宽度调制模式可以生成一个信号,该信号频率由 TIMx_ARR 寄存器值决定,其占空比由 TIMx_CCRx 寄存器值决定。
' |6 T7 r' k9 L$ O2 S4 j0 m- v+ r3 _3 E; x8 a) _
通过向 TIMx_CCMRx 寄存器中的 OCxM 位写入 110(PWM 模式 1)或 111(PWM 模式 2) ,可以独立选择各通道 (每个 OCx 输出对应一个 PWM)的 PWM 模式。必须通过将TIMx_CCMRx 寄存器中的 OCxPE 位置 1 使能相应预装载寄存器,最后通过将 TIMx_CR1寄存器中的 ARPE 位置 1 使能自动重载预装载寄存器(在递增计数或中心对齐模式下)。1 {7 _ T2 _7 D+ o+ N
6 ^( O& E9 Z. U9 E' a3 T由于只有在发生更新事件时预装载寄存器才会传送到影子寄存器,因此启动计数器之前,必须通过将 TIMx_EGR 寄存器中的 UG 位置 1 来初始化所有寄存器。OCx 极性可使用 TIMx_CCER 寄存器的 CCxP 位来编程。既可以设为高电平有效,也可以设为低电平有效。 OCx 输出通过将 TIMx_CCER 寄存器中的 CCxE 位置 1 来使能。有关详细信息,请参见 TIMx_CCERx 寄存器说明在 PWM 模式(1 或 2)下, TIMx_CNT 总是与 TIMx_CCRx 进行比较,以确定是TIMx_CNT =< TIMx_CCRx。' f0 ]% A8 j; o; R7 A: k
+ Z7 ]1 @! @* O- V2 d8 K因为计数器采用递增方式计数,所以定时器能够在边沿对齐模式下生成 PWM。
' l5 R! w- a8 A5 Q+ }) l; L. V" x/ Y8 @6 B
4、PWM 边沿对齐模式
( N) `* h* C4 X& R T/ M9 J* g% h3 ]
以下以 PWM 模式 1 为例。只要 TIMx_CNT < TIMx_CCRx, PWM 参考信号 OCxREF 便为高电平,否则为低电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“1”。如果比较值为 0, 则 OCxRef 保持为“0”。 图 183 举例介绍边沿对齐模式的一些 PWM 波形 (TIMx_ARR=8)。# D5 z: r# i& w Q
% @' H' ^; r c5 R
9 d7 g5 Q1 j- t9 f4 a$ t4 `. P y3 K( S; f
5、PWM步骤-灯光亮度控制:% [* ?' R1 \0 F! y( U ?/ T
3 w- W1 D% H+ X; j! `. ? 查看LED的原理图:
. z6 D- d( }( X6 h8 [
& {% o( ]6 @( ?3 X
/ e8 F9 g' c; O5 u& K. x4 ~3 U
1 v7 W% N% f: v7 i: Z& ]) B! L6 e
1 F9 ]$ F+ W' U6 l( F- //①根据原理图找到4个引脚:
: `7 f; g- _$ W - PF9可以使用TIM14_CH1,表示可以使用定时器14的通道1产生PWM输出。
+ c" B T! N: ], X$ o' ^% b) d+ N" V - TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct; // 定义的TIM属性结构体变量- h% S* G+ `& R
- GPIO_InitTypeDef GPIO_InitStruct; // 定义GPIO类型变量
% f: H" z9 n! w' A) R - TIM_OCInitTypeDef TIM_OCInitStruct; // 定义复用功能的变量
" p w' p' d4 k
# ^, {3 T) q5 L& D/ a- ②// 1.初始化时钟:TIM14 和 PF9
. S& z3 i V: x6 x7 W - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
|, w& r$ A* E0 b% Q' r8 B: _( t/ _0 K - ! b! e- S& @- ?: z5 T
- /* TIM3 clock enable */( l E2 w' V& x( k j3 T- V( X+ A; t
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
7 q2 ~/ [4 ]: k8 x7 g - ' s( S! e' D0 D }
- // 2.配GPIO引脚为复用功能
5 {. L: O% n' [ y7 Q, {3 x N& q% x - /* GPIOC Configuration: TIM14 CH1 (PF9) */
1 O5 V/ D8 v7 e- ~* V - GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; // 选择引脚为PF9
- v. E+ Y" O+ G3 y8 ~ - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; // 设置为复用功能
' p0 d' R" V/ M; o! o" [, @( j. ] - GPIO_InitStruct.GPIO_Speed = GPIO_High_Speed; // 设置输出速度为100MHz# M: F( x7 y: {" H! \, ]
- GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; // 设置为推挽输出# | F# d, |; J. a; n1 h$ `$ g( y
- GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; // 设置为上拉输出
2 H* X0 s& Z2 r9 @' w, x* P8 L1 D0 P - GPIO_Init(GPIOC, &GPIO_InitStruct); // 安装参数5 O4 A/ g# P% W3 r
! L# r0 F1 r3 U' \0 N( J- // 3.将TIM和引脚的复用功能连接:TIM14和PF9连接起来' U; l& R- Z% h
- GPIO_PinAFConfig(GPIOF, GPIO_PinSource9, GPIO_AF_TIM14);
3 f( q; O6 z: W8 n# h# a# j: O, C4 a - 8 _3 U" _; j& A" v: T- \
- // 4.配置TIM定时器的参数
4 k) z0 P. J. ?* q - TIM_TimeBaseInitStruct.TIM_Period = 100-1; // 设置重装载值 ARR(控制频率)' i P9 k1 r* J4 ]
- TIM_TimeBaseInitStruct.TIM_Prescaler = 8400-1; // 设置预分频系数:周期(次) 100Hz == 100us
9 Q0 V+ \% T# z - TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; // 设置再分频值:TIM_CKD_DIV1就是不分频
+ s8 K2 X+ D; c - TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 设置计数模式1 H% a# g* m1 z6 B3 J
- TIM_TimeBaseInit(TIM14, &TIM_TimeBaseInitStruct);
, K6 O' `( G8 U+ D
# C$ ^$ i) n! _3 v L6 @- // 5.配置复用功能:PWM
2 f% d! x: k0 V, S! P8 m z# b - TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; // 配置为PWM模式1
1 [7 \ n5 x5 ?# J# I - TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; // 开启输出使能( i' G; g* ?- B; u' [
- //TIM_OCInitStruct.TIM_Pulse = CCR1_Val; // 初始化配置比较值寄存器
! x+ ^$ C$ Y, u$ l4 [" L9 } - TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // 配置为高电平有效: s7 ~( x: r7 f
- + `' P {2 t M4 j5 D3 s
- // 6.TIM14通道1初始化0 T- C; L \% `9 F, U1 D) y
- TIM_OC1Init(TIM14, &TIM_OCInitStruct); // TIM14通道1初始化7 X; O; j) N5 l# g7 m9 v% o$ V
- # _0 i/ l( ^+ d; l5 w: r7 ]" |* {
- // 7.设置自动重载比较值CCR1初值,不断产生PWM脉冲- q- E7 c# M: z) ]7 P/ N
- TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
; v( v7 _) i: I; H9 ^$ O/ y
9 u C+ B5 D$ }) ]+ N
5 I, @$ |! I5 F+ B+ w- // 8.设置自动重装载值(ARR),不断产生PWM脉冲
+ K! f. ?" _) r2 B5 ^3 \. y - TIM_ARRPreloadConfig(TIM14, ENABLE);
0 D R" f c: k W9 b5 \7 i( ~ J' _
% \3 y& [ C; z* O& X4 _( a- /* 9.使能定时器14 */8 ?! D$ J2 F g2 F+ [) N0 l" ~+ x
- TIM_Cmd(TIM14, ENABLE);# P0 S7 v! ~/ H0 R
3 D: M8 V9 y7 O, R* K+ p- // 10.使能TIM1PWM输出(高级定时器)/ S! @& c3 }- k0 U4 b$ r ]9 y
- //TIM_CtrlPWMOutputs(TIM1, ENABLE)
5 z# Y! z9 h$ @. a+ R - 6 m+ h' c6 [8 _, ] x" F6 t
复制代码 * _. k3 H5 u5 b8 H# V/ v; k. W
设置比较值函数0 }! Z! @/ @% {$ k) i: f( X
4 E5 Y Z( ~6 n
- void TIM_SetCompareX(TIM_TypeDef* TIMx, uint16_t Comparex);
复制代码
+ N- x$ O f/ S# u0 b4 A$ V4 ^& ]7 M; X$ f
7 N# [% e( P1 Z# u) o! N* X8 y1 q$ j |