cancel
Showing results for 
Search instead for 
Did you mean: 

Minimal configuration to restart PWM

kenneth
Associate
Posted on December 29, 2015 at 22:42

I am using the timer output to drive a buzzer.  It runs okay as it is but I have to completely reinitialize the timer counter registers each time I want to make a sound.  Don't the configuration settings persist?  I would think that I should be able to configure the timer registers once and then just enable/disable to start/stop the sound.  Note that this is a battery powered device so I do want to turn off the timer when not in use.  Here is the code I use now which works but seems excessive.  But anything less will not turn on the output.  Is there a simpler way - or are my settings getting lost somehow.

Initialization:

  /*Enable or disable the AHB peripheral clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);

  /*Configure GPIO pin : PB */

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;

  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_400KHz;

  GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pin alternate function */

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM11);

Code which must be repeated every cycle.

void ConfigureChirpPWM(FunctionalState enable)

{

 if (enable == ENABLE)

 {

  uint16_t PrescalerValue;

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_OCInitTypeDef TIM_OCInitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, ENABLE);

  /* Compute the prescaler value */

 

  PrescalerValue = (uint16_t) (SystemCoreClock / 800000) - 1;

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

 

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

 

  TIM_TimeBaseStructure.TIM_Period = FOUR_KHZ;

 

  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;

 

  TIM_TimeBaseInit(TIM11, &TIM_TimeBaseStructure);

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

 

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

 

  TIM_OCInitStructure.TIM_Pulse = (AudioIntensityTimerCounter * FOUR_KHZ) / 100;

 

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

 

  TIM_OC1Init(TIM11, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM11, TIM_OCPreload_Enable);

  TIM_Cmd(TIM11, ENABLE);

 }

 else

 {

  TIM_ForcedOC1Config(TIM11, TIM_ForcedAction_InActive);  // Be sure output is low

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, DISABLE);

  TIM_Cmd(TIM11, DISABLE);

 }

}

I would have thought I could put the italicized code in the initialization and not do it every time but that does not work.  Ideas?

Thanks.

#pwm-timer-output
1 REPLY 1
Posted on December 29, 2015 at 23:29

No real clue as to which STM32 part we are talking about here, or what power modes it might transition through.

The ordering of this fails, you can't turn the peripheral clock off, and then have register writes to it work.

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, DISABLE); 

 TIM_Cmd(TIM11, DISABLE);

To undo that, you'd need

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM11, ENABLE);

// Dwell a few cycles

// Undo this, or figure a better method to stop the output, ie preload ARR,CNT,CCR1 to zero

//  TIM_ForcedOC1Config(TIM11, TIM_ForcedAction_InActive); 

 

 TIM_Cmd(TIM11, ENABLE);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..