cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with timer initialization (TIM1)

danesh
Associate II
Posted on September 04, 2015 at 19:08

Dear all,

I want to use TIM1 CH3N  to drive a buzzer with different frequencies. I have 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.

8 REPLIES 8
Posted on September 04, 2015 at 19:16

And what STM32 part is this, and what pin# are we talking about, and is it configured.

This looks to be overly complicated.

Are you sure the buzzer takes a PWM signal, and isn't just an ON/OFF type device?

Don't set the prescaler to the period value, if the period is based off the TIMCLK, leave the prescaler as zero.

Is the millisecond delay function work properly, or use an interrupt?

If you just drive the pin high/low manually, as a GPIO, does the buzzer function as expected?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on September 04, 2015 at 19:17

Is there some purpose to enabling the CC3 interrupt?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on September 04, 2015 at 19:25

The pin connected to the buzzer is GPIOB_15. The buzzer is ST-03CH. I used to drive the buzzer by activating a timer (TIM2 to be specific) and generate sounds by toggling its pin (on/off at different frequencies) and it worked perfectly. So, I am actually not sure if the buzzer works with PWM signal too or not. The milisecond function is based on Data Watchpoint and it is tested separately and works fine. The problem with previous approach (toggling buzzer pin based on TIM2) was that since I had to toggle buzzer's pin in TIM2's interrupt handler and at the same time I needed to run buzzer in another interrupt handler when an interrupt was triggered, this never worked. I could run buzzer without any problem in the main thread (main function) but not in any interrupt handler. That is why I tried to implement another approach by activating TIM1 as alternate function directly on the buzzer's pin.

danesh
Associate II
Posted on September 04, 2015 at 19:27

You are right and CC3 interrupt is not needed here. But I thought it wouldn't have any effect. I am not not using any interrupt in this approash.

Posted on September 04, 2015 at 19:37

What STM32 part, they make literally hundreds of different families/variants at this point?

How are you getting 4-5V to this buzzer?

Needs a 50/50 duty, have you confirmed the value being programmed? Can you see a signal with a scope if you just program the timer to clock at 50 Hz, with a 50/50 duty? ie turn it on, and don't turn it off?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on September 04, 2015 at 19:46

It is a STM32F103 MCU.

I am not sure what you mean with getting 4-5v, but the buzzer is a 4-pin chip.

The chip worked with TIM2 and toggling buzzer's pin. With TIM1, when I activated the timer's interrupt for test, I saw that the interrupt is called only once, so the timer is not working as it should. Do I still need to test it with scope when I know that the input signal is not there? Besides, can you please let me know if this is a limitation that my interrupt handler could not run buzzer when I toggles buzzer's pin in another interrupt handler (TIM2's interrupt handler) or there is a solution for that?

Regards,

Dan.

Posted on September 04, 2015 at 21:58

Sorry I'm just reviewing the

http://www.soberton.com/wp-content/themes/uploads/ST-03CH1.pdf

If you sit in an interrupt, spinning in a delay loop, the other interrupt implementing the delay count would actually have to be serviced, which won't happen if it can't preempt the current one. The general rule is to do you're thing and leave immediately. Quick blind example

// STM32F103 PWM1 TIM1_CH3N(PB15) - sourcer32@gmail.com
#include ''stm32f10x.h''
/**************************************************************************************/
void RCC_Configuration(void)
{
/* TIM1 and GPIOB clocks enable */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOB, ENABLE);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* GPIOB Configuration: Channel 3N as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**************************************************************************************/
void TIM1_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
/* Time Base configuration */
TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // 1MHz timebase from 72 MHz bus
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 20000 - 1; // 50 Hz
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
/* Channel 3 Configuration in PWM mode */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = 10000; // 50/50
TIM_OC3Init(TIM1, &TIM_OCInitStructure); // Channel 3
/* TIM1 counter enable */
TIM_Cmd(TIM1, ENABLE);
/* TIM1 Main Output Enable */
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
TIM1_Configuration();
while (1); /* Infinite loop */
}
/**************************************************************************************/
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t* file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
/* Infinite loop */
while (1)
{
}
}
#endif

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danesh
Associate II
Posted on September 15, 2015 at 14:14

Thanks a lot. I think I initialized the timer incorrectly. It works now. Thanks again. I am also surprised that the buzzer works with toggling its pin and also when a timer is directly connected to the buzzer which is better and more precise. I have another question. My processor i.e. STM32F103 is operating at 72 MHz, but when I run ''SystemCoreClockUpdate()'' function, the variable for the core frequency value shows 108 MHz which doesn't really make sense since 72 MHz should be the highest operating frequency for this MCU. How would it possible? I have also used this updated value i.e. 108 MHz as freauency for TIM1. I hope I have done the right thing.

Regards,

Dan