cancel
Showing results for 
Search instead for 
Did you mean: 

Failing to call interrupt handler

danesh
Associate II
Posted on September 04, 2015 at 09:23

Hi all,

I have implemented a simple routine to drive a buzzer. The routine will enable a timer and will toggle state of the pin connected to the buzzer at different frequencies. The buzzer code is:

void buzz(uint32_t freq, uint32_t t, uint32_t duty_cycle) {

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

  TIM2_init(freq, duty_cycle);

  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

  TIM_Cmd(TIM2, ENABLE);

  delay_ms(t);

  TIM_DeInit(TIM2);

  TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE);

  TIM_Cmd(TIM2, DISABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, DISABLE);

}

and the interrupt handler where the pin state is toggles is:

void TIM2_IRQHandler() {

  TIM_ClearITPendingBit(TIM2, TIM_IT_Update);

  ToggleBuzzerBit();

}

The code works fine as it should from the main function in the code, but I would like to call buzzer in another interrupt handler. In that case, when I call buzzer from another

interrupt handler, it never works and I can see through code tracing that the timer never starts and therefore the buzzer pin never toggles inside the interrupt handler above.

I am wondering whether there is any solution for that, or it is a limitation that an interrupt handler cannot be called by another interrupt handler?

Thanks for your help,

Dan.

1 REPLY 1
danesh
Associate II
Posted on September 04, 2015 at 11:29

I decided to try to use TIM1 channle 3N which can be used on the pin which is connected to the buzzer to just simply turn on and off the timer on the selected pin, without need to toggle the bit manually which seems to be more efficient. Then I tried to program TIM1 on channel 3N as below (the corresponding pin is already configured as AF_PP at 50 MHz):

void buzz(uint32_t freq, uint32_t t, uint32_t duty_cycle) {

  // Turn on peripheral clock for the buzzer only when it is needed.

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

  // Initialize the timer TIM1 on channel 3N timer with the given frequency

  // and duty cycle.

  TIM_TimeBaseInitTypeDef TIM_InitStruct;

  TIM_OCInitTypeDef TIM_OCStruct;

  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

  // Reset all timers to their default values.

  TIM_DeInit(TIM1);

  uint32_t period = 0;

  if (freq == 0)

    // DC is not allowed, so just assume frequency is 1Hz.

    period = (SystemCoreClock / 1) - 1;

  else

    period = (SystemCoreClock / freq) - 1;

  // Configure TIM1 internal timer.

  TIM_InitStruct.TIM_Prescaler         = period;

  TIM_InitStruct.TIM_CounterMode       = TIM_CounterMode_Up;

  TIM_InitStruct.TIM_Period            = period;

  TIM_InitStruct.TIM_ClockDivision     = 0;

  TIM_InitStruct.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM1, &TIM_InitStruct);

  // TIM1 on channel 3N configuration in PWM mode.

  TIM_OCStruct.TIM_OCMode       = TIM_OCMode_Timing;

  TIM_OCStruct.TIM_OutputState  = TIM_OutputState_Enable;

  TIM_OCStruct.TIM_OutputNState = TIM_OutputNState_Enable;

  TIM_OCStruct.TIM_Pulse        = (period + 1) * duty_cycle / 100;

  TIM_OCStruct.TIM_OCPolarity   = TIM_OCPolarity_High;

  TIM_OCStruct.TIM_OCNPolarity  = TIM_OCNPolarity_High;

  TIM_OCStruct.TIM_OCIdleState  = TIM_OCIdleState_Set;

  TIM_OCStruct.TIM_OCNIdleState = TIM_OCNIdleState_Set;

  TIM_OC3Init(TIM1, &TIM_OCStruct);

  // 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_OFF;

  TIM_BDTRInitStructure.TIM_DeadTime        = 1;

  TIM_BDTRInitStructure.TIM_Break           = TIM_Break_Enable;

  TIM_BDTRInitStructure.TIM_BreakPolarity   = TIM_BreakPolarity_High;

  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

  TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);

  TIM_CCPreloadControl(TIM1, ENABLE);

  TIM_ITConfig(TIM1, TIM_IT_CC3, ENABLE);

  TIM_Cmd(TIM1, ENABLE);

  TIM_CtrlPWMOutputs(TIM1, ENABLE);

  TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_OCMode_PWM1);

  TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);

  // Buzz for t ms.

  delay_ms(t);

  // Disable TIM1 internal timer.

  TIM_DeInit(TIM1);

  TIM_CCPreloadControl(TIM1, DISABLE);

  TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE);

  TIM_Cmd(TIM1, DISABLE);

  TIM_CtrlPWMOutputs(TIM1, DISABLE);

  // Turn off the buzzer's peripheral clock to save some power.

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, DISABLE);

}

But the code doesn't work at all and nothing happens on the buzzer side. Can anybody give a hint if there is any problem?

Regards,

Dan.