有源蜂鸣器:由于本身存在信号源,因此通电就响。
无源蜂鸣器:由于本身无信号源,因此给不同频率的方波信号,可发出不同音调的声音。

有源蜂鸣器
有源蜂鸣器的驱动十分简单,只要通电就能响,但是只能以固定的音调发声。
案例以1ms为时基,设置蜂鸣器发声的时间即可。

演示视频:
无源蜂鸣器
由于有源蜂鸣器只能以特定的频率发声,只含有一种声调,因此想要使用蜂鸣器播放音乐,只能使用无源蜂鸣器,通过给定不同频率的方波信号,控制蜂鸣器发出不同的声调,再结合乐谱,即可播放音乐。
推荐使用带PWM功能的进行控制,【火烛】使用普通引脚进行控制,因此使用定时器配合生成PWM方波信号。
音度--音调 与 频率之间的关系(不含黑键)
通过查阅一些资料,可以得到以下对照表

如何实现任意频率的方波信号输出
// 先使用定时器11 设置一个10us的时基
Timer11_Init(0, TIM_CLOCK_1T, 10, TIM_us); // 10us定时
// 再编写一个方波处理函数,通过设置beep_Passive_Frequency(频率Hz),自动输出对应频率的方波信号
// 可能不太精准,但也能用
/**
* @name BEEP_Passive_Deal
* @brief 无源蜂鸣器处理函数 本例程使用10us
* @version 版本:v1.0
* @date 日期:2025-05-01
* @author 作者:四汐
* @note 注释:f=1(s)/T=1000(ms)/T --> T=1000(ms)/f
* 20Hz = 1000(ms)/T --> T=50
* 40Hz : T=25
* 定时器1ms 最大频率为1kHz, 定时器10us 最大 100kHz, 定时器100us 最大 10kHz, 定时器1us 最大 1MHz, 1000000 us = 1s
*/
void BEEP_Passive_Deal(void)
{
// 10us 100kHz 1,000,000us = 1s 100,000 T = 1s
static float T_cycle = 0;
T_cycle += 1.0;
if (beep_Passive_Frequency == 0)
{
T_cycle = 0.0;
BEEP_OFF();
}
else if (T_cycle >= ( Toggle_time/beep_Passive_Frequency) )
{
T_cycle = 0.0;
BEEP_Toggle();
}
}
了解简谱
这里以《两只老虎》为例 (本人对乐理并不精通,仅粗略了解一些)

可以看到左上角有一个 2/4,这个代表每个节拍(“|“区分节拍)进行了2分节,
比如一首60BPM(1分钟有60个节拍,即一节拍占时1秒)的曲子,一个节拍内应含有2个音符,每个音符为0.5秒,比如曲中“眼睛”对应的音符
而带有一个下划线的音符,会再进行一次2分,即4分音符,每个音符占0.25秒。
例如:两只老虎 12 31,对应0.25-0.25 0.25-0.25,即1秒
例如:跑得快 34 5,对应0.25-0.25 0.5,即1秒
了解完每个音符对应的时间(时值),再了解一下数字代表的音调是什么
0-7分别代表着:休止,do,re,mi,fa,so,la,si。
除了音调,还有音度,一般的中央C为4度,那么3度就是低音,2度就是倍低音,4度就是高音,5度就是倍高音。而数字下面带一个点,就说明该音调为低音音调。
如何播放音乐
了解完这些,对简单的曲谱 ,可以创建一个乐谱数组

在固定的周期内输出对应的音调,也能勉强听得出来曲调

那么,对于复杂一点的乐谱,这个函数貌似就无法满足了。
不仅需要处理音调、音度,还需要处理每一个音调的时值,才能使音乐更有韵律
对此,我简单写了一段曲谱,并编写了对应的处理函数


大家可以猜猜看是什么曲子,难度可能有点大(全损音质哈哈哈),但还是能够听得出来的嘿嘿。
演示视频: