STM32用OCToggle模式产生单脉冲

平台:KEIL5+stm32f103。
功能:采用TIM3的1,2通道的比较翻转模式产生宽度可调的单脉冲(本例的脉冲宽度200us/100us),脉冲之间间隔1s。
目前网上流传较多的方案一般2种:第一种:外部IO做触发源,定时器接收后产生脉宽;第二种:用定时器的主从或门控模式,用一个定时器驱动另外一个定时器。这两种方案要么需要外部IO,要么需要2个通用或高级的定时器,占用资源相对较多。本方案使用一个高级活通用定时器+系统滴答。系统滴答做这一件事同时还可以执行其他计时任务,总的来说,占用资源相对较少。

#define TIMER3_OCTOGGLE_FREQUENCY (uint32_t)1000000 //MHz,OCToggle模式下计时时钟//翻转频率 = TIMER3_OCTOGGLE_FREQUENCY/Timer3_PWM_CCR1_Val uint16_t Timer3_PWM_CCR1_Val = 100; //翻转频率 = 方波频率*2 uint16_t Timer3_PWM_CCR2_Val = 50; void TIMER3_OCToggleMode_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_TimeBaseInitTypeDefTIM_TimeBaseStructure; TIM_OCInitTypeDefTIM_OCInitStructure; uint16_t Timer3_PWM__PrescalerValue = https://www.it610.com/article/0; /* PCLK1 = HCLK/4 */ RCC_PCLK1Config(RCC_HCLK_Div4); /* TIM3 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); /* GPIOA clock enable */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); /* GPIOA Configuration:TIM3 Channel1, 2 as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Enable the TIM3 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); Timer3_PWM__PrescalerValue = (uint16_t) (SystemCoreClock / TIMER3_OCTOGGLE_FREQUENCY) - 1; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = Timer3_PWM__PrescalerValue; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* Output Compare Toggle Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = Timer3_PWM_CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Disable); /* Output Compare Toggle Mode configuration: Channel2 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = Timer3_PWM_CCR2_Val; TIM_OC2Init(TIM3, &TIM_OCInitStructure); TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Disable); /* TIM enable counter */ TIM_Cmd(TIM3, ENABLE); /* TIM IT enable */ TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2, ENABLE); }

uint8_t ch0cnt = 0; //通道1翻转的次数 uint8_t ch1cnt = 0; //通道2翻转的次数u32 G_SystemTickTime; //滴答系统时钟变量 u32 G_SecondTimeCnt; //秒计时void TIM3_IRQHandler(void) { #if 1 /* TIM3_CH1 toggling with frequency =Hz */ if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 ); capture = TIM_GetCapture1(TIM3); TIM_SetCompare1(TIM3, capture + Timer3_CCR1_Val); ch0cnt++; if (ch0cnt > 0)//setpulsenumber { TIM_CCxCmd(TIM3,TIM_Channel_1,TIM_CCx_Disable); TTIM_ITConfig(TIM3, TIM_IT_CC1, DISABLE); }}/* TIM3_CH2 toggling with frequency =Hz */ if (TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_CC2); capture = TIM_GetCapture2(TIM3); TIM_SetCompare2(TIM3, capture + Timer3_CCR2_Val); ch1cnt++; if (ch1cnt > 0)//setpulsenumber { TIM_CCxCmd(TIM3,TIM_Channel_2,TIM_CCx_Disable); TIM_ITConfig(TIM3, TIM_IT_CC2, DISABLE); } }#endif }




void SysTick_Handler(void) { uint16_t tmp; //记录当前计数值 G_SystemTickTime++; if (G_SystemTickTime == 1000)//每1s执行一次 { G_SecondTimeCnt++; tmp = TIM_GetCounter(TIM3); //必须读此值,否则脉冲宽度不是固定值 TIM_SetCompare1(TIM3, tmp + Timer3_CCR1_Val); //调整CCR1_Val可以改变脉宽 TIM_SetCompare2(TIM3, tmp + Timer3_CCR2_Val); //重新打开该通道 TIM_ClearITPendingBit(TIM3, TIM_IT_CC1 ); TIM_ClearITPendingBit(TIM3, TIM_IT_CC2 ); TIM_CCxCmd(TIM3,TIM_Channel_1,TIM_CCx_Enable); TIM_CCxCmd(TIM3,TIM_Channel_2,TIM_CCx_Enable); TTIM_ITConfig(TIM3, TIM_IT_CC1, ENABLE); TTIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE); ch0cnt = 0; ch1cnt = 0; G_SystemTickTime = 0; } }

keil仿真结果:绿色的是通道1,红色的通道2。
STM32用OCToggle模式产生单脉冲
文章图片


【STM32用OCToggle模式产生单脉冲】STM32用OCToggle模式产生单脉冲
文章图片

    推荐阅读