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模式产生单脉冲】
文章图片
推荐阅读
- Docker应用:容器间通信与Mariadb数据库主从复制
- JS中的各种宽高度定义及其应用
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- 涉毒患者(新诗)
- 参保人员因患病来不及到指定的医疗机构就医,能否报销医疗费用()
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。