输出比较模式实现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=Fre*0xffff/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=Fre*0xffff/ch2_fre
	CH3_Duty=CH3_Fre*newduty/100;


}

 

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值