使用STM32定时器实现精确输出指定脉冲个数

文章目录

  • 前言
  • 1、计数器中断方式
  • 原理:
  • 主要程序:
  • 2、定时器同步方式
  • 原理:
  • 主要程序:
  • 前言

    本例使用芯片为 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);
    }
    
    

    结果图:

    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32定时器实现精确输出指定脉冲个数

    发表评论