• 基于STM32F429+HAL库编写的定时器主从门控模式级联输出固定个数PWM脉冲的程序


    硬件设备

      42步进电机,步进电机驱动器,正点原子F429开发板

    开发软件

       keil5,Cube

    综述

      一般要精准的控制电机,就要控制单片机的引脚输出指定个数的PWM波,有多种可实现的方法,其中最好用的方法是用定时器级联输出固定个数PWM脉冲,虽然多用了一个定时器,但大大减少了CPU的处理资源。STM32的每个定时器可以通过另外一个定时器的某一个条件被触发而启动.这里所谓某一个条件可以是定时到时、定时器超时、比较成功等许多条件.这种通过一个定时器触发另一个定时器的工作方式称为定时器的同步,发出触发信号的定时器工作于主模式,接受触发信号而启动的定时器工作于从模式。

    Cube配置定时器,主定时器为PWM输出,从定时器为门控模式

    1.主定时器为TIM3,其中通道1配置为PWM输出,主模式的更新事件选为触发输入

      

    Cube的配置为参考,一切以代码为准

    void MX_TIM3_Init(void)
    {
      TIM_ClockConfigTypeDef sClockSourceConfig;
      TIM_MasterConfigTypeDef sMasterConfig = {0};
      TIM_OC_InitTypeDef          sConfigOC = {0};
    
    
        
      htim3.Instance = TIM3;                                //设置主定时器为TIM3
      htim3.Init.Prescaler = 4-1;                           //设置PWM频率
      htim3.Init.CounterMode = TIM_COUNTERMODE_UP;          //设置计数模式为向上计数
      htim3.Init.Period = 100-1;                            //设置占空比
      htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;    //设置为无分频
      if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
      {
        Error_Handler();
      }
     
        
      sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;              //更新事件被选为触发输入
      sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;       //开启主从模式
      if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
      {
        Error_Handler();
      }
        
      sConfigOC.OCMode = TIM_OCMODE_PWM1;            //设置PWM模式为PWM1
      sConfigOC.Pulse = 50;                          //设置PWM占空比为50%(50/100)
      sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;     //设置PWM空闲状态引脚拉低
      if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
      {
        Error_Handler();
      }    
    
      HAL_TIM_MspPostInit(&htim3);                    //设置PA6复用为PWM输出引脚
      HAL_TIM_Base_Stop(&htim3);
    }

     2.从定时器为TIM4,选为门控模式——触发输入

     

    从为TIM4,主为TIM3,根据下图,所以从模式的触发时钟为ITR2

     

     

    void MX_TIM4_Init(void)
    {
      TIM_ClockConfigTypeDef sClockSourceConfig = {0};
      TIM_SlaveConfigTypeDef sSlaveConfig = {0};
    
      htim4.Instance = TIM4;                                   //设置从定时器为TIM4
      htim4.Init.Prescaler =0;                                 //设置从定时器频率为0
      htim4.Init.CounterMode = TIM_COUNTERMODE_UP;             //设置计数模式为向上计数
      htim4.Init.Period =0xffff;                               //这个大于0就行
      htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;       //设置为无分频    
      if (HAL_TIM_Base_Init(&htim4) != HAL_OK)
      {
        Error_Handler();
      }
        
        
      sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;  //设置为内部时钟触发,即为TIM3
      if (HAL_TIM_ConfigClockSource(&htim4, &sClockSourceConfig) != HAL_OK)
      {
        Error_Handler();
      }
        
      sSlaveConfig.SlaveMode =  TIM_SLAVEMODE_GATED;              //设置为门触发
      sSlaveConfig.InputTrigger = TIM_TS_ITR2;                    //设置ITR2(tim3)为输入源
      sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_RISING;  //设置触发模式为上升沿
      sSlaveConfig.TriggerPrescaler = TIM_TRIGGERPRESCALER_DIV1;  //设置无预分频 
      sSlaveConfig.TriggerFilter = 0x0;                           //设置无滤波
        
      if (HAL_TIM_SlaveConfigSynchronization(&htim4, &sSlaveConfig) != HAL_OK)
      {
        Error_Handler();
      }
         HAL_TIM_Base_Stop_IT(&htim4);
    
    
    }

    从定时器的频率一定要设为0,不然输出的PWM会加倍

    中断处理函数

      HAL里的中断处理函数要选HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim),当TIM4->CNT的值达到TIM4->ARR的值时触发中断,关闭主从定时器,清零中断标志位SR

    void  HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    { 
        
       FLAG1_OK = 0; 
        
      
        if(htim==(&htim4))
        {    
            
    //****************************************************//       
                if(__HAL_TIM_GET_FLAG(&htim4, TIM_FLAG_CC1) != RESET)           //判断是否触发中断
            { 
                 __HAL_TIM_CLEAR_FLAG(&htim4, TIM_FLAG_CC1);                    //清除中断标志位
                  
                 HAL_TIM_PWM_Stop_IT(&htim3, TIM_CHANNEL_1);                    //关闭主定时器的PWM输出
                 
                 HAL_TIM_Base_Stop_IT(&htim4);                                  //关闭从定时器的计数
            
    //****************************************************//                      
            
            }
        
        delay_ms(1);    
            FLAG1_OK = 1;
        }
    
            
    }

    脉冲输出主函数

       中断函数关闭的,于此要重新开启,有始有终

    while(1)
    { 
         
      
        if(FLAG1_OK == 1 )     //标志判断
        {        she10
        
             __HAL_TIM_SET_AUTORELOAD(&htim4,10-1);    //ARR装载要输出的PWM脉冲数 
            
             HAL_TIM_Base_Start_IT(&htim4);                   //从定时器计数开启
            
           HAL_TIM_PWM_Start_IT(&htim3, TIM_CHANNEL_1);        //主定时器PWM脉冲输出

    } }

     分析仪实测波形

     

    很漂亮整洁的10个PWM波,在1MHz以下挺准的,但上去了就多了一两个波,还需要细调。

    这个是单定时器的单通道的程序,已经写好单定时器多通道的了,有时间再发。

    有不足之处还请各位不吝赐教。

     

     

  • 相关阅读:
    JS 禁止刷新和右键
    报错 避免重复
    CSS 总结
    CSS BUG 总结
    安装 mrtg
    人人网 网站接入总结
    PHPcms 把盛大登陆换成人人网登陆
    HTML 相同name 传递一个数组
    file_get_contents无法请求https连接的解决方法
    现货黄金白银上阻力位和压力位的确定和应用
  • 原文地址:https://www.cnblogs.com/feiniaoliangtiangao/p/10745691.html
Copyright © 2020-2023  润新知