#每日话题# #技术资源#
目前我们有两种方式来实现定时器输出指定数量的脉冲
方法1:定时器级联
方法2:高级定时器
接下来给大家简单讲一下两种方式具体的实现原理
定时器级联:这里我们用到的是TIM2和TIM3,是两个通用定时器;然后我们TIM2从模式配置为外部时钟模式1,触发源选择TIM3,即利用TIM3来驱动TIM2,TIM3每更新一次,TIM2计数器+1,所以TIM3输出PWM的个数 = TIM2的计数值,这里如果我们选择输出10个PWM,就需要配置TIM2_ARR = 10-1,然后使能TIM2的更新中断,当TIM3输出指定数量的PWM之后,进入TIM2更新中断,在中断中关闭TIM3,停止PWM输出。
void TIM3_Master_Config(void)
{
GPIO_InitType GPIO_InitStructure;
TIM_TimeBaseInitType TIM_TimeBaseStructure;
OCInitType TIM_OCInitStructure;
/** RCC Config */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);
/** GPIO Config */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_6 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM3;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
/** Time Base Config */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 1000 - 1;
TIM_TimeBaseStructure.Prescaler = 108 - 1;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure);
/** PWM Config */
TIM_InitOcStruct(&TIM_OCInitStructure);
TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM2;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = 500;
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_LOW;
TIM_InitOc1(TIM3, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
TIM_ConfigArPreload(TIM3, ENABLE);
TIM_SelectOutputTrig(TIM3, TIM_TRGO_SRC_OC1REF); // 选择OC1REF作为主定时器的TRGO信号
}
void TIM2_Slave_Config(uint32_t countpluse)
{
NVIC_InitType NVIC_InitStructure;
TIM_TimeBaseInitType TIM_TimeBaseStructure;
/** RCC Config */
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);
/** NVIC Config */
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/** Time Base Config */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = (countpluse - 1);
TIM_TimeBaseStructure.Prescaler = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);
TIM_SelectInputTrig(TIM2, TIM_TRIG_SEL_IN_TR2);
TIM_SelectSlaveMode(TIM2, TIM_SLAVE_MODE_EXT1);
TIM_ConfigInt(TIM2, TIM_INT_UPDATE, DISABLE);
TIM_ClearFlag(TIM2, TIM_FLAG_UPDATE);
TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);
TIM_Enable(TIM2, ENABLE);
}
TIM_Enable(TIM3, ENABLE);
void TIM2_IRQHandler(void)
{
if(TIM_GetIntStatus(TIM2, TIM_INT_UPDATE) != RESET)
{
TIM_Enable(TIM3, DISABLE);
TIM_ConfigInt(TIM2, TIM_INT_UPDATE, DISABLE);
TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);
}
}
然后我们来看一下TIM3输出的PWM波形:
其实定时器级联还有一种配置也可以达到这种效果,我们主定时器TIM3选择更新事件触发,TIM2从模式选择门控模式;
接下来讲一下第二种实现方式,高级定时器
高级定时器:N32高级定时器独有一个重复计数器的模块,每次计数器更新都会让重复计数器-1,当重复计数器=0时,触发更新事件,在更新中断中关闭定时器,停止PWM输出。
void TIM1_PWM_Config(uint8_t num)
{
GPIO_InitType GPIO_InitStructure;
NVIC_InitType NVIC_InitStructure;
TIM_TimeBaseInitType TIM_TimeBaseStructure;
OCInitType TIM_OCInitStructure;
/** RCC Config */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOA, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE);
TIM_EnableCtrlPwmOutputs(TIM1, ENABLE);
/** GPIO Config */
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM1;
GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
/** NVIC Config */
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/** Time Base Config */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Period = 1000 - 1;
TIM_TimeBaseStructure.Prescaler = 108 - 1;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_TimeBaseStructure.ClkDiv = TIM_CLK_DIV1;
TIM_TimeBaseStructure.RepetCnt = (num - 1);
TIM_InitTimeBase(TIM1, &TIM_TimeBaseStructure);
/** PWM Config */
TIM_InitOcStruct(&TIM_OCInitStructure);
TIM_OCInitStructure.OcMode = TIM_OCMODE_PWM1;
TIM_OCInitStructure.OutputState = TIM_OUTPUT_STATE_ENABLE;
TIM_OCInitStructure.Pulse = 500;
TIM_OCInitStructure.OcPolarity = TIM_OC_POLARITY_LOW;
TIM_OCInitStructure.OcIdleState = TIM_OC_IDLE_STATE_SET;
TIM_InitOc1(TIM1, &TIM_OCInitStructure);
TIM_ConfigOc1Preload(TIM1, TIM_OC_PRE_LOAD_ENABLE);
TIM_ConfigArPreload(TIM1, ENABLE);
TIM_ConfigInt(TIM1, TIM_INT_UPDATE, DISABLE);
TIM_ClearFlag(TIM1, TIM_FLAG_UPDATE);
TIM_ConfigInt(TIM1, TIM_INT_UPDATE, ENABLE);
TIM_Enable(TIM1, ENABLE);
}
void TIM1_UP_IRQHandler(void)
{
if(TIM_GetIntStatus(TIM1, TIM_INT_UPDATE) != RESET)
{
TIM_Enable(TIM1, DISABLE);
TIM_ConfigInt(TIM1, TIM_INT_UPDATE, DISABLE);
TIM_ClrIntPendingBit(TIM1, TIM_INT_UPDATE);
}
}
输出PWM波形展示:
|