stm32定时器方式精确输出指定脉冲个数

前言

本例使用芯片为 STM32f407zg
使用标准库编程

输出指定脉冲个数的PWM方法主要有两种:计数器中断方式和定时器同步方式。
项目输出可控双脉冲pwm波形,可根据需要控制输出脉冲个数,查阅网上资料大部分为HAL库配置,自己实际第一次编程有些一头雾水,后查阅官方帮助手册和参考手册,配置出项目,故在此纪录。

1、计数器中断方式

原理:

程序定义两个定时器,定时器1负责计数,开启定时器1比较中断和溢出更新中断,在达到给定的比较值时产生中断,进入中断开启定时器2输出PWM波(设置占空比),在达到溢出值时产生更新中断,停止定时器2的PWM输出(占空比0),从而达到稳定输出脉冲个数。结果如图
在这里插入图片描述

主要程序:

定时器1:

 TIM_TimeBaseInitTypeDef  TIM_TimeStructure;
    TIM_OCInitTypeDef   TIM_OCStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //选择优先级分组2。
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    //引脚复用
   GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_TIM10);
   GPIO_Init(GPIOF,&GPIO_InitStructure); 

    //时基单元
    RCC_APB2PeriphClockCmd(Major_TIM_CLK,ENABLE);
    TIM_TimeStructure.TIM_Period = TIM_Time-1;
    TIM_TimeStructure.TIM_Prescaler = Major_TIM_Prescaler;
    TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM10,&TIM_TimeStructure);


    //占空比设置
    TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
    TIM_OCStructure.TIM_Pulse = TIM_duty*TIM_Time;
    TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM10, &TIM_OCStructure); 

    TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);//使能预装载值处理器
    TIM_ARRPreloadConfig(TIM10, ENABLE);//使能ARPE位
    TIM_ClearFlag(TIM10, TIM_FLAG_Update);//清除中断标志位 
    TIM_ITConfig(TIM10,TIM_FLAG_Update,ENABLE); //开启中断
    TIM_ITConfig(TIM10,TIM_FLAG_CC1,ENABLE);
    
    TIM_Cmd(TIM10,ENABLE);

以定时器10为计数器,在比较值和更新值分别进入中断,比较值中断负责开启定时器2PWM,更新值中断负责关闭。

定时器2:

    TIM_TimeBaseInitTypeDef  TIM_TimeStructure;
    TIM_OCInitTypeDef   TIM_OCStructure;
    GPIO_InitTypeDef  GPIO_InitStructure;    //定义IO口模式,并初始化IO口
    
    RCC_APB2PeriphClockCmd(Main_TIM_CLK,ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM9);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    TIM_TimeStructure.TIM_Period = Main_Time-1;
    TIM_TimeStructure.TIM_Prescaler = Main_TIM_Prescaler;
    TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM9,&TIM_TimeStructure);

    TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCStructure.TIM_Pulse = Main_Time*0.5;
    //TIM_OCStructure.TIM_Pulse = 100;
    TIM_OC1Init(TIM9,&TIM_OCStructure); 
  
    TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);//使能预装载值处理器
    TIM_ARRPreloadConfig(TIM9, ENABLE);//使能ARPE位

    TIM_Cmd(TIM9,ENABLE);

中断服务函数:

void TIM1_UP_TIM10_IRQHandler(void)  
{
    if(TIM_GetITStatus(TIM10,TIM_FLAG_Update)!=RESET)
    {
        TIM_ClearITPendingBit(TIM10, TIM_FLAG_Update); //清除中断标志位
        TIM_SetCompare1(TIM9,50);
    }
    if (TIM_GetITStatus(TIM10, TIM_FLAG_CC1)!=RESET)
    {
        TIM_ClearITPendingBit(TIM10, TIM_FLAG_CC1); 
      TIM_SetCompare1(TIM9,0);
    }
        
} 

2、定时器同步方式

原理:

stm32定时器从内部就连接到一起,可以查询芯片参考手册获取主从定时器分配信息。如图查询结果:
在这里插入图片描述
本例中设置TIM9为从定时器,TIM10为主定时器,采用门控方式输出
因此设置TIM9为ITR2模式,TIM_SlaveMode_Gated门控
通过定时器 10 的输出比较来使能定时器 9。 仅当定时器 10的 OC1REF 为高电平时,定时器 9 才根据分频后的内部时钟进行计数。
如图所示:
在这里插入图片描述
在这里插入图片描述
其中第一中为复位,第二中为门控,这两种较为常用

主要程序:

主定时器:

static void TIM10_TimeConfig(u16 TIM_Time,double TIM_duty)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeStructure;
    TIM_OCInitTypeDef   TIM_OCStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    //引脚复用
   GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_TIM10);
   GPIO_Init(GPIOF,&GPIO_InitStructure); 

    //时基单元
    RCC_APB2PeriphClockCmd(Major_TIM_CLK,ENABLE);
    TIM_TimeStructure.TIM_Period = TIM_Time-1;
    TIM_TimeStructure.TIM_Prescaler = Major_TIM_Prescaler;
    TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM10,&TIM_TimeStructure);


    //占空比设置
    TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM2;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
    TIM_OCStructure.TIM_Pulse = TIM_duty*TIM_Time;
    TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OC1Init(TIM10, &TIM_OCStructure); 

    TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);//使能预装载值处理器
    TIM_ARRPreloadConfig(TIM10, ENABLE);//使能ARPE位
    TIM_ITConfig(TIM10,TIM_FLAG_CC1,ENABLE);

    //定时器主模式设置
    TIM_SelectMasterSlaveMode(TIM10, TIM_MasterSlaveMode_Enable);//开启 Master/Slave 模式 
    TIM_SelectOutputTrigger(TIM10,TIM_TRGOSource_Update);

    TIM_Cmd(TIM10,ENABLE);
    
}

从定时器:

static void TIM9_TimeConfig(u16 Main_Time)
{
    //时基单元
    TIM_TimeBaseInitTypeDef  TIM_TimeStructure;
    TIM_OCInitTypeDef   TIM_OCStructure;
    GPIO_InitTypeDef  GPIO_InitStructure;    //定义IO口模式,并初始化IO口
    RCC_APB2PeriphClockCmd(Main_TIM_CLK,ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM9);
   

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStructure);

    TIM_TimeStructure.TIM_Period = Main_Time-1;
    TIM_TimeStructure.TIM_Prescaler = Main_TIM_Prescaler;
    TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM9,&TIM_TimeStructure);

    TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
    TIM_OCStructure.TIM_Pulse = Main_Time*0.5;
    //TIM_OCStructure.TIM_Pulse = 100;
    TIM_OC1Init(TIM9,&TIM_OCStructure); 

    //定时器从模式设置
    TIM_SelectSlaveMode(TIM9, TIM_SlaveMode_Gated);//允许Slave 模式
    TIM_SelectInputTrigger(TIM9, TIM_TS_ITR2);

    TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);//使能预装载值处理器
    TIM_ARRPreloadConfig(TIM9, ENABLE);//使能ARPE位

    TIM_Cmd(TIM9,ENABLE);
}

结果图:在这里插入图片描述

  • 10
    点赞
  • 77
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值