学习定时器输出比较模式产生PWM的一些感悟

(刚开始尝试写博客,如有错误或者不足之处欢迎指正)
我用的是通用定时器TIM3来产生的
输出比较模式产生PWM与直接配置定时器PWM模式相比有一些优势,最大的就是同一个定时器的不同通道可以产生频率不同的PWM。
个人理解:
其实PWM模式输出比较模式的一个特殊情况,即不去改变频率值,单改变比较值从而改变占空比。
在输出比较模式中,需要利用中断,不断改变比较值,即捕获/比较寄存器的值
在这里插入图片描述
如图所示,假设我预分频值取71即72分频,重装载值取最大0xffff,则CNT_Fre就是0xffff,频率的1M,在配置时,设置捕获/比较中断TIM_IT_CCx,每当进行一次比较时会进入一次中断,我们在中断服务函数里配置,每次获取计数器的值capture,当处于上升沿的位置时,我们把下次的比较值改为 capture+Duty,处于下降沿的位置时,把下次比较值设置为capture+CNT_fre-Duty,实际上在代码中只要设置一个标志位,每设置一次取反就好了,这样不断改变比较值我们就能产生我们想要的频率占空比的PWM波了。
附上自己配的代码:
代码中为了程序易读性改了取名
/*********Êä³ö±È½ÏPWM/
u16 CH3_Fre; //对应CNT_fre
u8 CH3_Duty; //对应Duty
u8 CH3_Flag=1;

//TIM3 CH3 PB0
//fre : ƵÂÊ£¨Ð¡ÓÚ60k£©
//duty : Õ¼¿Õ±È(°Ù·ÖÖÆ)
void PWMS_Initi(u16 fre,u8 duty)
{
u8 psc=72;
u16 arr=0xffff;

GPIO_InitTypeDef GPIO_InitStruct;
 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
 TIM_OCInitTypeDef TIM_OCInitStruct;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;   //¸´ÓÃÍÆÍêÊä³ö
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);

TIM_TimeBaseInitStruct.TIM_ClockDivision=0;		//²»·ÖƵ£¬Ê±ÖÓ·Ö¸î
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period=arr;		//ԤװÔØÖµ
TIM_TimeBaseInitStruct.TIM_Prescaler=(psc-1);   //Ô¤·ÖƵ
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);

NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn;  //ÖжϴóͨµÀ£¬ÔÚstm32f10x.hÖÐ
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);

//»»ËãƵÂÊ£¬Õ¼¿Õ±È¶ÔÓ¦µÄ¼ÆÊýÖµ
CH3_Fre=1000000/fre; //Fre=72M/72/0xffff, pulse=Fre0xffff/ch2_fre
CH3_Duty=CH3_Fre
duty/100;

TIM_OCInitStruct.TIM_OCMode=TIM_OCMode_Toggle;  //´¥·¢Ä£Ê½
TIM_OCInitStruct.TIM_OCPolarity=TIM_OCPolarity_Low;
TIM_OCInitStruct.TIM_OutputState=ENABLE;
TIM_OCInitStruct.TIM_Pulse=CH3_Fre;
TIM_OC3Init(TIM3,&TIM_OCInitStruct);

TIM_SetCounter(TIM3,0);   //Çå¿Õ¼ÆÊýÆ÷Öµ
TIM_SetCompare3(TIM3,0);	//ÉèÖóõʼ±È½ÏÖµ£¬¿É¿ØÖƳõʼÏàλ

TIM_ITConfig(TIM3,TIM_IT_CC2,ENABLE);  //ʹÄÜ´óÖжÏϾßÌåµÄÖжÏͨµÀ
TIM_Cmd(TIM3,ENABLE);		//ʹÄܶ¨Ê±Æ÷

}

void TIM3_IRQHandler() //ÖжϷþÎñº¯Êý
{
u16 capture;
if(TIM_GetITStatus(TIM3,TIM_IT_CC3))
{
TIM_ClearITPendingBit(TIM3,TIM_IT_CC3);
capture=TIM_GetCapture3(TIM3); //»ñÈ¡¼ÆÊýÆ÷Öµ
if(CH3_Flag) //±ê־λÓÃÓÚÇø·ÖÊä³ö¸ßµçƽʱ¼äºÍÊä³öµÍµçƽʱ¼ä
{
TIM_SetCompare3(TIM3,capture+CH3_Duty); //СÓÚDutyʱÊä³ö¸ßµçƽ
}
else
{
TIM_SetCompare3(TIM3,capture+CH3_Fre-CH3_Duty); //ÖÜÆÚÄÚ´óÓÚDutyµÄʱ¼äÊä³öµÍµçƽ
}
CH3_Flag^=1; //Óë1Òì»ò¼´È¡·´
}

}

//º¯ÊýÖиıäͨµÀ3Êä³öƵÂÊÕ¼¿Õ±È
void Setnew_FreDuty(u16 newfre,u8 newduty)
{
CH3_Fre=1000000/newfre; //Fre=72M/72/0xffff, pulse=Fre0xffff/ch2_fre
CH3_Duty=CH3_Fre
newduty/100;

}

猜你喜欢

转载自blog.csdn.net/dbfy666/article/details/86644164