Quadcopter/User/bsp/buzzer_pwm.c
2025-10-03 14:32:06 +08:00

171 lines
5.4 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Includes ----------------------------------------------------------------- */
#include "buzzer_pwm.h"
#include "main.h"
#include "tim.h"
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
typedef struct {
TIM_HandleTypeDef* htim;
uint32_t channel;
} BSP_BUZZER_Config_t;
/* Private variables -------------------------------------------------------- */
BSP_BUZZER_Config_t bsp_buzzer_ch={&htim4, TIM_CHANNEL_3}; //自定义蜂鸣器TIM通道
uint8_t bsp_buzzer_s_flag = 0; //蜂鸣器状态
/* Private function -------------------------------------------------------- */
/* Exported functions ------------------------------------------------------- */
/**
* @brief 获取APBx定时器时钟频率
* @param *htim 定时器句柄
* @return APBx定时器时钟频率
*/
int32_t BSP_BUZ_GetTIMxFrequency(TIM_HandleTypeDef *htim) {
uint32_t timx_clk = 0;
if (htim->Instance == TIM4) {
timx_clk = HAL_RCC_GetPCLK1Freq();
if (HAL_RCC_GetPCLK1Freq() != SystemCoreClock) {
timx_clk *= 2;
}
return timx_clk;
}
return BSP_ERR;
}
/**
* @brief 使能蜂鸣器PWM通道
* @return 成功BSP_OK 错误BSP_ERR
*/
int8_t BSP_BUZZER_Start(void) {
if(HAL_TIM_PWM_Start(bsp_buzzer_ch.htim, bsp_buzzer_ch.channel)!=HAL_OK){
return BSP_ERR;
}else return BSP_OK;
}
/**
* @brief 失能蜂鸣器PWM通道
* @return 成功BSP_OK 错误BSP_ERR
*/
int8_t BSP_BUZZER_Stop(void){
if(HAL_TIM_PWM_Stop(bsp_buzzer_ch.htim, bsp_buzzer_ch.channel)!=HAL_OK){
return BSP_ERR;
}else return 0;
}
/**
* @brief 设置蜂鸣器PWM占空比
* @param duty_cycle 占空比
* @return 成功BSP_OK 错误BSP_ERR
*/
int8_t BSP_BUZZER_Set_Duty_Cycle(float duty_cycle) {
if (duty_cycle > 1.0f) return BSP_ERR;
uint16_t pulse = duty_cycle * bsp_buzzer_ch.htim->Instance->ARR;
__HAL_TIM_SET_COMPARE(bsp_buzzer_ch.htim, bsp_buzzer_ch.channel, pulse);
return BSP_OK;
}
/**
* @brief 设置蜂鸣器PWM频率
* @param psc 预分频值
* @param arr 自动重装载值
* @return 成功BSP_OK 错误BSP_ERR
*/
int8_t BSP_BUZZER_Set_Freq(uint16_t psc, uint16_t arr) {
if (psc == 0 || arr == 0) return BSP_ERR;
BSP_BUZZER_Stop();
__HAL_TIM_SET_PRESCALER(bsp_buzzer_ch.htim, psc);
__HAL_TIM_SetAutoreload(bsp_buzzer_ch.htim, arr);
__HAL_TIM_SET_COMPARE(bsp_buzzer_ch.htim, bsp_buzzer_ch.channel, bsp_buzzer_ch.htim->Instance->ARR * 0.5); // 鏇存柊鍗犵┖姣?
BSP_BUZZER_Start();
return BSP_OK;
}
/**
* @brief 设置蜂鸣器音调和音量
* @param s 蜂鸣器状态
* @param tone 音调
* @param volume 音量
* @return 成功BSP_OK 错误BSP_ERR
*/
int8_t BSP_BUZZER_Set(BSP_BUZZER_Status_t s, BSP_BUZZER_USUAL_TONE_t tone, float volume)
{
switch (s)
{
case BSP_BUZZER_ON:
BSP_BUZZER_Start();
bsp_buzzer_s_flag= 1;
break;
case BSP_BUZZER_OFF:
BSP_BUZZER_Stop();
bsp_buzzer_s_flag= 2;
break;
case BSP_BUZZER_TAGGLE:
if (bsp_buzzer_s_flag==1)
{
BSP_BUZZER_Stop();
bsp_buzzer_s_flag=2;
}
else if(bsp_buzzer_s_flag==2)
{
BSP_BUZZER_Start();
bsp_buzzer_s_flag=1;
}
else return BSP_ERR;
default:
return BSP_ERR;
}
if(bsp_buzzer_s_flag==1)
switch(tone)
{
case BSP_BUZZER_C5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_C5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_D5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_D5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_E5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_E5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_F5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_F5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_G5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_G5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_A5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_A5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
case BSP_BUZZER_B5:
BSP_BUZZER_Set_Freq(BSP_BUZ_GetTIMxFrequency(bsp_buzzer_ch.htim)/1000000, 1000000/BSP_BUZZER_B5);
BSP_BUZZER_Set_Duty_Cycle(volume);
break;
default:
return BSP_ERR;
}
return BSP_OK;
}
void Buzzer_On(uint16_t freq_hz, uint8_t volume) {
uint32_t arr_value = (168000000 / (167 + 1) / freq_hz) - 1; // 动态计算 ARR
__HAL_TIM_SET_AUTORELOAD(&htim4, arr_value); // 更新 ARR
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, (arr_value + 1) * volume / 100); // 设置占空比
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3); // 启动 PWM
}
// 关闭蜂鸣器
void Buzzer_Off(void) {
HAL_TIM_PWM_Stop(&htim4, TIM_CHANNEL_3);
}