stm32定時器時鍾以及中間對齊模式


在永磁同步電機的控制中,需要對電機的三相定子施加一定的電壓,才能控制電機轉動。現在用的較多的是SVPWM(SVPWM的具體原理會在后面另寫一篇博客說明),要想產生SVPWM波形,需要控制的三相電壓呈如下形式,即A、B、C三相的電壓是中間對齊的,這就需要用到stm32定時器的中間對齊模式了。

1、stm32的時鍾樹

stm32的時鍾樹如下圖所示,簡單介紹一下stm32時鍾的配置過程。以外部時鍾作為時鍾源為例。HSE代表外部時鍾(假設為8M)、SYSCLK為系統時鍾,經過倍頻器之后變成168M、SYSCLK經過AHB預分頻器(假設分頻系數為1)后變成HCLK時鍾等於系統時鍾SYSCLKHCLK即AHB外部總線時鍾,經過APB預分頻器分出APB1時鍾(分頻系數為2,低速設備SYSCLK/4)與APB2時鍾(分頻系數為1,高速設備SYSCLK/2

HSE->SYSCLK->HCLK->APB1、APB2。

 針對stm32f427的配置源碼如下

static void SetSysClock(void)
{
#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx) || defined (STM32F401xx)
/******************************************************************************/
/*            PLL (clocked by HSE) used as System clock source                */
/******************************************************************************/
  __IO uint32_t StartUpCounter = 0, HSEStatus = 0;
  
  /* Enable HSE */
  RCC->CR |= ((uint32_t)RCC_CR_HSEON);
 
  /* Wait till HSE is ready and if Time out is reached exit */
  do
  {
    HSEStatus = RCC->CR & RCC_CR_HSERDY;
    StartUpCounter++;
  } while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));

  if ((RCC->CR & RCC_CR_HSERDY) != RESET)
  {
    HSEStatus = (uint32_t)0x01;
  }
  else
  {
    HSEStatus = (uint32_t)0x00;
  }

  if (HSEStatus == (uint32_t)0x01)
  {
    /* Select regulator voltage output Scale 1 mode */
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    PWR->CR |= PWR_CR_VOS;

    /* HCLK = SYSCLK / 1*/
    RCC->CFGR |= RCC_CFGR_HPRE_DIV1;//AHB時鍾  

#if defined (STM32F40_41xxx) || defined (STM32F427_437xx) || defined (STM32F429_439xx)      
    /* PCLK2 = HCLK / 2*/
    RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;//APB2時鍾
    
    /* PCLK1 = HCLK / 4*/
    RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;//APB1時鍾
#endif /* STM32F40_41xxx || STM32F427_437x || STM32F429_439xx */

   
    /* Configure the main PLL */
    RCC->PLLCFGR = PLL_M | (PLL_N << 6) | (((PLL_P >> 1) -1) << 16) |
                   (RCC_PLLCFGR_PLLSRC_HSE) | (PLL_Q << 24);

    /* Enable the main PLL */
    RCC->CR |= RCC_CR_PLLON;

    /* Wait till the main PLL is ready */
    while((RCC->CR & RCC_CR_PLLRDY) == 0)
    {
    }
   
#if defined (STM32F427_437xx) || defined (STM32F429_439xx)
    /* Enable the Over-drive to extend the clock frequency to 180 Mhz */
    PWR->CR |= PWR_CR_ODEN;
    while((PWR->CSR & PWR_CSR_ODRDY) == 0)
    {
    }
    PWR->CR |= PWR_CR_ODSWEN;
    while((PWR->CSR & PWR_CSR_ODSWRDY) == 0)
    {
    }      
    /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
    FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_5WS;
#endif /* STM32F427_437x || STM32F429_439xx  */


    /* Select the main PLL as system clock source */
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    /* Wait till the main PLL is used as system clock source */
    while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL);
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock
         configuration. User can add here some code to deal with this error */
  }
}

2、stm32定時器的時鍾

 stm32定時器分為高級定時器(TIM1與TIM8)、通用定時器(TIM2-TIM5、TIM9-TIM14)、基本定時器(TIM6、TIM7)。不同的定時器使用不同的時鍾。

其中TIM1、TIM8、TIM10、TIM11使用的是APB2時鍾,而其余定時器使用的是APB1時鍾。

在stm32手冊中有這么一段話

 根據前面RCC配置可以知道TIM1、TIM8、TIM10、TIM11使用的時鍾頻率為SYSCLK,其他定時器使用的時鍾頻率為SYSCLK/2

3、stm32定時器1的中間對齊模式

對齊模式的圖示如下圖所示,可以看到在中心對齊模式下產生的PWM波形的周期比實際計數周期要大1倍,所以假設要使用中間對齊模式,並且需要產生的PWM波頻率為20K,那么對應的定時器時基應該設為40K。

在SVPWM波的產生過程中使用的是定時器1的3對互補的PWM通道,它的配置如下

static void TIM1_Configuration(void)
{    
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    TIM_OCInitTypeDef  TIM_OCInitStructure;
    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);//使能定時器1時鍾
    
    Time1_Period =  (SystemCoreClock / 40000 );//定時器頻率為APB2頻率的2倍=HCLK 自動重裝載為40K,最大值為4200
    
    Limit_Pluse_Max_Value = Time1_Period * 0.95;
    
  /* TIM1 Peripheral Configuration */ 
    
  TIM_DeInit(TIM1);

  /* Time Base configuration */
    //配置定時器的計數方式為中間對齊方式,所以產生的PWM波的頻率為20K
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;//TIM_CounterMode_Up;TIM_CounterMode_CenterAligned1
  TIM_TimeBaseStructure.TIM_Period = Time1_Period - 1;//PERIOD;//定時器時基40K
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0x0;

  TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);

  /* Channel 1, 2,3 and 4 Configuration in PWM mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;                  
  TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR1_Val; //占空比50%
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//TIM_OCPolarity_Low;TIM_OCPolarity_High;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;//TIM_OCNPolarity_Low;TIM_OCNPolarity_High;         
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;//TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
    
  TIM_OC1Init(TIM1,&TIM_OCInitStructure); 

  TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR2_Val;//占空比50%
  TIM_OC2Init(TIM1,&TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_Pulse = Time1_Period / 2;//CCR3_Val;//占空比50%
  TIM_OC3Init(TIM1,&TIM_OCInitStructure);
    
    
//   /* Channel 4 Configuration in OC */
//   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
//   TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//   TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;
//   TIM_OCInitStructure.TIM_Pulse = 4000;//Time1_Period / 2;            //1500;//PERIOD - 1; 
//   
//   TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 
//   TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;         
//   TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
//   TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;            
  
//   TIM_OC4Init(TIM1,&TIM_OCInitStructure);    
    
    /* TIMx->CCMR1的bit3設為1:輸出比較寄存器預裝載使能 */  // PWM占空比改變只在更新事件時生效
  TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);//A相
    
    /* TIMx->CCMR1的bit11設為1:輸出比較寄存器預裝載使能 */ // PWM占空比改變只在更新事件時生效
  TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);//B相
    
    /* TIMx->CCMR2的bit3設為1:輸出比較寄存器預裝載使能 */  // PWM占空比改變只在更新事件時生效
  TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);//C相

//   TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);//電磁鐵
    
  /* Automatic Output enable, Break, dead time and lock configuration*/
  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1; 
  TIM_BDTRInitStructure.TIM_DeadTime = 50;
  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;//TIM_Break_Enable;
  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;//TIM_AutomaticOutput_Enable;

  TIM_BDTRConfig(TIM1,&TIM_BDTRInitStructure);
    
    TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_Update);
    
  /* TIM1 counter enable */
//   TIM_Cmd(TIM1,ENABLE);

  /* Main Output Enable */
   TIM_CtrlPWMOutputs(TIM1,ENABLE);//由於使用中間對齊模式,PWM頻率為20K
    
  //TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);//定時器1的溢出中斷
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM