161 lines
6.5 KiB
C
161 lines
6.5 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);
|
|
}
|
|
|
|
/* ==========================================================================
|
|
* 春日影(MyGO!!!!! ver.) / MyGO!!!!!【原创歌曲】官方原版完整编配
|
|
* "なんで春日影やったの?!"
|
|
* 乐曲架构:
|
|
* Part 1: 乐奈吉他前奏 (Guitar Intro Riff)
|
|
* Part 2: 主歌 Verse A ("まだ誰も知らない...")
|
|
* Part 3: 预副歌 Pre-Chorus B ("踏み出す一歩が...")
|
|
* Part 4: 灵魂副歌 Chorus ("春の日差しに 包まれて...")
|
|
* Part 5: 乐奈标志性吉他间奏 (Guitar Solo)
|
|
* 吐音设计: 每个音符末尾精准留有 BUZZER_P 断音,保证音符清脆灵动不糊音
|
|
* ========================================================================== */
|
|
static const buzzer_tone_e buzzer_melody[] = {
|
|
/* ==================== Part 1: 乐奈吉他前奏 (Intro) ==================== */
|
|
/* 3 2 1 5_ | 6_ 1 2 3 2 - - */
|
|
BUZZER_M3, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_P,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_P,
|
|
BUZZER_L5, BUZZER_L5, BUZZER_P,
|
|
BUZZER_L6, BUZZER_L6, BUZZER_P,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_P,
|
|
BUZZER_M2, BUZZER_P,
|
|
BUZZER_M3, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P, BUZZER_P,
|
|
|
|
/* 3 2 1 5_ | 6_ 1 2 3 1 - - */
|
|
BUZZER_M3, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_P,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_P,
|
|
BUZZER_L5, BUZZER_L5, BUZZER_P,
|
|
BUZZER_L6, BUZZER_L6, BUZZER_P,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_P,
|
|
BUZZER_M2, BUZZER_P,
|
|
BUZZER_M3, BUZZER_P,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_M1, BUZZER_M1, BUZZER_M1, BUZZER_P, BUZZER_P,
|
|
|
|
/* ==================== Part 2: 主歌 Verse A ==================== */
|
|
/* "まだ誰も知らない" (3 3 3 2 1 2 3 5 3 | 2 1 2 -) */
|
|
BUZZER_M3, BUZZER_P, BUZZER_M3, BUZZER_P, BUZZER_M3,
|
|
BUZZER_M2, BUZZER_M1, BUZZER_M2, BUZZER_M3,
|
|
BUZZER_M5, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M1,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P,
|
|
|
|
/* "薄明かりの空に" (3 3 3 2 1 2 3 5 3 | 2 1 1 -) */
|
|
BUZZER_M3, BUZZER_P, BUZZER_M3, BUZZER_P, BUZZER_M3,
|
|
BUZZER_M2, BUZZER_M1, BUZZER_M2, BUZZER_M3,
|
|
BUZZER_M5, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M1,
|
|
BUZZER_M1, BUZZER_M1, BUZZER_M1, BUZZER_M1, BUZZER_P,
|
|
|
|
/* ==================== Part 3: 预副歌 Pre-Chorus B ==================== */
|
|
/* "踏み出す一歩が 怖くても" (6_ 1 2 3 2 1 2 3 | 5 3 2 1 2 -) */
|
|
BUZZER_L6, BUZZER_M1, BUZZER_M2,
|
|
BUZZER_M3, BUZZER_M2, BUZZER_M1,
|
|
BUZZER_M2, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M5, BUZZER_M3, BUZZER_M2, BUZZER_M1,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P,
|
|
|
|
/* "あなたとなら 行ける気がした" (6_ 1 2 3 2 1 | 2 3 5 6 5 3 2 -) */
|
|
BUZZER_L6, BUZZER_M1, BUZZER_M2,
|
|
BUZZER_M3, BUZZER_M2, BUZZER_M1, BUZZER_P,
|
|
BUZZER_M2, BUZZER_M3, BUZZER_M5, BUZZER_M6,
|
|
BUZZER_M5, BUZZER_M3,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P, BUZZER_P,
|
|
|
|
/* ==================== Part 4: 灵魂副歌 Chorus ==================== */
|
|
/* "春の日差しに 包まれて" (1' 7 6 5 3 5 6 | 5 3 2 1 2 -) */
|
|
BUZZER_H1, BUZZER_P, BUZZER_M7, BUZZER_M6,
|
|
BUZZER_M5, BUZZER_M3, BUZZER_M5, BUZZER_M6, BUZZER_P,
|
|
BUZZER_M5, BUZZER_M3,
|
|
BUZZER_M2, BUZZER_M1,
|
|
BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_M2, BUZZER_P,
|
|
|
|
/* "揺れる影 重なり合う" (1' 7 6 5 3 | 5 6 1' 2' 3' 2' -) */
|
|
BUZZER_H1, BUZZER_P, BUZZER_M7, BUZZER_M6,
|
|
BUZZER_M5, BUZZER_M3, BUZZER_P,
|
|
BUZZER_M5, BUZZER_M6,
|
|
BUZZER_H1, BUZZER_H2,
|
|
BUZZER_H3, BUZZER_H2, BUZZER_H2, BUZZER_H2, BUZZER_P,
|
|
|
|
/* "どうか消えないで" (1' 2' 3' 2' 1' 2' - -) */
|
|
BUZZER_H1, BUZZER_H2,
|
|
BUZZER_H3, BUZZER_H2,
|
|
BUZZER_H1, BUZZER_P,
|
|
BUZZER_H2, BUZZER_H2, BUZZER_H2, BUZZER_H2, BUZZER_H2, BUZZER_P,
|
|
|
|
/* "私たちが 見つけた光" (6 1' 2' 3' 2' 1' | 6 1' 2' 1' - - -) */
|
|
BUZZER_M6, BUZZER_H1, BUZZER_H2,
|
|
BUZZER_H3, BUZZER_H2, BUZZER_H1, BUZZER_P,
|
|
BUZZER_M6, BUZZER_H1, BUZZER_H2,
|
|
BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_P, BUZZER_P,
|
|
|
|
/* ==================== Part 5: 乐奈间奏 Solo (Guitar Solo) ==================== */
|
|
/* 3' - 2' 1' 6 | 1' 2' 3' 5' 3' - | 2' 3' 2' 1' 6_ 1' | 1' - - - */
|
|
BUZZER_H3, BUZZER_H3, BUZZER_P,
|
|
BUZZER_H2, BUZZER_H1, BUZZER_M6, BUZZER_P,
|
|
BUZZER_H1, BUZZER_H2, BUZZER_H3, BUZZER_H5,
|
|
BUZZER_H3, BUZZER_H3, BUZZER_H3, BUZZER_P,
|
|
BUZZER_H2, BUZZER_H3, BUZZER_H2, BUZZER_H1,
|
|
BUZZER_L6, BUZZER_H1,
|
|
BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, BUZZER_H1, // 终章长音收尾
|
|
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]);
|
|
}
|