PWM
介绍
脉冲宽度调制(
PulseWidthModulation
,
PWM
)简称脉宽调制。通俗讲,
PWM
是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。
补充知识:PWM在通讯等信号传输行业得到大量应用的主要原因。
其最大的优点是从处理器到被控对象之间的所有信号都是数字形式的,无需再进行数模转换过程;而且对噪声的抗干扰能力也大大增强(噪声只有在强到足以将逻辑值改变时,才可能对数字信号产生实质的影响)
图中为向上计数(当TIMx_CNT值达到ARR时,定时器溢出,重新向上计数...循环此过程至此一个PWM周期完成)
当处于t1到t2时间段,CCRX<CNT<ARR,下方逻辑电平为1(高电平)
当处于t2到t3时间段,CNT<CCRX<ARR,下方逻辑电平为0(低电平)
占空比:指高电平占整个周期的比例。(t1到t2)/(t1到t3)
PWM输出的原理。修改CCRx的值,即可修改PWM输出的占空比,改变ARR的值,就可以改变PWM输出的频率。
PWM的两种模式(编译的时候需要选择)
编译
本次编译需达成对风扇调节转速(Motor Module 直流电机(带扇叶))
/**
* 初始化TIM12的通道1引脚PB14
* 因为这个PB14是一个普通的GPIO引脚,如果要将这个引脚作为TIM12_CH1 ,那么得进行引脚复用。
*/
void TIM12_GPIO_Init(void)
{
//声明引脚初始化结构体
GPIO_InitTypeDef GPIO_InitStructure;
//总线外设时钟1使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14; //引脚PB14
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF; //复用
GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽
GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_100MHz; //不考虑功耗
//初始化引脚
GPIO_Init(GPIOB,&GPIO_InitStructure);
//引脚复用
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_TIM12);
}
/**
*配置定时器TIM12 输出PWM
*/
void TIM12_PWM_Config(void)
{
//声明定时器结构体
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//定时器输出比较结构体
TIM_OCInitTypeDef TIM_OCInitStructure;
//外设时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM12,ENABLE);
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//APB1 42Mhz TIM12=84Mhz
TIM_TimeBaseStructure.TIM_Period= 2000-1; //ARR计数最大值
TIM_TimeBaseStructure.TIM_Prescaler= 84-1; //PSC分频系数
/*
168Mhz/168=1Mhz 数一个数:1/1000000 s
数4000个数: 4000* 1/1000000= 4/1000 =0.004s = 4ms
*/
TIM_TimeBaseInit(TIM12, &TIM_TimeBaseStructure); //定时器初始化
//pwm 模式配置
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //当定时器计数值高于CCR时为高电平
//TIM_OCInitStructure.TIM_Pulse=800-1; //CCR
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OC1Init(TIM12, &TIM_OCInitStructure);
//注意这里,是将结构体中的CCR值写入寄存器,如果后续想改变CCR,则使用其他方法
TIM_OC1PreloadConfig(TIM12, TIM_OCPreload_Enable);
TIM_Cmd(TIM12, ENABLE);
}
/*
*在你想要改变转速的地方修改CCR的值(只提供修改方式)
*/
//方法一(函数修改)
TIM_SetCompare1(TIM12, 0); //0不可修改超出ARR的值
//方法二 (寄存器修改)
TIM12->CCR1 = 0; //0不可修改超出ARR的值
输出比较结构体
TIM_OCInitTypeDef
用于输出比较模式,与
TIM_OCxInit
函数配合使用完成指定定时器输出通道初始化配置。
结构参数介绍(颜色标注的PWM模式用不到)
(1) TIM_OCMode
:比较输出模式选择,总共有八种,常用的为
PWM1/PWM2
。它设定
CCMRx
寄 存器OCxM[2:0]
位的值。
(2) TIM_OutputState
:比较输出使能,决定最终的输出比较信号
OCx
是否通过外部引脚输出。它 设定TIMx_CCER
寄存器
CCxE/CCxNE
位的值。
(3)
TIM_OutputNState:
比较互补输出使能,决定
OCx
的互补信号
OCxN
是否通过外部引脚输出。
它设定
CCER
寄存器
CCxNE
位的值。
(4) TIM_Pulse
:比较输出脉冲宽度,实际设定比较寄存器
CCR
的值,决定脉冲宽度。可设置范围 为0
至
65535
。
(5) TIM_OCPolarity
:比较输出极性,可选
OCx
为高电平有效或低电平有效。它决定着定时器通 道有效电平。它设定CCER
寄存器的
CCxP
位的值。
(6)
TIM_OCNPolarity
:比较互补输出极性,可选
OCxN
为高电平有效或低电平有效。它设定 TIMx_CCER 寄存器的
CCxNP
位的值。
(7)
TIM_OCIdleState
:空闲状态时通道输出电平设置,可选输出
1
或输出
0
,即在空闲状态 (BDTR_MOE 位为
0)
时,经过死区时间后定时器通道输出高电平或低电平。它设定
CR2
寄存 器的OISx
位的值。
(8)
TIM_OCNIdleState
:空闲状态时互补通道输出电平设置,可选输出
1
或输出
0
,即在空闲状态 (BDTR_MOE 位为
0)
时,经过死区时间后定时器互补通道输出高电平或低电平,设定值必须与 TIM_OCIdleState 相反。它设定是
CR2
寄存器的
OISxN
位的值。
分频系数:
84-1
arr
值:
2000-1
比较值:
800-1
可知:
输送给定时器
4
的时钟频率为:
APB1
时钟频率
*2/84=48*2/84=1Mhz
PWM
周期为:在
1Mhz
的时钟频率下。数
2000
个数
1/1Mhz*2000=2ms
占空比为:高电平时间
/PWM
周期
=
数
800
个数
/
数
2000
个数
=800/2000=40%
pwm
频率为:
1/pwm
周期
= 1/2ms=500Hz
输出比较模式和
PWM
模式的区别
输出比较模式和
PWM
模式都可以用来输出
PWM
波,在功能上两者有相同之处,对于一个定时器这两种方式都可以做到四路输出PWM
,每一路
PWM
占空比都可调,也有不 同之处,输出比较模式可以方便的调节每一路PWM
波的频率,可以输出四路频率不同,占空比不同的PWM。但是
PWM
模式如果想要调节
PWM
波的频率,那么就只能重新设置预分频系数或者自动重装载寄存器ARR
,并且输出的四路
PWM
频率必定一致。PWM模式是输出比较模式的子集。