Files
Simba-OmniInfantry/云台/modules/dev/buzzer.c
T

118 lines
5.0 KiB
C

/* =============================================================================
* buzzer.c - C 板无源蜂鸣器(TIM4_CH3, PD14)
* 说明: 音调表与 legacy 完全一致(ARR 固定 10 分频,改 PSC 变调,
* 装载用 HAL_TIM_GenerateEvent 立即生效);buzzer_init 必须在
* CAN_Task 中调用一次启动 PWM 输出,否则所有报警/音效无声
* ========================================================================== */
#include "buzzer.h"
#include "tim.h"
#include "robot_param.h"
extern TIM_HandleTypeDef htim4;
/* 蜂鸣器音调频率表(ARR 固定 10 分频下的 PSC 值,与 legacy 一致) */
static const uint16_t buzzer_tone_freq[37] = {
0,
32107, 30305, 28604, 26999, 25483, 24053, 22703, 21429, 20226, 19091, 18019, 17008,
16053, 15152, 14302, 13499, 12742, 12026, 11352, 10714, 10113, 9545, 9010, 8504,
8027, 7576, 7151, 6750, 6371, 6013, 5676, 5357, 5056, 4773, 4505, 4252,
};
void buzzer_init(void)
{
/* 与 legacy 相同:ARR=10 分频,CubeMX 的 ARR=65535 改为 9 */
__HAL_TIM_SET_AUTORELOAD(&htim4, 10 - 1);
__HAL_TIM_SET_PRESCALER(&htim4, 19091);
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_3);
}
void buzzer_on(buzzer_tone_e tone)
{
if (tone != BUZZER_P)
{
__HAL_TIM_SET_PRESCALER(&htim4, buzzer_tone_freq[tone]);
HAL_TIM_GenerateEvent(&htim4, TIM_EVENTSOURCE_UPDATE); // 立即装载 PSC
/* 占空比 30%:抑制高次尖锐谐波,使吉他拨弦音色圆润纯净 */
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 3);
}
else
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
}
void buzzer_off(void)
{
__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_3, 0);
}
/* ==========================================================================
* 周杰伦《晴天》- 标志性吉他前奏伴奏 Solo (纯享循环版)
* 调式: 1=C,处于 C 板蜂鸣器最佳频响区间(500~1000Hz)
* 结构: 完整还原原曲前奏 4 小节经典木吉他单音分解
* [小节1: Em] 3 2 1 1 2 1 5_ 1 2
* [小节2: C ] 3 2 1 1 2 1 6_ 1 2
* [小节3: G ] 3 2 1 1 2 1 5_ 1 2
* [小节4: D ] 3 2 1 1 2 1 2 3 5 3 2 1 2 -
* 吐音设计: 每个音符保留 BUZZER_P 间隔,模拟吉他真实的清脆拨弦与泛音
* ========================================================================== */
static const buzzer_tone_e buzzer_melody[] = {
/* ---- 小节 1 (Em): 3 2 1 1 2 1 | 5_ 1 2 ---- */
BUZZER_M3, BUZZER_P, // 3 (Mi)
BUZZER_M2, BUZZER_P, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_L5, BUZZER_P, // 低音 5 (Sol)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
/* ---- 小节 2 (C): 3 2 1 1 2 1 | 6_ 1 2 ---- */
BUZZER_M3, BUZZER_P, // 3 (Mi)
BUZZER_M2, BUZZER_P, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_L6, BUZZER_P, // 低音 6 (La)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
/* ---- 小节 3 (G): 3 2 1 1 2 1 | 5_ 1 2 ---- */
BUZZER_M3, BUZZER_P, // 3 (Mi)
BUZZER_M2, BUZZER_P, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_L5, BUZZER_P, // 低音 5 (Sol)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
/* ---- 小节 4 (D): 3 2 1 1 2 1 | 2 3 5 3 2 1 2 - ---- */
BUZZER_M3, BUZZER_P, // 3 (Mi)
BUZZER_M2, BUZZER_P, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M1, // 1 (Do)
BUZZER_M2, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M2, BUZZER_P, // 2 (Re)
BUZZER_M3, // 3 (Mi)
BUZZER_M5, // 5 (Sol)
BUZZER_M3, // 3 (Mi)
BUZZER_M2, // 2 (Re)
BUZZER_M1, BUZZER_P, // 1 (Do)
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P, // 2 (Re 长音结音)
BUZZER_P, BUZZER_P, BUZZER_P, BUZZER_P, // 尾部休止 400ms 后循环
};
void buzzer_play_melody(uint16_t step)
{
const uint16_t steps =
(uint16_t)(sizeof(buzzer_melody) / sizeof(buzzer_melody[0]));
#ifndef BUZZER_MELODY_SPEED_DIV
#define BUZZER_MELODY_SPEED_DIV 1
#endif
buzzer_on(buzzer_melody[(step / BUZZER_MELODY_SPEED_DIV) % steps]);
}