本帖最后由 黑皮男 于 2018-3-27 20:57 编辑
产生两种交替的高频pwm,最佳的组合就是使用主从定时器模式。一个定时器做主,用来产生pwm,另一个从定时器对主定时器进行计数,当产生足够数量的脉冲后,在从定时器的中断中更改主定时器的ARR和CCR的值,来更改定时器的pwm频率。但是当频率很高的时候,两种频率进行切换的时候,中间由于代码的延时,切换处的脉冲信号会有误差,不会和两种频率PWM的周期相同,这个对我的应用是能够满足的。目前测的2M以下的频率计数比较准确。下面是部分代码实现,只做原理说明,代码无法拿来直接用,需要一些其他相关配置,平台是nucleo-f303,主定时器是TIM2,从定时器是TIM15。请见谅,没有准备图
主要步骤:
1、主定时器初始化,设置好初始pwm频率
2、从定时器初始化,连接到主定时器
3、启动定时器
4、从定时器计数符合要求脉冲数,产生中断,切换主定时器的pwm频率
主定时器初始化
- LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL);
- LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1);
-
- LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_UPDATE);//主定时器主模式,更新事件产生触发信号到从定时器
-
- LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
-
- LL_TIM_SetPrescaler(TIM2, SLOW_FREQ_PRESCALER);
-
- LL_TIM_EnableARRPreload(TIM2);
-
- LL_TIM_SetAutoReload(TIM2, SLOW_FREQ_RELOAD);
- LL_TIM_OC_SetMode(TIM2, PWM_CHANNEL, LL_TIM_OCMODE_PWM2);
-
- LL_TIM_OC_SetPolarity(TIM2, PWM_CHANNEL, LL_TIM_OCPOLARITY_HIGH);
-
- LL_TIM_OC_SetCompareCH2(TIM2, SLOW_FREQ_PULSE);
-
- LL_TIM_OC_EnablePreload(TIM2, PWM_CHANNEL);
-
- LL_TIM_CC_EnableChannel(TIM2, PWM_CHANNEL);
-
- LL_TIM_GenerateEvent_UPDATE(TIM2);
-
- LL_TIM_DisableCounter(TIM2);
复制代码 从定时器初始化- NVIC_SetPriority(TIM15_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),10, 0));
- NVIC_EnableIRQ(TIM15_IRQn);
- //从模式,连接到TIM2
- LL_TIM_SetClockSource(TIM15,LL_TIM_CLOCKSOURCE_EXT_MODE1);
- LL_TIM_EnableMasterSlaveMode(TIM15);
- LL_TIM_SetTriggerInput(TIM15, LL_TIM_TS_ITR0);
-
- LL_TIM_SetClockDivision(TIM15, LL_TIM_CLOCKDIVISION_DIV1);
- LL_TIM_SetCounterMode(TIM15, LL_TIM_COUNTERMODE_UP);
- LL_TIM_SetPrescaler(TIM15, 0);
- LL_TIM_SetAutoReload(TIM15, SLOW_PULSE_NUM);//第一组脉冲的数量
- LL_TIM_SetOnePulseMode(TIM15, LL_TIM_ONEPULSEMODE_SINGLE);
- LL_TIM_GenerateEvent_UPDATE(TIM15);
- LL_TIM_DisableCounter(TIM15);
- LL_TIM_ClearFlag_UPDATE(TIM15);
- LL_TIM_EnableIT_UPDATE(TIM15);
复制代码
从定时器中断函数- void TIM1_BRK_TIM15_IRQHandler(void)
- {
- if(LL_TIM_IsActiveFlag_UPDATE(TIM15))
- {
- LL_TIM_ClearFlag_UPDATE(TIM15);
- LL_TIM_OC_SetMode(TIM2, PWM_CHANNEL, LL_TIM_OCMODE_FORCED_INACTIVE);
- LL_TIM_DisableCounter(TIM2);
- LL_TIM_SetAutoReload(TIM2, HIGH_FREQ_RELOAD);
- LL_TIM_OC_SetCompareCH2(TIM2, HIGH_FREQ_PULSE);
- LL_TIM_SetCounter(TIM2, 0);
- LL_TIM_EnableCounter(TIM2);
- LL_TIM_OC_SetMode(TIM2, PWM_CHANNEL, LL_TIM_OCMODE_PWM2);
- }
- }
复制代码
启动定时器
- LL_TIM_EnableCounter(TIM15);
- LL_TIM_EnableCounter(TIM2);
- LL_TIM_OC_SetMode(TIM2, PWM_CHANNEL, LL_TIM_OCMODE_PWM2);
复制代码
|