2015-09-04 10:08 AM
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.2015-09-04 10:16 AM
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?2015-09-04 10:17 AM
Is there some purpose to enabling the CC3 interrupt?
2015-09-04 10:25 AM
2015-09-04 10:27 AM
2015-09-04 10:37 AM
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?2015-09-04 10:46 AM
2015-09-04 12:58 PM
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
2015-09-15 05:14 AM
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