1)什么是PWM
0 f5 A2 z- i4 d9 M5 [) K4 R% s. H- w. D1 Q" {4 B
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。' t" n% ~2 P" U H/ U2 @6 d
: h9 I2 H" ?6 m9 k9 h2)PWM原理$ b- M, I( |: Y) D
2 N& A F- Z$ @5 {$ p9 F/ D
2.1 什么是占空比
- K: _1 l4 y2 w6 b
% E9 R$ W9 G H9 }. D2 @( j0 w5 {- v1 z
) }# T% j# q' z8 ]4 B# a
1 W* s# @1 `4 y( L% G* I
从上面图片可以看出:
: A0 E v! m( y; A3 j第一个PWM波,周期为10ms,高电平的时间为4ms,所以占空比为40%,同理第二个PWM波为60%,第三个为80%。
+ F5 }/ q3 H& ~3 Y! n
8 ]" [# m8 z% q, |* `PWM的频率: PWM的频率的整个周期的倒数,所以说上图PWM的周期为1/0.01,也就是100HZ。改变PWM的频率是通过改变整个的周期实现的。所以通过改变高低电平总共的时间、改变高电平占总周期的比例就可以实现任意频率、任意占空比的PWM波。) Z. b* g9 T# O" y
# l+ K# K7 l# G
PWM的用途和优点:电机调速、功率调制、PID调节、通信等等,配置简单、抗干扰能力强,从处理器到被控系统信号都是数字形式的,无需进行数模转换。并且让信号保持为数字形式可将噪声影响降到最小,噪声只有在强到足以将逻辑1改变为逻辑0或将逻辑0改变为逻辑1时,也才能对数字信号产生影响,这是PWM用于通信的主要原因。8 b0 O5 W9 L; b( A
: |: T1 Z7 M& }# p; n! s" }2.2 重装处置3 `8 e" ~; k$ O5 l o& h
5 c2 U; y$ A4 |% N
6 k- L. j4 ]) g$ P上图可以看出:9 L1 B! O9 N. d0 ^3 `% l& d
9 s- k( w/ q1 Y7 ?+ R0-t1段,定时器计数器TIMx_CNT值小于CCRx值,输出低电平。
# [- ^0 x- h& @2 i/ w
1 j1 W' j$ f6 C: R' G, J3 P: _t1-t2段,定时器计数器TIMx_CNT值大于CCRx值,输出高电平。0 T l' o9 }; |7 b) J; u3 p2 H
0 |8 k) Y& r% }3 O. q, h当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数…循环此过程至此一个PWM周期完成。6 C" R6 i" C/ z- A, @* B& k ]. l
7 o0 V* \ [6 V
上图更加形象的说明了2 K$ N! F5 I$ N- P0 M% p1 E7 _
1 {5 s% |) @0 Q( u1 I5 p+ E
信号频率由 TIMx_ARR 寄存器值决定。
) {( V2 C1 e8 ^; {% M
! G+ D. D; {' k& p w占空比则由 TIMx_CCRx 寄存器值决定。8 ^ c" g) E' w0 a
- o: B7 {, u9 R6 N: @' g0 t4 B
3)代码展示
3 V+ G- b. u Q; P& y0 H, z: r% h+ C* X, r/ U8 y9 I% ]+ |
pwm.c文件6 O4 Z% c; `# ?; V
9 V# u9 A# _; y' `' S7 S- #include "pwm.h"2 c3 j V) I7 @
- //TIM3 PWM部分初始化 , V+ T1 Y7 }0 J& `
- //PWM输出初始化
0 B8 n1 O8 k3 a) t$ t, e, ] - //arr:自动重装值
% f0 t, k2 [* Q - //psc:时钟预分频数+ o: k2 }1 G! D
- void TIM3_PWM_Init(u16 arr,u16 psc)7 x' y! m9 S9 j7 S0 M) ~( \( ?
- {
( m. _9 C0 _2 |- m1 g6 e. a - GPIO_InitTypeDef GPIO_InitStructure;% ~: A- d9 C9 Y& Q+ e" S3 E1 y
- TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;# D/ m3 O$ A4 `- u6 o$ b" n
- TIM_OCInitTypeDef TIM_OCInitStructure;* n! O( m* ^- G& t
-
L4 v. F- H# O* F: i - 9 B* v: `4 d7 I! G! o5 [$ I
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能定时器3时钟
5 R# C+ m5 T) p2 h* Z, J - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //使能GPIO外设和AFIO复用功能模块时钟
7 r, f1 P$ ~' L7 }% r \ - 5 ^& f2 [# {1 m+ f* Q" v0 ^' G
- GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); //Timer3部分重映射 TIM3_CH2->PB5
7 ?6 c9 O/ v4 n! Y" g" X2 }
B' A8 S; |6 L' Y- //设置该引脚为复用输出功能,输出TIM3 CH2的PWM脉冲波形 GPIOB.51 H/ l2 n8 r* T9 b1 | [8 O" A
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //TIM_CH2
" s d' I; H9 m. U - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
/ t3 y% O. V a - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;* g' W2 E0 q B o! y
- GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIO% `2 s$ l5 [! M- P; f5 m3 Z
; n1 f+ C* r/ s/ o2 o, t- //初始化TIM3
# Q% l% P& y* V' y8 ? - TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值- _/ p: U3 c+ S) |
- TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 ' D2 Q" |: H& G
- TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim4 g2 |) q% X( p7 m/ ~
- TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式
. C" r4 x7 G( i2 j8 r9 w2 a x - TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
' c3 o! H5 \5 @, x( L5 W0 r -
# ]8 p1 r7 e1 A3 n! {& K - //初始化TIM3 Channel2 PWM模式
, ~6 ?1 x! b0 R, h% E - TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //选择定时器模式:TIM脉冲宽度调制模式26 r2 ^# q/ z$ r* V j
- TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
, S4 S; ?: Z/ r% C7 A - TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //输出极性:TIM输出比较极性高/ f7 F+ @5 y5 I" }3 s# \6 r2 r
- TIM_OC2Init(TIM3, &TIM_OCInitStructure); //根据T指定的参数初始化外设TIM3 OC25 D% I8 E0 r% \1 z
- : N* n, `3 b9 I8 m
- TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器
+ O' f) W; m9 L* A - % b7 Z$ w' @& U; H
- TIM_Cmd(TIM3, ENABLE); //使能TIM3
4 B1 W( b6 Q: D" K3 r$ b; Z - % i( j1 ~) b; a, M
- ; T p/ b/ ]2 I; F. x" u
- }
复制代码
1 p; k8 k" K2 n8 w3 S# Z) Xpwm.h文件
( h6 k* Y* @3 C; \" a' G- o* w! u
- #ifndef _PWM_H_
+ T4 O+ [8 _) r* y- ^, A, d - #define _PWM_H_
2 s3 f) I( H$ M" @, G$ x
" l! n3 n5 _( W* V" k- #include "stm32f10x.h"! T1 J* ^+ g( z4 j: w' Z" c
- void TIM3_PWM_Init(u16 arr,u16 psc);
) S5 A; h G2 N - #endif
复制代码 9 q& s- [1 j9 \+ D+ S' s+ U# N
Main.c文件( f4 l M& v/ R. f5 b# P5 w
9 P) y" b9 e, W' x- #include "stm32f10x.h"
% B3 r; f, ^' s, \ - #include "pwm.h"
- {9 y7 s' q3 { - #include "delay.h"( ~' x. j2 l+ B H
- #include "led.h"
9 Y# Y% l( o5 o; o: Z - 1 D( y x% S$ M) g
- int main(void)
% P) M, W7 z: r! T% h& i2 t( P - { 6 v/ |# h) P/ j; V) U3 N7 W6 }8 z
- u16 led0pwmval=0;& J) D1 u% E" v! ], ]9 j$ ?
- u8 dir=1; : T" S5 A' H$ N3 h
- delay_init(); //延时函数初始化 9 s- q, \! m9 X/ \3 j9 q5 d
- LED_GPIO_Config(); //LED端口初始化
4 x- ` p, }5 l% J - TIM3_PWM_Init(899,0);+ a/ H0 I8 P5 U& N
- while(1)5 Z1 C$ Z' s2 y1 f& N
- {+ P' X8 @/ l& m7 a, E8 ], k- T0 d
- delay_ms(10); ; }0 I \& [" a( J) c( H+ e1 a8 b# m5 S
- if(dir)led0pwmval++;* U" h! E k i9 c- @/ [4 \ V9 w
- else led0pwmval--;# z1 \. Y9 i: t* V) ~
$ W( W3 _8 b+ R1 _/ i8 w- if(led0pwmval>300)dir=0;2 a* o& x3 V4 C+ R$ s o0 `
- if(led0pwmval==0)dir=1;
- y* T' g0 x2 [& z! P- F% d* Z$ Z - TIM_SetCompare2(TIM3,led0pwmval); 0 E. [' |& s. G1 g" C* M
- }
" ^" m" S! q u9 D9 M4 b# N' I& y - }7 c. `& ?2 {9 `8 y: J6 ]6 h
复制代码 7 A2 o/ k& \9 t
, T f. \% k0 {/ w————————————————
# p4 L; F! I0 o2 B4 y, z版权声明:@slow-walker# r$ w3 ?* X1 U: P# u- K
3 F; Q, f% n8 O0 {. \' O+ H7 ?* j
1 a8 x2 l8 j% N+ n
|