STM32定时器同步功能3:前面有篇博客讲到了将一个定时器用作另一个定时器的预分频器的功能,现用这个功能实现生成指定个数的PWM方波个数功能。
本例中主定时为TIM3,从定时器为TIM2,TIM3配置为PWM输出,并且使能主从模式,并将更新事件输出给从机TIM2,从机TIM2检测到触发信号后进行计数,计数到指定值CNT后,产生更新中断。
这个CNT值就是TIM3输出的PWM脉冲数,使用这种脉冲计数方式可以避免频繁中断产生,并且可以精确计算脉冲数。
PWM输出频率= TIM3时钟线频率/TIM3预分频系数/TIM3装载值=32MHz/31/1000=1KHz
TIM2更新中断频率=PWM输出频率/TIM2预分频系数/TIM2装载值=1KHz/1/5=200Hz
本例代码如下:
/**
* 说明 : 主定时器初始化,用来控制从定时器
* 参数 : 无
* 返回 : 无
*/
void Master_Timer_Init(void)
{
LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/** PWM_OUT->PC8 */
GPIO_InitStruct.Pin=LL_GPIO_PIN_8;
GPIO_InitStruct.Mode=LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed=LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull=LL_GPIO_PULL_UP;
GPIO_InitStruct.Alternate=LL_GPIO_AF_2;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/** 定时器时基配置:输出PWM频率为1KHz */
LL_TIM_SetPrescaler(TIM3, 31);
LL_TIM_SetAutoReload(TIM3, 999);
LL_TIM_SetCounterMode(TIM3, LL_TIM_COUNTERMODE_UP);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3,LL_TIM_TRGO_UPDATE); /** 触发源输出:更新事件作为触发源 */
LL_TIM_EnableMasterSlaveMode(TIM3); /** 使能主从模式 */
/** 输出模式配置 */
TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1;
TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE;
TIM_OC_InitStruct.CompareValue = 500; /** 占空比50% */
TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_LOW;
LL_TIM_OC_Init(TIM3, LL_TIM_CHANNEL_CH3, &TIM_OC_InitStruct);
/** 使能通道输出 */
LL_TIM_CC_EnableChannel(TIM3, LL_TIM_CHANNEL_CH3);
/** 使能TIM3 */
LL_TIM_EnableCounter(TIM3);
}
/**
* 说明 : 从定时器
* 参数 : 无
* 返回 : 无
*/
void Slave_Timer_Init(void)
{
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
/** 定时器时基配置 :频率为200Hz */
LL_TIM_SetPrescaler(TIM2, 0);
LL_TIM_SetAutoReload(TIM2, 5);
LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP);
LL_TIM_EnableARRPreload(TIM2);
/** 选择时钟源 */
LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_EXT_MODE1);
/** 和主机TIM3绑定 */
LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_ITR2);
/** 配置中断 */
LL_TIM_EnableIT_UPDATE(TIM2);
NVIC_EnableIRQ(TIM2_IRQn);
NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 1, 0));
/** 使能TIM2 */
LL_TIM_EnableCounter(TIM2);
}
/**
* 说明 : 定时器2中断服务函数
* 参数 : 无
* 返回 : 无
*/
void TIM2_IRQHandler(void)
{
if(LL_TIM_IsActiveFlag_CC1(TIM2) != RESET)
{
LL_TIM_ClearFlag_CC1(TIM2);
}
if(LL_TIM_IsActiveFlag_TRIG(TIM2) != RESET)
{
LL_TIM_ClearFlag_TRIG(TIM2);
}
if(LL_TIM_IsActiveFlag_UPDATE(TIM2) != RESET)
{
LL_TIM_ClearFlag_UPDATE(TIM2);
PB6_Toggle(); /** 通过此引脚测量频率,实际频率为示波器看到的2倍 */
}
}
测试结果如下:
从测试结果可以看出符合预期设置