2024-04-22 09:04 PM
I am developing a product using the STM32F412REFxLQFP64 chip, and I want to implement multi-PWM control.
For TIM2 buzzer control: TIM_HandleTypeDef TIM2 PB10 ------> TIM2_CH3
TIM3 is used to generate a 1kHz waveform: TIM_HandleTypeDef TIM3 Channel 4 PB1 ------> TIM3_CH4
void buzzerInit(void)
{
Buzzer_InitTypeDef buzzerConfig;
buzzerConfig.channel = TIM_CHANNEL_3;
buzzerConfig.timer = &htim2;
buzzerConfig.timerClockFreqHz = HAL_RCC_GetPCLK2Freq(); // NOTE: this should be freq of timer, not frequency of peripheral clock
hbuzzer.Init = buzzerConfig;
}
void buzzer(BUZZER_StateTypeDef mode){
buzzerStart(&hbuzzer);
size_t songSize;
switch(mode){
case BUZZER_REGISTER:{
songSize = sizeof(buzzer_register_theme) / sizeof(buzzer_register_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_register_theme[i].pitch);
HAL_Delay(buzzer_register_theme[i].duration * 15);
}
break;
}
case BUZZER_START:{
songSize = sizeof(buzzer_start_theme) / sizeof(buzzer_start_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_start_theme[i].pitch);
HAL_Delay(buzzer_start_theme[i].duration * 15);
}
break;
}
case BUZZER_END:{
songSize = sizeof(buzzer_end_theme) / sizeof(buzzer_end_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_end_theme[i].pitch);
HAL_Delay(buzzer_end_theme[i].duration * 15);
}
break;
}
default :{
break;
}
}
buzzerStop(&hbuzzer);
return;
}
void ctrl_pwm_1hz(char _flg)
{
if(pwm_status == _flg)
return;
pwm_status = _flg;
if(_flg == 0)
{
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_4);
}
else
{
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
}
}
When I control the buzzer and the 1kHz signal individually,
there are no issues. However, when I try to control them simultaneously,
the buzzer does not sound.
How can I solve this issue?
Thank you.
Solved! Go to Solution.
2024-05-09 06:06 AM
If you change TIMx_ARR in running timer (or stop timer for the TIMx_ARR change but don't clear TIMx_CNT) , use the ARR preload, i.e. set TIMx_CR1.ARPE.
JW
2024-04-23 12:22 AM
Hello,
can you also send the code of these functions:
buzzerStart(&hbuzzer);
buzzerNote(&hbuzzer, buzzer_register_theme[i].pitch);
buzzerStop(&hbuzzer);
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-04-23 07:47 AM
> However, when I try to control them simultaneously, the buzzer does not sound.
Read out and check/compare-to-working/post TIM registers content, for working/non-working setup.
JW
2024-04-23 08:05 AM
Hello there.
this is buzzer code
#include "buzzer.h"
Buzzer_HandleTypeDef hbuzzer;
note_t buzzer_register_theme[] =
{
{NOTE_E7, 12},
{0, 12},
{NOTE_E7, 12},
{0, 12},
{NOTE_E7, 12},
{0, 12},
{NOTE_C7, 12},
{NOTE_C7, 12}
};
note_t buzzer_start_theme[] =
{
{NOTE_E7, 12},
{NOTE_F7, 12},
{NOTE_FS7, 12},
{NOTE_G7, 12},
{NOTE_GS7, 12},
{NOTE_A7, 12}
};
void buzzerInit(void)
{
Buzzer_InitTypeDef buzzerConfig;
buzzerConfig.channel = TIM_CHANNEL_3;
buzzerConfig.timer = &htim2;
buzzerConfig.timerClockFreqHz = HAL_RCC_GetPCLK2Freq(); // NOTE: this should be freq of timer, not frequency of peripheral clock
hbuzzer.Init = buzzerConfig;
}
void buzzerNote(Buzzer_HandleTypeDef* handle, uint32_t noteFreq) {
if(noteFreq > 0) {
handle->Init.timer->Instance->ARR=handle->Init.timerClockFreqHz/(handle->Init.timer->Init.Prescaler+1)/noteFreq;
__HAL_TIM_SET_COMPARE(handle->Init.timer, handle->Init.channel, handle->Init.timer->Instance->ARR/2);
} else
__HAL_TIM_SET_COMPARE(handle->Init.timer, handle->Init.channel, 0);
}
void buzzerNoNote(Buzzer_HandleTypeDef* handle) {
buzzerNote(handle,0);
}
void buzzerStart(Buzzer_HandleTypeDef* handle) {
buzzerNoNote(handle);
HAL_TIM_PWM_Start(handle->Init.timer, handle->Init.channel);
}
void buzzerStop(Buzzer_HandleTypeDef* handle){
buzzerNote(&hbuzzer, 0);
HAL_TIM_PWM_Stop(handle->Init.timer, handle->Init.channel);
}
void buzzer(BUZZER_StateTypeDef mode){
buzzerStart(&hbuzzer);
size_t songSize;
switch(mode){
case BUZZER_REGISTER:{
songSize = sizeof(buzzer_register_theme) / sizeof(buzzer_register_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_register_theme[i].pitch);
HAL_Delay(buzzer_register_theme[i].duration * 15);
}
break;
}
case BUZZER_START:{
songSize = sizeof(buzzer_start_theme) / sizeof(buzzer_start_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_start_theme[i].pitch);
HAL_Delay(buzzer_start_theme[i].duration * 15);
}
break;
}
case BUZZER_END:{
songSize = sizeof(buzzer_end_theme) / sizeof(buzzer_end_theme[0]);
for (size_t i = 0; i < songSize; i++) {
buzzerNote(&hbuzzer, buzzer_end_theme[i].pitch);
HAL_Delay(buzzer_end_theme[i].duration * 15);
}
break;
}
default :{
break;
}
}
buzzerStop(&hbuzzer);
return;
}
This is TIM code
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file tim.c
* @brief This file provides code for the configuration
* of the TIM instances.
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "tim.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
//PWM TM2 CH3 = PB10, BUZZER
//PWM TM3 CH4 = PB1, Voltage Level Control
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
/* TIM2 init function */
void MX_TIM2_Init(void)
{
/* USER CODE BEGIN TIM2_Init 0 */
/* USER CODE END TIM2_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM2_Init 1 */
/* USER CODE END TIM2_Init 1 */
htim2.Instance = TIM2;
htim2.Init.Prescaler = 8-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0xFFFF;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM2_Init 2 */
/* USER CODE END TIM2_Init 2 */
HAL_TIM_MspPostInit(&htim2);
}
/* TIM3 init function */
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 32;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 999;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 499;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* TIM2 clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(tim_pwmHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* TIM3 clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(timHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM2 GPIO Configuration
PB10 ------> TIM2_CH3
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */
}
else if(timHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM3 GPIO Configuration
PB1 ------> TIM3_CH4
*/
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
}
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* tim_pwmHandle)
{
if(tim_pwmHandle->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(tim_pwmHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
note_t buzzer_end_theme[] =
{
{NOTE_C7, 12},
{0, 12},
{NOTE_C7, 12},
{0, 12},
{NOTE_C7, 12},
{0, 12}
};
sorry this code inside buzzer.c
This is PWM code
extern TIM_HandleTypeDef htim3;
char pwm_status = 0;
void ctrl_pwm_1hz(char _flg)
{
if(pwm_status == _flg)
return;
pwm_status = _flg;
if(_flg == 0)
{
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_4);
}
else
{
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
}
}
this is main code
buzzer(BUZZER_START);
osDelay(500);
pwm_flag = true;
ctrl_pwm_1hz(pwm_flag);
When you first call the function, the buzzer and PWM operate normally,
But when you call the function the next time,
The buzzer does not operate normally and only the PWM operates normally.
2024-04-25 09:20 PM
Commented below.
2024-04-25 09:21 PM
Commented below.!
2024-04-29 02:37 AM
It seems that the definition of htim2 in buzzer code is missing so try to add:
extern TIM_HandleTypeDef htim2;
into buzzer code.
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-05-07 07:24 PM
I put the code into the buzzer, but it doesn't work.
#include "buzzer.h"
extern TIM_HandleTypeDef htim2;
Buzzer_HandleTypeDef hbuzzer;
2024-05-08 07:15 PM - edited 2024-05-08 07:16 PM
We set a break point and analyzed the case closely.
When it's normal
TIM_HandleTypeDef
TIM_TypeDef *Instance; in
CNT; /*!< TIM counter register,
The value is within the normal range, but when there is no sound, there is a large value as shown below.
If we are trying to solve this, how should we solve it?
normal sound buzzer img = cnt range 100~ , 200~ , etc...
error sound buzzer img = cnt range 7237947, 619114 etc..
2024-05-09 06:06 AM
If you change TIMx_ARR in running timer (or stop timer for the TIMx_ARR change but don't clear TIMx_CNT) , use the ARR preload, i.e. set TIMx_CR1.ARPE.
JW