PWM原理简介
脉冲宽度调制(PWM),是英文“Pulse Width Modulation” 的缩写,简称脉宽调制,是利用
微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽
度的控制,脉宽调制也叫占空比
这个图中阐述了利用高级定时器产生PWM的原理,其中
- ARR是自动重装载寄存器(TIMx_ARR)的值
- CNT是定时器计数器当前的值
- CCRx是捕获/比较寄存器 x(TIMx_CCRx)的值
每经过一次定时器时钟周期就会+1,通过设置定时器的输出模式,可以实现,当计数器的值CNT,小于设定的CCRx的值时,输出低电平,大于时就输出高电平
PWM波的占空比和周期
可以通过改变CCRx的值来改变占空比,改变ARR的值来改变周期
- CCRx 》占空比
- ARR 》周期,也就是溢出时间
计算公式为:Tout= ((arr+1)*(psc+1))/Tclk;
Tclk为时钟周期,psc为时钟分频因子
PWM波形时间计算
向上计数时,如果此时设置的模式为当计数器的值小于CCRx的值时,输出高电平,也是PWM1模式(可以通过TIMx_CCMR1的OCxM位来配置PWM模式)
- 假设psc分频设置成71,arr的值设置成4999,由公式
Tout= ((arr+1)*(psc+1))/Tclk
得Tout=5ms - 这时候我们又能知道计数器每一次计数的时间为1us
(相当于把公式Tout= ((arr+1)*(psc+1))/Tclk里的arr的值取0所算出来的时间) - 如果要使PWM输出高电平的时间为2.5ms的话,经过计算这时候CCRx的值就要设置成2500
PWM程序
编程步骤:
代码:
#include "stm32f10x.h"
#include "bsp_systick.h"
void TIM8_PWM_Config(uint16_t Arr, uint16_t Psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE); //使能TIM8的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //使能 GPIO 的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//配置GPIO
//设置该引脚为复用输出功能,输出 TIM8 CH1 的 PWM 脉冲波形
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//初始化TIM8
TIM_TimeBaseStructure.TIM_Period = Arr; //设置自动重装载的值
TIM_TimeBaseStructure.TIM_Prescaler = Psc; //设置预分频系数
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置向上计数(累加)计数模式
//至此,定时器就能正常工作了,此时的溢出时间也就是周期为:Tout= ((arr+1)*(psc+1))/Tclk 这里的Tclk为72MHz
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟的分频因子,仅对电路的稳定性有影响
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseStructure); //初始化TIM8
//初始化 TIM8 Channel2 PWM 模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; // 选择PWM模式2,
/*在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为
有效电平;在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,
否则为无效电平。*/
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //设置极性,输出有效电平为:高电平
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //输出使能
TIM_OC1Init(TIM8, &TIM_OCInitStructure); //初始化外设 TIM8 OC1
TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable); //使能预装载寄存器
TIM_Cmd(TIM8, ENABLE); //使能 TIM8
TIM_CtrlPWMOutputs(TIM8, ENABLE); //主输出使能,当使用的是通用定时器时,这句不需要
}
int main(void)
{
uint16_t val=0;//必须16位
uint8_t dir=1;
TIM8_PWM_Config(999,71);
while (1)
{
delay_ms(10);
if(dir)
val++;
else
val--;
if(val>399)
dir=0;
if(val<=0)
dir=1;
TIM_SetCompare1(TIM8,val);//设置的是CCRx的值,也就是设置占空比
}
}