一、什么是PWM
脉宽调制
PWM就是脉冲宽度调制,通过调节占空比就可以调节脉冲宽度。
周期:T=1/f,T是周期,f是频率。
如果频率为50Hz ,也就是说一个周期是20ms,那么一秒钟就有 50次PWM周期。
占空比:脉宽时间/周期。
PWM原理
PWM就是在一定的频率下,通过不同的占空比即可得到不同大小的输出模拟电压,PWM就是通过这种原理实现数字模拟信号转换的。
可以实现
呼吸灯的设置
对电机转速的控制
对舵机的控制,控制多级不同的转角
二、输出比较框图
具体请看数据手册
三、工作过程
CCR1:捕获比较(值)寄存器(x=1,2,3,4):设置比较值。
CCMR1: OC1M[2:0]位:
对于PWM方式下,用于设置PWM模式1【110】或者PWM模式2【111】
CCER:CC1P位:输入/捕获1输出极性。0:有效电平为高电平,1:有效电平为低电平。
CCER:CC1E位:输入/捕获1输出使能。0:关闭,1:打开。
注释:详细信息查寄存器手册
//--------------------------------------
代码:TIM_OC1Init()函数配置
TIM_OCInitTypeDef TIMOCInitDef;
TIMOCInitDef.TIM_OCMode=TIM_OCMode_PWM1; //输出模式为1
TIMOCInitDef.TIM_OutputState=TIM_OutputState_Enable; //使能输出
TIMOCInitDef.TIM_Pulse=0; //CCR寄存器的值,后面会改变
TIMOCInitDef.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OC1Init(TIM1,&TIMOCInitDef);
如果是高级定时器
则还需要配置:刹车和死区寄存器( TIMx_BDTR)。
该寄存器,我们只需要关注最高位: MOE 位,要想高级定时器的 PWM 正常输出,则必须设置 MOE 位为 1,否则不会有输出。注意:通用定时器不需要配置这个。
五、配置
引脚对应的定时器与通道
在芯片手册中查找
配置流程
1. 使能定时器和相关IO口时钟:RCC_APB2PeriphClockCmd();
2. 初始化IO口为复用功能输出。函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
3. 初始化定时器:ARR,PSC等:TIM_TimeBaseInit();
4. 初始化输出比较参数:TIM_OC1Init();
5. 使能预装载寄存器: TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
6. 使能定时器。TIM_Cmd();
7. 不断改变比较值CCRx,达到不同的占空比效果:TIM_SetCompare1();
9. 注释:TIM_CtrlPWMOutputs(TIM1, ENABLE); //高级定时器才有 必须打开
六、PWM实现呼吸灯
void pwm_init(void)
{
GPIO_InitTypeDef GPIOInitDef;
//------------------------------------开始,配置GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //开启时钟
GPIOInitDef.GPIO_Pin=GPIO_Pin_8;
GPIOInitDef.GPIO_Speed=GPIO_Speed_50MHz;
GPIOInitDef.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIOInitDef);
// -------------------------------------配置定时器
TIM_TimeBaseInitTypeDef TIMBaseIniteDef;
TIMBaseIniteDef.TIM_ClockDivision=TIM_CKD_DIV1; //时钟选择,一般选1
TIMBaseIniteDef.TIM_CounterMode=TIM_CounterMode_Up; //计数方式
TIMBaseIniteDef.TIM_Period= 399; //ARR寄存器,每500um一个周期
TIMBaseIniteDef.TIM_Prescaler=89; //PSC寄存器,分频,分频后得到频率
//TIMBaseIniteDef.TIM_RepetitionCounter= //重复计数,用在高级定时器上面,如果配置为2,则第二次出现中断源时触发
TIM_TimeBaseInit(TIM1,&TIMBaseIniteDef);
//--------------------------------------初始化输出比较参数
TIM_OCInitTypeDef TIMOCInitDef;
TIMOCInitDef.TIM_OCMode=TIM_OCMode_PWM2; //输出模式为1
TIMOCInitDef.TIM_OutputState=TIM_OutputState_Enable; //是能输出
TIMOCInitDef.TIM_Pulse=0; //CRR寄存器的值,后面会改变
TIMOCInitDef.TIM_OCPolarity=TIM_OCPolarity_High;
TIM_OC1Init(TIM1,&TIMOCInitDef);
//--------------------------------------使能预装载通道寄存器
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);
//--------------------------------------使能ARR预重装载通道寄存器
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_CtrlPWMOutputs(TIM1,ENABLE); //高级定时器需要有,通用定时器不需要
TIM_Cmd(TIM1,ENABLE);//使能定时器1
}
void led_pwm(void)
{
int i;
for(i=1;i<400;i++)
{
TIM_SetCompare1(TIM1,i);
delay_ms(2);
}
for(i=400;i>1;i--)
{
TIM_SetCompare1(TIM1,i);
delay_ms(2);
}
}