171 lines
5.4 KiB
C
171 lines
5.4 KiB
C
/* 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);
|
||
} |